socsvn commit: r224208 - soc2011/shm/TESLA/examples/ping

shm at FreeBSD.org shm at FreeBSD.org
Thu Jul 14 10:11:03 UTC 2011


Author: shm
Date: Thu Jul 14 10:11:00 2011
New Revision: 224208
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=224208

Log:
   * remerged from soc-g (missing part of the great merge)

Added:
  soc2011/shm/TESLA/examples/ping/
  soc2011/shm/TESLA/examples/ping/Makefile
  soc2011/shm/TESLA/examples/ping/ping.c
  soc2011/shm/TESLA/examples/ping/ping.spl
  soc2011/shm/TESLA/examples/ping/ping_assert.c
  soc2011/shm/TESLA/examples/ping/ping_assert.h

Added: soc2011/shm/TESLA/examples/ping/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2011/shm/TESLA/examples/ping/Makefile	Thu Jul 14 10:11:00 2011	(r224208)
@@ -0,0 +1,34 @@
+SPLC ?= ../../cfa/splc
+TESLA_CLANG ?= ../../kernel/tesla-clang
+OPTLEVEL ?= -O0
+CC = $(TESLA_CLANG)
+
+CFLAGS=-Wall -g -I../.. -I. $(OPTLEVEL)
+
+TESLALIBS=                                \
+	../../libtesla/tesla_state.o            \
+	../../libtesla/tesla_state_global.o     \
+	../../libtesla/tesla_state_perthread.o  \
+	../../libtesla/tesla_util.o
+
+.PHONY: all clean
+all: ping
+
+ping_automata.c ping_defs.h: ping.spl
+	$(SPLC) -t tesla -s ping ping.spl
+	cp ping.spec instrumentation.spec
+
+ping.o: ping.c
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+ping_assert.o: ping_assert.c ping_defs.h
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+ping_automata.o: ping_automata.c ping_defs.h
+	$(CC) -c $(CFLAGS) -o $@ $<
+
+ping: ping_assert.o ping_automata.o ping.o ${TESLALIBS} 
+	$(CC) -o $@ ping.o ping_automata.o ping_assert.o ${TESLALIBS} -lm -lipsec
+
+clean:
+	rm -f ping *.o

