/*
 * Multi Ping includes
 *
 * (c) Pittsburgh Supercomputing Center, Matthew B Mathis, 1992.
 * All rights reserved.   See COPYRIGHT.h for additional information.
 */

#ifdef CRAY
#include "craytypes.h"
#include <netinet/udp_var.h>
#include <fcntl.h>
#include <sys/cpu.h>
#include <sys/category.h>
#else /* ! CRAY */
#define STRUCTALIGN(type, ptr, offset) (type)(ptr)
#define ip32o ip
#define icmp32o icmp
#define udphdr32o udphdr
#define SIZEOFstructip sizeof(struct ip)
#endif /* CRAY */

#define NOERROR(val,msg) {if (((int)(val)) < 0) {perror(msg);exit(1);}}
#define NOTNULL(val,msg) {if (!(val)) {fprintf(stderr,msg);exit(1);}}
#define USEC(st,fi) (((fi)->tv_sec-(st)->tv_sec)*1000000+ \
		((fi)->tv_usec-(st)->tv_usec))

#define SHORT(val)	((val) & 0xFFFF)
#define NEG(val)	((val) & 0x8000)	/* Sign of an unsigned int16 */
#define	SEQ_LT(a,b)	(NEG((a)-(b)))
#define	SEQ_LEQ(a,b)	(!NEG((b)-(a)))
#define	SEQ_GT(a,b)	(NEG((b)-(a)))
#define	SEQ_GEQ(a,b)	(!NEG((a)-(b)))

/* The classical definitions are as follows */
#if 0
#define	SEQ_LT(a,b)	((int)((a)-(b)) < 0)
#define	SEQ_LEQ(a,b)	((int)((a)-(b)) <= 0)
#define	SEQ_GT(a,b)	((int)((a)-(b)) > 0)
#define	SEQ_GEQ(a,b)	((int)((a)-(b)) >= 0)
#endif


/************** canonical signal functions ************
 * "The nice thing about standards, is that there are so many to choose from"
 * If anybody can suggest a better way to do this, I am open to suggestions.
 */


     /* Our goal is simple, we need recvfrom() to get timed out by
      * SIGALRM. Under 4.2BSD and 4.3BSD the state of interruptability,
      * whether defined by sigvec() and SV_INTERRUPT or sigaction() and
      * SA_INTERRUPT/SA_RESTART (opposites) was irrelevent, as recvfrom()
      * would not be restarted in any case. Under 4.4BSD, however recvfrom()
      * becomes restartable so it is important to ensure interruptability.
      *
      * A previous version of this code incorrectly used SV_INTERRUPT
      * where SA_INTERRUPT was meant, causing problems on systems where
      * SA_INTERRUPT did not exist and SV_INTERRUPT had the same value
      * as SA_RESTART!
      */ 

#if HAVE_SIGACTION
/*  We have POSIX sigaction() semantics. Some such systems, like SunOS,
 *  require explicit requests for interruptability (SA_INTERRUPT), though
 *  under POSIX that is the default.
 */
# ifndef SA_INTERRUPT
#  define SA_INTERRUPT 0
# endif
#  define MP_SIGNAL(sig, fcn) {struct sigaction sa, osa; \
   sigemptyset(&sa.sa_mask); sa.sa_handler = fcn; sa.sa_flags = SA_INTERRUPT; \
   NOERROR(sigaction(sig,&sa,&osa),"MP_SIGNAL");}
#  define MP_RESIGNAL(sig, fcn) /* Noop */
#  define MP_SIG_TYPE "Signals are POSIX style (sigaction)"
#else
# define MP_SIGNAL(sig, fcn) NOERROR(signal(sig, fcn), "MP_SIGNAL");
# define MP_RESIGNAL(sig, fcn) MP_SIGNAL(sig, fcn)
# define MP_SIG_TYPE "Signals are old style"
#endif

#ifdef								SYSV_SIGNALS
#define MP_SIGNAL(sig, fcn) NOERROR(signal(sig, fcn), "MP_SIGNAL");
#define MP_RESIGNAL(sig, fcn) /* Noop */
#define MP_SIG_TYPE "Signals are SYSV style"
#endif

#ifndef MP_EXTERN
#define MP_EXTERN extern
#else
char sig_type[] = MP_SIG_TYPE;		/* strings <cmd> | fgrep Signals */
#endif

/* prototypes */
void crackip (u_char *);
void setthrust();
int setroute(int sock, int mode, int rlen, struct sockaddr_in *route, int rr);


/* globals used by crackip(buff) to indicate parts of the message */
/* In all cases zero indicates not found, in order of increasing address */
MP_EXTERN	struct ip	*cip;		/* IP header */
MP_EXTERN	u_char		*cipopt;	/* options */
MP_EXTERN	int		cipolen;	/* option length (bytes) */
MP_EXTERN	struct icmp32o	*cicmp;		/* icmp message */
MP_EXTERN	struct ip32o	*cip2;		/* IP that provoked an icmp error */
MP_EXTERN	u_char		*cipopt2;	/* options within the error */
MP_EXTERN	int		cipolen2;	/* option length */
MP_EXTERN	u_char		*cipclient;	/* client data */

/* global used by netprintf */
extern int numeric;				/* 1 -> suppress namelookups */

/* globals used by setroute() */
#define MAXOPTS 40	/* (15-5)*4 bytes */
#define MAXROUTE 20     /* But only if we can do one hop at a time */
MP_EXTERN struct sockaddr_in route[MAXROUTE];	/* The requested route */