Added: soc2011/shm/TESLA/examples/ping/ping.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ soc2011/shm/TESLA/examples/ping/ping.c	Thu Jul 14 10:11:00 2011	(r224208)
@@ -0,0 +1,1726 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Muuss.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)ping.c	8.1 (Berkeley) 6/5/93";
+#endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sbin/ping/ping.c,v 1.112.10.1.4.1 2010/06/14 02:09:06 kensmith Exp $");
+
+/*
+ *			P I N G . C
+ *
+ * Using the Internet Control Message Protocol (ICMP) "ECHO" facility,
+ * measure round-trip-delays and packet loss across network paths.
+ *
+ * Author -
+ *	Mike Muuss
+ *	U. S. Army Ballistic Research Laboratory
+ *	December, 1983
+ *
+ * Status -
+ *	Public Domain.  Distribution Unlimited.
+ * Bugs -
+ *	More statistics could always be gathered.
+ *	This program has to run SUID to ROOT to access the ICMP socket.
+ */
+
+#include <sys/param.h>		/* NB: we rely on this for <sys/types.h> */
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/ip_var.h>
+#include <arpa/inet.h>
+
+#ifdef IPSEC
+#include <netipsec/ipsec.h>
+#endif /*IPSEC*/
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <math.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include <tesla/tesla.h>
+#include <tesla/tesla_state.h>
+#include "ping_defs.h"
+#include "ping_assert.h"
+
+#define	INADDR_LEN	((int)sizeof(in_addr_t))
+#define	TIMEVAL_LEN	((int)sizeof(struct tv32))
+#define	MASK_LEN	(ICMP_MASKLEN - ICMP_MINLEN)
+#define	TS_LEN		(ICMP_TSLEN - ICMP_MINLEN)
+#define	DEFDATALEN	56		/* default data length */
+#define	FLOOD_BACKOFF	20000		/* usecs to back off if F_FLOOD mode */
+					/* runs out of buffer space */
+#define	MAXIPLEN	(sizeof(struct ip) + MAX_IPOPTLEN)
+#define	MAXICMPLEN	(ICMP_ADVLENMIN + MAX_IPOPTLEN)
+#define	MAXWAIT		10000		/* max ms to wait for response */
+#define	MAXALARM	(60 * 60)	/* max seconds for alarm timeout */
+#define	MAXTOS		255
+
+#define	A(bit)		rcvd_tbl[(bit)>>3]	/* identify byte in array */
+#define	B(bit)		(1 << ((bit) & 0x07))	/* identify bit in byte */
+#define	SET(bit)	(A(bit) |= B(bit))
+#define	CLR(bit)	(A(bit) &= (~B(bit)))
+#define	TST(bit)	(A(bit) & B(bit))
+
+struct tv32 {
+	int32_t tv32_sec;
+	int32_t tv32_usec;
+};
+
+/* various options */
+int options;
+#define	F_FLOOD		0x0001
+#define	F_INTERVAL	0x0002
+#define	F_NUMERIC	0x0004
+#define	F_PINGFILLED	0x0008
+#define	F_QUIET		0x0010
+#define	F_RROUTE	0x0020
+#define	F_SO_DEBUG	0x0040
+#define	F_SO_DONTROUTE	0x0080
+#define	F_VERBOSE	0x0100
+#define	F_QUIET2	0x0200
+#define	F_NOLOOP	0x0400
+#define	F_MTTL		0x0800
+#define	F_MIF		0x1000
+#define	F_AUDIBLE	0x2000
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+#define F_POLICY	0x4000
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
+#define	F_TTL		0x8000
+#define	F_MISSED	0x10000
+#define	F_ONCE		0x20000
+#define	F_HDRINCL	0x40000
+#define	F_MASK		0x80000
+#define	F_TIME		0x100000
+#define	F_SWEEP		0x200000
+#define	F_WAITTIME	0x400000
+
+/*
+ * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
+ * number of received sequence numbers we can keep track of.  Change 128
+ * to 8192 for complete accuracy...
+ */
+#define	MAX_DUP_CHK	(8 * 128)
+int mx_dup_ck = MAX_DUP_CHK;
+char rcvd_tbl[MAX_DUP_CHK / 8];
+
+struct sockaddr_in whereto;	/* who to ping */
+int datalen = DEFDATALEN;
+int maxpayload;
+int s;				/* socket file descriptor */
+u_char outpackhdr[IP_MAXPACKET], *outpack;
+char BBELL = '\a';		/* characters written for MISSED and AUDIBLE */
+char BSPACE = '\b';		/* characters written for flood */
+char DOT = '.';
+char *hostname;
+char *shostname;
+int ident;			/* process id to identify our packets */
+int uid;			/* cached uid for micro-optimization */
+u_char icmp_type = ICMP_ECHO;
+u_char icmp_type_rsp = ICMP_ECHOREPLY;
+int phdr_len = 0;
+int send_len;
+
+/* counters */
+long nmissedmax;		/* max value of ntransmitted - nreceived - 1 */
+long npackets;			/* max packets to transmit */
+long nreceived;			/* # of packets we got back */
+long nrepeats;			/* number of duplicates */
+long ntransmitted;		/* sequence # for outbound packets = #sent */
+long snpackets;			/* max packets to transmit in one sweep */
+long snreceived;		/* # of packets we got back in this sweep */
+long sntransmitted;		/* # of packets we sent in this sweep */
+int sweepmax;			/* max value of payload in sweep */
+int sweepmin = 0;		/* start value of payload in sweep */
+int sweepincr = 1;		/* payload increment in sweep */
+int interval = 1000;		/* interval between packets, ms */
+int waittime = MAXWAIT;		/* timeout for each packet */
+long nrcvtimeout = 0;		/* # of packets we got back after waittime */
+
+/* timing */
+int timing;			/* flag to do timing */
+double tmin = 999999999.0;	/* minimum round trip time */
+double tmax = 0.0;		/* maximum round trip time */
+double tsum = 0.0;		/* sum of all times, for doing average */
+double tsumsq = 0.0;		/* sum of all times squared, for std. dev. */
+
+volatile sig_atomic_t finish_up;  /* nonzero if we've been told to finish up */
+volatile sig_atomic_t siginfo_p;
+
+static void fill(char *, char *);
+static u_short in_cksum(u_short *, int);
+static void check_status(void);
+static void finish(void) __dead2;
+static void pinger(void);
+static char *pr_addr(struct in_addr);
+static char *pr_ntime(n_time);
+static void pr_icmph(struct icmp *);
+static void pr_iph(struct ip *);
+static void pr_pack(char *, int, struct sockaddr_in *, struct timeval *);
+static void pr_retip(struct ip *);
+static void status(int);
+static void stopit(int);
+static void tvsub(struct timeval *, struct timeval *);
+static void usage(void) __dead2;
+
+int
+main(argc, argv)
+	int argc;
+	char *const *argv;
+{
+	struct sockaddr_in from, sock_in;
+	struct in_addr ifaddr;
+	struct timeval last, intvl;
+	struct iovec iov;
+	struct ip *ip;
+	struct msghdr msg;
+	struct sigaction si_sa;
+	size_t sz;
+	u_char *datap, packet[IP_MAXPACKET] __aligned(4);
+	char *ep, *source, *target, *payload;
+	struct hostent *hp;
+#ifdef IPSEC_POLICY_IPSEC
+	char *policy_in, *policy_out;
+#endif
+	struct sockaddr_in *to;
+	double t;
+	u_long alarmtimeout, ultmp;
+	int almost_done, ch, df, hold, i, icmp_len, mib[4], preload, sockerrno,
+	    tos, ttl;
+	char ctrl[CMSG_SPACE(sizeof(struct timeval))];
+	char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN];
+#ifdef IP_OPTIONS
+	char rspace[MAX_IPOPTLEN];	/* record route space */
+#endif
+	unsigned char loop, mttl;
+
+	payload = source = NULL;
+#ifdef IPSEC_POLICY_IPSEC
+	policy_in = policy_out = NULL;
+#endif
+
+	/*
+	 * Do the stuff that we need root priv's for *first*, and
+	 * then drop our setuid bit.  Save error reporting for
+	 * after arg parsing.
+	 */
+	s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+	sockerrno = errno;
+
+	setuid(getuid());
+	uid = getuid();
+
+	alarmtimeout = df = preload = tos = 0;
+
+	outpack = outpackhdr + sizeof(struct ip);
+	while ((ch = getopt(argc, argv,
+		"Aac:DdfG:g:h:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:"
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+		"P:"
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
+		)) != -1)
+	{
+		switch(ch) {
+		case 'A':
+			options |= F_MISSED;
+			break;
+		case 'a':
+			options |= F_AUDIBLE;
+			break;
+		case 'c':
+			ultmp = strtoul(optarg, &ep, 0);
+			if (*ep || ep == optarg || ultmp > LONG_MAX || !ultmp)
+				errx(EX_USAGE,
+				    "invalid count of packets to transmit: `%s'",
+				    optarg);
+			npackets = ultmp;
+			break;
+		case 'D':
+			options |= F_HDRINCL;
+			df = 1;
+			break;
+		case 'd':
+			options |= F_SO_DEBUG;
+			break;
+		case 'f':
+			if (uid) {
+				errno = EPERM;
+				err(EX_NOPERM, "-f flag");
+			}
+			options |= F_FLOOD;
+			setbuf(stdout, (char *)NULL);
+			break;
+		case 'G': /* Maximum packet size for ping sweep */
+			ultmp = strtoul(optarg, &ep, 0);
+			if (*ep || ep == optarg)
+				errx(EX_USAGE, "invalid packet size: `%s'",
+				    optarg);
+			if (uid != 0 && ultmp > DEFDATALEN) {
+				errno = EPERM;
+				err(EX_NOPERM,
+				    "packet size too large: %lu > %u",
+				    ultmp, DEFDATALEN);
+			}
+			options |= F_SWEEP;
+			sweepmax = ultmp;
+			break;
+		case 'g': /* Minimum packet size for ping sweep */
+			ultmp = strtoul(optarg, &ep, 0);
+			if (*ep || ep == optarg)
+				errx(EX_USAGE, "invalid packet size: `%s'",
+				    optarg);
+			if (uid != 0 && ultmp > DEFDATALEN) {
+				errno = EPERM;
+				err(EX_NOPERM,
+				    "packet size too large: %lu > %u",
+				    ultmp, DEFDATALEN);
+			}
+			options |= F_SWEEP;
+			sweepmin = ultmp;
+			break;
+		case 'h': /* Packet size increment for ping sweep */
+			ultmp = strtoul(optarg, &ep, 0);
+			if (*ep || ep == optarg || ultmp < 1)
+				errx(EX_USAGE, "invalid increment size: `%s'",
+				    optarg);
+			if (uid != 0 && ultmp > DEFDATALEN) {
+				errno = EPERM;
+				err(EX_NOPERM,
+				    "packet size too large: %lu > %u",
+				    ultmp, DEFDATALEN);
+			}
+			options |= F_SWEEP;
+			sweepincr = ultmp;
+			break;
+		case 'I':		/* multicast interface */
+			if (inet_aton(optarg, &ifaddr) == 0)
+				errx(EX_USAGE,
+				    "invalid multicast interface: `%s'",
+				    optarg);
+			options |= F_MIF;
+			break;
+		case 'i':		/* wait between sending packets */
+			t = strtod(optarg, &ep) * 1000.0;
+			if (*ep || ep == optarg || t > (double)INT_MAX)
+				errx(EX_USAGE, "invalid timing interval: `%s'",
+				    optarg);
+			options |= F_INTERVAL;
+			interval = (int)t;
+			if (uid && interval < 1000) {
+				errno = EPERM;
+				err(EX_NOPERM, "-i interval too short");
+			}
+			break;
+		case 'L':
+			options |= F_NOLOOP;
+			loop = 0;
+			break;
+		case 'l':
+			ultmp = strtoul(optarg, &ep, 0);
+			if (*ep || ep == optarg || ultmp > INT_MAX)
+				errx(EX_USAGE,
+				    "invalid preload value: `%s'", optarg);
+			if (uid) {
+				errno = EPERM;
+				err(EX_NOPERM, "-l flag");
+			}
+			preload = ultmp;
+			break;
+		case 'M':
+			switch(optarg[0]) {
+			case 'M':
+			case 'm':
+				options |= F_MASK;
+				break;
+			case 'T':
+			case 't':
+				options |= F_TIME;
+				break;
+			default:
+				errx(EX_USAGE, "invalid message: `%c'", optarg[0]);
+				break;
+			}
+			break;
+		case 'm':		/* TTL */
+			ultmp = strtoul(optarg, &ep, 0);
+			if (*ep || ep == optarg || ultmp > MAXTTL)
+				errx(EX_USAGE, "invalid TTL: `%s'", optarg);
+			ttl = ultmp;
+			options |= F_TTL;
+			break;
+		case 'n':
+			options |= F_NUMERIC;
+			break;
+		case 'o':
+			options |= F_ONCE;
+			break;
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+		case 'P':
+			options |= F_POLICY;
+			if (!strncmp("in", optarg, 2))
+				policy_in = strdup(optarg);
+			else if (!strncmp("out", optarg, 3))
+				policy_out = strdup(optarg);
+			else
+				errx(1, "invalid security policy");
+			break;
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
+		case 'p':		/* fill buffer with user pattern */
+			options |= F_PINGFILLED;
+			payload = optarg;
+			break;
+		case 'Q':
+			options |= F_QUIET2;
+			break;
+		case 'q':
+			options |= F_QUIET;
+			break;
+		case 'R':
+			options |= F_RROUTE;
+			break;
+		case 'r':
+			options |= F_SO_DONTROUTE;
+			break;
+		case 'S':
+			source = optarg;
+			break;
+		case 's':		/* size of packet to send */
+			ultmp = strtoul(optarg, &ep, 0);
+			if (*ep || ep == optarg)
+				errx(EX_USAGE, "invalid packet size: `%s'",
+				    optarg);
+			if (uid != 0 && ultmp > DEFDATALEN) {
+				errno = EPERM;
+				err(EX_NOPERM,
+				    "packet size too large: %lu > %u",
+				    ultmp, DEFDATALEN);
+			}
+			datalen = ultmp;
+			break;
+		case 'T':		/* multicast TTL */
+			ultmp = strtoul(optarg, &ep, 0);
+			if (*ep || ep == optarg || ultmp > MAXTTL)
+				errx(EX_USAGE, "invalid multicast TTL: `%s'",
+				    optarg);
+			mttl = ultmp;
+			options |= F_MTTL;
+			break;
+		case 't':
+			alarmtimeout = strtoul(optarg, &ep, 0);
+			if ((alarmtimeout < 1) || (alarmtimeout == ULONG_MAX))
+				errx(EX_USAGE, "invalid timeout: `%s'",
+				    optarg);
+			if (alarmtimeout > MAXALARM)
+				errx(EX_USAGE, "invalid timeout: `%s' > %d",
+				    optarg, MAXALARM);
+			alarm((int)alarmtimeout);
+			break;
+		case 'v':
+			options |= F_VERBOSE;
+			break;
+		case 'W':		/* wait ms for answer */
+			t = strtod(optarg, &ep);
+			if (*ep || ep == optarg || t > (double)INT_MAX)
+				errx(EX_USAGE, "invalid timing interval: `%s'",
+				    optarg);
+			options |= F_WAITTIME;
+			waittime = (int)t;
+			break;
+		case 'z':
+			options |= F_HDRINCL;
+			ultmp = strtoul(optarg, &ep, 0);
+			if (*ep || ep == optarg || ultmp > MAXTOS)
+				errx(EX_USAGE, "invalid TOS: `%s'", optarg);
+			tos = ultmp;
+			break;
+		default:
+			usage();
+		}
+	}
+
+	if (argc - optind != 1)
+		usage();
+	target = argv[optind];
+
+	switch (options & (F_MASK|F_TIME)) {
+	case 0: break;
+	case F_MASK:
+		icmp_type = ICMP_MASKREQ;
+		icmp_type_rsp = ICMP_MASKREPLY;
+		phdr_len = MASK_LEN;
+		if (!(options & F_QUIET))
+			(void)printf("ICMP_MASKREQ\n");
+		break;
+	case F_TIME:
+		icmp_type = ICMP_TSTAMP;
+		icmp_type_rsp = ICMP_TSTAMPREPLY;
+		phdr_len = TS_LEN;
+		if (!(options & F_QUIET))
+			(void)printf("ICMP_TSTAMP\n");
+		break;
+	default:
+		errx(EX_USAGE, "ICMP_TSTAMP and ICMP_MASKREQ are exclusive.");
+		break;
+	}
+	icmp_len = sizeof(struct ip) + ICMP_MINLEN + phdr_len;
+	if (options & F_RROUTE)
+		icmp_len += MAX_IPOPTLEN;
+	maxpayload = IP_MAXPACKET - icmp_len;
+	if (datalen > maxpayload)
+		errx(EX_USAGE, "packet size too large: %d > %d", datalen,
+		    maxpayload);
+	send_len = icmp_len + datalen;
+	datap = &outpack[ICMP_MINLEN + phdr_len + TIMEVAL_LEN];
+	if (options & F_PINGFILLED) {
+		fill((char *)datap, payload);
+	}
+	if (source) {
+		bzero((char *)&sock_in, sizeof(sock_in));
+		sock_in.sin_family = AF_INET;
+		if (inet_aton(source, &sock_in.sin_addr) != 0) {
+			shostname = source;
+		} else {
+			hp = gethostbyname2(source, AF_INET);
+			if (!hp)
+				errx(EX_NOHOST, "cannot resolve %s: %s",
+				    source, hstrerror(h_errno));
+
+			sock_in.sin_len = sizeof sock_in;
+			if ((unsigned)hp->h_length > sizeof(sock_in.sin_addr) ||
+			    hp->h_length < 0)
+				errx(1, "gethostbyname2: illegal address");
+			memcpy(&sock_in.sin_addr, hp->h_addr_list[0],
+			    sizeof(sock_in.sin_addr));
+			(void)strncpy(snamebuf, hp->h_name,
+			    sizeof(snamebuf) - 1);
+			snamebuf[sizeof(snamebuf) - 1] = '\0';
+			shostname = snamebuf;
+		}
+		if (bind(s, (struct sockaddr *)&sock_in, sizeof sock_in) == -1)
+			err(1, "bind");
+	}
+
+	bzero(&whereto, sizeof(whereto));
+	to = &whereto;
+	to->sin_family = AF_INET;
+	to->sin_len = sizeof *to;
+	if (inet_aton(target, &to->sin_addr) != 0) {
+		hostname = target;
+	} else {
+		hp = gethostbyname2(target, AF_INET);
+		if (!hp)
+			errx(EX_NOHOST, "cannot resolve %s: %s",
+			    target, hstrerror(h_errno));
+
+		if ((unsigned)hp->h_length > sizeof(to->sin_addr))
+			errx(1, "gethostbyname2 returned an illegal address");
+		memcpy(&to->sin_addr, hp->h_addr_list[0], sizeof to->sin_addr);
+		(void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1);
+		hnamebuf[sizeof(hnamebuf) - 1] = '\0';
+		hostname = hnamebuf;
+	}
+
+	if (options & F_FLOOD && options & F_INTERVAL)
+		errx(EX_USAGE, "-f and -i: incompatible options");
+
+	if (options & F_FLOOD && IN_MULTICAST(ntohl(to->sin_addr.s_addr)))
+		errx(EX_USAGE,
+		    "-f flag cannot be used with multicast destination");
+	if (options & (F_MIF | F_NOLOOP | F_MTTL)
+	    && !IN_MULTICAST(ntohl(to->sin_addr.s_addr)))
+		errx(EX_USAGE,
+		    "-I, -L, -T flags cannot be used with unicast destination");
+
+	if (datalen >= TIMEVAL_LEN)	/* can we time transfer */
+		timing = 1;
+
+	if (!(options & F_PINGFILLED))
+		for (i = TIMEVAL_LEN; i < datalen; ++i)
+			*datap++ = i;
+
+	ident = getpid() & 0xFFFF;
+
+	if (s < 0) {
+		errno = sockerrno;
+		err(EX_OSERR, "socket");
+	}
+	hold = 1;
+	if (options & F_SO_DEBUG)
+		(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold,
+		    sizeof(hold));
+	if (options & F_SO_DONTROUTE)
+		(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold,
+		    sizeof(hold));
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+	if (options & F_POLICY) {
+		char *buf;
+		if (policy_in != NULL) {
+			buf = ipsec_set_policy(policy_in, strlen(policy_in));
+			if (buf == NULL)
+				errx(EX_CONFIG, "%s", ipsec_strerror());
+			if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY,
+					buf, ipsec_get_policylen(buf)) < 0)
+				err(EX_CONFIG,
+				    "ipsec policy cannot be configured");
+			free(buf);
+		}
+
+		if (policy_out != NULL) {
+			buf = ipsec_set_policy(policy_out, strlen(policy_out));
+			if (buf == NULL)
+				errx(EX_CONFIG, "%s", ipsec_strerror());
+			if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY,
+					buf, ipsec_get_policylen(buf)) < 0)
+				err(EX_CONFIG,
+				    "ipsec policy cannot be configured");
+			free(buf);
+		}
+	}
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
+
+	if (options & F_HDRINCL) {
+		ip = (struct ip*)outpackhdr;
+		if (!(options & (F_TTL | F_MTTL))) {
+			mib[0] = CTL_NET;
+			mib[1] = PF_INET;
+			mib[2] = IPPROTO_IP;
+			mib[3] = IPCTL_DEFTTL;
+			sz = sizeof(ttl);
+			if (sysctl(mib, 4, &ttl, &sz, NULL, 0) == -1)
+				err(1, "sysctl(net.inet.ip.ttl)");
+		}
+		setsockopt(s, IPPROTO_IP, IP_HDRINCL, &hold, sizeof(hold));
+		ip->ip_v = IPVERSION;
+		ip->ip_hl = sizeof(struct ip) >> 2;
+		ip->ip_tos = tos;
+		ip->ip_id = 0;
+		ip->ip_off = df ? IP_DF : 0;
+		ip->ip_ttl = ttl;
+		ip->ip_p = IPPROTO_ICMP;
+		ip->ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY;
+		ip->ip_dst = to->sin_addr;
+        }
+	/* record route option */
+	if (options & F_RROUTE) {
+#ifdef IP_OPTIONS
+		bzero(rspace, sizeof(rspace));
+		rspace[IPOPT_OPTVAL] = IPOPT_RR;
+		rspace[IPOPT_OLEN] = sizeof(rspace) - 1;
+		rspace[IPOPT_OFFSET] = IPOPT_MINOFF;
+		rspace[sizeof(rspace) - 1] = IPOPT_EOL;
+		if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace,
+		    sizeof(rspace)) < 0)
+			err(EX_OSERR, "setsockopt IP_OPTIONS");
+#else
+		errx(EX_UNAVAILABLE,
+		    "record route not available in this implementation");
+#endif /* IP_OPTIONS */
+	}
+
+	if (options & F_TTL) {
+		if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl,
+		    sizeof(ttl)) < 0) {
+			err(EX_OSERR, "setsockopt IP_TTL");
+		}
+	}
+	if (options & F_NOLOOP) {
+		if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
+		    sizeof(loop)) < 0) {
+			err(EX_OSERR, "setsockopt IP_MULTICAST_LOOP");
+		}
+	}
+	if (options & F_MTTL) {
+		if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &mttl,
+		    sizeof(mttl)) < 0) {
+			err(EX_OSERR, "setsockopt IP_MULTICAST_TTL");
+		}
+	}
+	if (options & F_MIF) {
+		if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &ifaddr,
+		    sizeof(ifaddr)) < 0) {
+			err(EX_OSERR, "setsockopt IP_MULTICAST_IF");
+		}
+	}
+#ifdef SO_TIMESTAMP
+	{ int on = 1;
+	if (setsockopt(s, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)) < 0)
+		err(EX_OSERR, "setsockopt SO_TIMESTAMP");
+	}
+#endif
+	if (sweepmax) {
+		if (sweepmin >= sweepmax)
+			errx(EX_USAGE, "Maximum packet size must be greater than the minimum packet size");
+
+		if (datalen != DEFDATALEN)
+			errx(EX_USAGE, "Packet size and ping sweep are mutually exclusive");
+
+		if (npackets > 0) {
+			snpackets = npackets;
+			npackets = 0;
+		} else
+			snpackets = 1;
+		datalen = sweepmin;
+		send_len = icmp_len + sweepmin;
+	}
+	if (options & F_SWEEP && !sweepmax) 
+		errx(EX_USAGE, "Maximum sweep size must be specified");
+
+	/*
+	 * When pinging the broadcast address, you can get a lot of answers.
+	 * Doing something so evil is useful if you are trying to stress the
+	 * ethernet, or just want to fill the arp cache to get some stuff for
+	 * /etc/ethers.  But beware: RFC 1122 allows hosts to ignore broadcast
+	 * or multicast pings if they wish.
+	 */
+
+	/*
+	 * XXX receive buffer needs undetermined space for mbuf overhead
+	 * as well.
+	 */
+	hold = IP_MAXPACKET + 128;
+	(void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold,
+	    sizeof(hold));
+	if (uid == 0)
+		(void)setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&hold,
+		    sizeof(hold));
+
+	if (to->sin_family == AF_INET) {
+		(void)printf("PING %s (%s)", hostname,
+		    inet_ntoa(to->sin_addr));
+		if (source)
+			(void)printf(" from %s", shostname);
+		if (sweepmax)
+			(void)printf(": (%d ... %d) data bytes\n",
+			    sweepmin, sweepmax);
+		else 
+			(void)printf(": %d data bytes\n", datalen);
+		
+	} else {
+		if (sweepmax)
+			(void)printf("PING %s: (%d ... %d) data bytes\n",
+			    hostname, sweepmin, sweepmax);
+		else
+			(void)printf("PING %s: %d data bytes\n", hostname, datalen);
+	}
+
+	/*
+	 * Use sigaction() instead of signal() to get unambiguous semantics,
+	 * in particular with SA_RESTART not set.
+	 */
+
+	sigemptyset(&si_sa.sa_mask);
+	si_sa.sa_flags = 0;
+
+	si_sa.sa_handler = stopit;
+	if (sigaction(SIGINT, &si_sa, 0) == -1) {
+		err(EX_OSERR, "sigaction SIGINT");
+	}
+
+	si_sa.sa_handler = status;
+	if (sigaction(SIGINFO, &si_sa, 0) == -1) {
+		err(EX_OSERR, "sigaction");
+	}
+
+        if (alarmtimeout > 0) {
+		si_sa.sa_handler = stopit;
+		if (sigaction(SIGALRM, &si_sa, 0) == -1)
+			err(EX_OSERR, "sigaction SIGALRM");
+        }
+
+	bzero(&msg, sizeof(msg));
+	msg.msg_name = (caddr_t)&from;
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+#ifdef SO_TIMESTAMP
+	msg.msg_control = (caddr_t)ctrl;
+#endif
+	iov.iov_base = packet;
+	iov.iov_len = IP_MAXPACKET;
+
+  ping_init(TESLA_SCOPE_GLOBAL);
+
+	if (preload == 0)
+		pinger();		/* send the first ping */
+	else {
+		if (npackets != 0 && preload > npackets)
+			preload = npackets;
+		while (preload--)	/* fire off them quickies */
+			pinger();
+	}
+	(void)gettimeofday(&last, NULL);
+
+	if (options & F_FLOOD) {
+		intvl.tv_sec = 0;
+		intvl.tv_usec = 10000;
+	} else {
+		intvl.tv_sec = interval / 1000;
+		intvl.tv_usec = interval % 1000 * 1000;
+	}
+
+	almost_done = 0;
+	while (!finish_up) {
+		struct timeval now, timeout;
+		fd_set rfds;
+		int cc, n;
+
+		check_status();
+		if ((unsigned)s >= FD_SETSIZE)
+			errx(EX_OSERR, "descriptor too large");
+		FD_ZERO(&rfds);
+		FD_SET(s, &rfds);
+		(void)gettimeofday(&now, NULL);
+		timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;
+		timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;
+		while (timeout.tv_usec < 0) {
+			timeout.tv_usec += 1000000;
+			timeout.tv_sec--;
+		}
+		while (timeout.tv_usec >= 1000000) {
+			timeout.tv_usec -= 1000000;
+			timeout.tv_sec++;
+		}
+		if (timeout.tv_sec < 0)
+			timeout.tv_sec = timeout.tv_usec = 0;
+		n = select(s + 1, &rfds, NULL, NULL, &timeout);
+		if (n < 0)
+			continue;	/* Must be EINTR. */
+		if (n == 1) {
+			struct timeval *tv = NULL;
+#ifdef SO_TIMESTAMP
+			struct cmsghdr *cmsg = (struct cmsghdr *)&ctrl;
+
+			msg.msg_controllen = sizeof(ctrl);
+#endif
+			msg.msg_namelen = sizeof(from);
+			if ((cc = recvmsg(s, &msg, 0)) < 0) {
+				if (errno == EINTR)
+					continue;
+				warn("recvmsg");
+				continue;
+			}
+#ifdef SO_TIMESTAMP
+			if (cmsg->cmsg_level == SOL_SOCKET &&
+			    cmsg->cmsg_type == SCM_TIMESTAMP &&
+			    cmsg->cmsg_len == CMSG_LEN(sizeof *tv)) {
+				/* Copy to avoid alignment problems: */
+				memcpy(&now, CMSG_DATA(cmsg), sizeof(now));
+				tv = &now;
+			}
+#endif
+			if (tv == NULL) {
+				(void)gettimeofday(&now, NULL);
+				tv = &now;
+			}
+			pr_pack((char *)packet, cc, &from, tv);
+			if ((options & F_ONCE && nreceived) ||
+			    (npackets && nreceived >= npackets))
+				break;
+		}
+		if (n == 0 || options & F_FLOOD) {
+			if (sweepmax && sntransmitted == snpackets) {
+				for (i = 0; i < sweepincr ; ++i) 
+					*datap++ = i;
+				datalen += sweepincr;
+				if (datalen > sweepmax)
+					break;
+				send_len = icmp_len + datalen;
+				sntransmitted = 0;
+			} 
+			if (!npackets || ntransmitted < npackets)
+				pinger();
+			else {
+				if (almost_done)
+					break;
+				almost_done = 1;
+				intvl.tv_usec = 0;
+				if (nreceived) {
+					intvl.tv_sec = 2 * tmax / 1000;
+					if (!intvl.tv_sec)
+						intvl.tv_sec = 1;
+				} else {
+					intvl.tv_sec = waittime / 1000;
+					intvl.tv_usec = waittime % 1000 * 1000;
+				}
+			}
+			(void)gettimeofday(&last, NULL);
+			if (ntransmitted - nreceived - 1 > nmissedmax) {
+				nmissedmax = ntransmitted - nreceived - 1;
+				if (options & F_MISSED)
+					(void)write(STDOUT_FILENO, &BBELL, 1);
+			}
+		}
+	}
+	finish();
+	/* NOTREACHED */
+	exit(0);	/* Make the compiler happy */
+}
+
+/*
+ * stopit --
+ *	Set the global bit that causes the main loop to quit.
+ * Do NOT call finish() from here, since finish() does far too much
+ * to be called from a signal handler.
+ */
+void
+stopit(sig)
+	int sig __unused;
+{
+
+	/*
+	 * When doing reverse DNS lookups, the finish_up flag might not
+	 * be noticed for a while.  Just exit if we get a second SIGINT.
+	 */
+	if (!(options & F_NUMERIC) && finish_up)
+		_exit(nreceived ? 0 : 2);
+	finish_up = 1;
+}
+
+/*
+ * pinger --
+ *	Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
+ * will be added on by the kernel.  The ID field is our UNIX process ID,
+ * and the sequence number is an ascending integer.  The first TIMEVAL_LEN
+ * bytes of the data portion are used to hold a UNIX "timeval" struct in
+ * host byte-order, to compute the round-trip time.
+ */
+static void
+pinger(void)
+{
+	struct timeval now;
+	struct tv32 tv32;
+	struct ip *ip;
+	struct icmp *icp;
+	int cc, i;
+	u_char *packet;
+
+	packet = outpack;
+	icp = (struct icmp *)outpack;
+	icp->icmp_type = icmp_type;
+	icp->icmp_code = 0;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-soc-all mailing list