lasttime = 0;
main(argc, argv)	int argc;	char **argv;{	extern int errno, optind;	extern char *optarg;	struct timeval timeout;	struct hostent *hp;	struct sockaddr_in *to;	struct protoent *proto;	struct in_addr saddr;	register int i;	int ch, hold = 1, packlen, preload;	int maxsize, maxsizelen, fdmasks;	u_char *datap, *packet;	char *target, hnamebuf[MAXHOSTNAMELEN];	u_char ttl = MAXTTL, loop = 1, df = 0;	int tos = 0;#ifdef IP_OPTIONS	char rspace[3 + 4 * NROUTES + 1];	/* record route space */#endif	fd_set *fdmaskp;	if (!(proto = getprotobyname("icmp")))		errx(1, "unknown protocol icmp");	if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0)		err(1, "socket");	/* revoke privs */	seteuid(getuid());	setuid(getuid());	preload = 0;	datap = &outpack[8 + sizeof(struct tvi)];	while ((ch = getopt(argc, argv, "DI:LRS:c:dfh:i:l:np:qrs:T:t:vw:")) != -1)		switch(ch) {		case 'c':			npackets = strtol(optarg, 0, NULL);			if (npackets <= 0)				errx(1, "bad number of packets to transmit: %s",				    optarg);			break;		case 'D':			options |= F_HDRINCL;			df = -1;			break;		case 'd':			options |= F_SO_DEBUG;			break;		case 'f':			if (getuid())				errx(1, "%s", strerror(EPERM));			options |= F_FLOOD;			setbuf(stdout, (char *)NULL);			break;		case 'I':		case 'S':	/* deprecated */			if (inet_aton(optarg, &saddr) == 0) {				if ((hp = gethostbyname(optarg)) == NULL)					errx(1, "bad interface address: %s",					     optarg);				memcpy(&saddr, hp->h_addr, sizeof(saddr));			}			options |= F_SADDR;			break;		case 'i':		/* wait between sending packets */			interval = strtol(optarg, NULL, 0);			if (interval <= 0)				errx(1, "bad timing interval: %s", optarg);			options |= F_INTERVAL;			break;		case 'L':			moptions |= MULTICAST_NOLOOP;			loop = 0;			break;		case 'l':			if (getuid())				errx(1, "%s", strerror(EPERM));			preload = strtol(optarg, NULL, 0);			if (preload < 0)				errx(1, "bad preload value: %s", optarg);			break;		case 'n':			options |= F_NUMERIC;			break;		case 'p':		/* fill buffer with user pattern */			options |= F_PINGFILLED;			fill((char *)datap, optarg);				break;		case 'q':			options |= F_QUIET;			break;		case 'R':			options |= F_RROUTE;			break;		case 'r':			options |= F_SO_DONTROUTE;			break;		case 's':		/* size of packet to send */			datalen = strtol(optarg, NULL, 0);			if (datalen <= 0)				errx(1, "bad packet size: %s", optarg);			if (datalen > MAXPACKET)				errx(1, "packet size too large: %s", optarg);			break;		case 'T':			options |= F_HDRINCL;			tos = strtoul(optarg, NULL, 0);			if (tos > 0xFF)				errx(1, "bad tos value: %s", optarg);			break;		case 't':			options |= F_TTL;			ttl = strtol(optarg, NULL, 0);			if (ttl <= 0)				errx(1, "bad ttl value: %s", optarg);			if (ttl > 255)				errx(1, "ttl value too large: %s", optarg);			break;		case 'v':			options |= F_VERBOSE;			break;		case 'w':			maxwait = strtol(optarg, NULL, 0);			if (maxwait <= 0)				errx(1, "bad maxwait value: %s", optarg);			break;		default:			usage();		}	argc -= optind;	argv += optind;	if (argc != 1)		usage();	target = *argv;	memset(&whereto, 0, sizeof(struct sockaddr));	to = (struct sockaddr_in *)&whereto;	to->sin_len = sizeof(struct sockaddr_in);	to->sin_family = AF_INET;	if (inet_aton(target, &to->sin_addr) != 0)		hostname = target;	else {		hp = gethostbyname(target);		if (!hp)			errx(1, "unknown host: %s", target);		to->sin_family = hp->h_addrtype;		memcpy(&to->sin_addr, hp->h_addr, hp->h_length);		(void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1);		hnamebuf[sizeof(hnamebuf) - 1] = '\0';		hostname = hnamebuf;	}	if (options & F_FLOOD && options & F_INTERVAL)		errx(1, "-f and -i options are incompatible");	if (datalen >= sizeof(struct tvi))	/* can we time transfer */		timing = 1;	packlen = datalen + MAXIPLEN + MAXICMPLEN;	if (!(packet = (u_char *)malloc((u_int)packlen)))		err(1, "malloc");	if (!(options & F_PINGFILLED))		for (i = 8 + sizeof(struct tvi); i < datalen; ++i)			*datap++ = i;	ident = getpid() & 0xFFFF;	if (options & F_SADDR) {		if (IN_MULTICAST(ntohl(to->sin_addr.s_addr)))			moptions |= MULTICAST_IF;		else {			memset(&whence, 0, sizeof(whence));			whence.sin_len = sizeof(whence);			whence.sin_family = AF_INET;			memcpy(&whence.sin_addr.s_addr, &saddr, sizeof(saddr));			if (bind(s, (struct sockaddr*)&whence,			    sizeof(whence)) < 0)				err(1, "bind");		}	}	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));	if (options & F_TTL) {		if (IN_MULTICAST(ntohl(to->sin_addr.s_addr))) 		    moptions |= MULTICAST_TTL;		else		    options |= F_HDRINCL;	}	if (options & F_RROUTE && options & F_HDRINCL)		errx(1, "-R option and -D or -T, or -t to unicast destinations"		     " are incompatible");	if (options & F_HDRINCL) {		struct ip *ip = (struct ip*)outpackhdr;		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 = htons(df?IP_DF:0);		ip->ip_ttl = ttl;		ip->ip_p = proto->p_proto;		ip->ip_src.s_addr = INADDR_ANY;		ip->ip_dst = to->sin_addr;	}	/* record route option */	if (options & F_RROUTE) {		if (IN_MULTICAST(ntohl(to->sin_addr.s_addr)))			errx(1, "record route not valid to multicast destinations");#ifdef IP_OPTIONS		rspace[IPOPT_OPTVAL] = IPOPT_RR;		rspace[IPOPT_OLEN] = sizeof(rspace)-1;		rspace[IPOPT_OFFSET] = IPOPT_MINOFF;		if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace,		    sizeof(rspace)) < 0) {			perror("ping: record route");			exit(1);		}#else		errx(1, "record route not available in this implementation");#endif /* IP_OPTIONS */	}	if ((moptions & MULTICAST_NOLOOP) &&	    setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,		       sizeof(loop)) < 0)		err(1, "setsockopt IP_MULTICAST_LOOP");	if ((moptions & MULTICAST_TTL) &&	    setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,		       sizeof(ttl)) < 0)		err(1, "setsockopt IP_MULTICAST_TTL");	if ((moptions & MULTICAST_IF) &&	    setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &saddr,		       sizeof(saddr)) < 0)		err(1, "setsockopt IP_MULTICAST_IF");	/* 	 * When trying to send large packets, you must increase the	 * size of both the send and receive buffers...	 */	maxsizelen = sizeof maxsize;	if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &maxsize, &maxsizelen) < 0)		err(1, "getsockopt");	if (maxsize < packlen &&	    setsockopt(s, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(maxsize)) < 0)		err(1, "setsockopt");	/*	 * 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.	 */	(void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, &packlen, sizeof(packlen));	if (to->sin_family == AF_INET)		(void)printf("PING %s (%s): %d data bytes\n", hostname,		    inet_ntoa(*(struct in_addr *)&to->sin_addr.s_addr),		    datalen);	else		(void)printf("PING %s: %d data bytes\n", hostname, datalen);	(void)signal(SIGINT, finish);	(void)signal(SIGALRM, catcher);#ifdef SIGINFO	(void)signal(SIGINFO, prtsig);#endif	while (preload--)		/* fire off them quickies */		pinger();	if ((options & F_FLOOD) == 0)		catcher();		/* start things going */	fdmasks = howmany(s+1, NFDBITS) * sizeof(fd_mask);	if ((fdmaskp = (fd_set *)malloc(fdmasks)) == NULL)		err(1, "malloc");	for (;;) {		struct sockaddr_in from;		register int cc;		int fromlen;		sigset_t omask, nmask;		if (options & F_FLOOD) {			pinger();			timeout.tv_sec = 0;			timeout.tv_usec = 10000;			memset(fdmaskp, 0, fdmasks);			FD_SET(s, fdmaskp);			if (select(s + 1, (fd_set *)fdmaskp, (fd_set *)NULL,			    (fd_set *)NULL, &timeout) < 1)				continue;		}		fromlen = sizeof(from);		if ((cc = recvfrom(s, (char *)packet, packlen, 0,		    (struct sockaddr *)&from, &fromlen)) < 0) {			if (errno == EINTR)				continue;			perror("ping: recvfrom");			continue;		}		sigemptyset(&nmask);		sigaddset(&nmask, SIGALRM);		sigprocmask(SIG_BLOCK, &nmask, &omask);		pr_pack((char *)packet, cc, &from);		sigprocmask(SIG_SETMASK, &omask, NULL);		if (npackets && nreceived >= npackets)			break;	}	free(fdmaskp);	finish();	/* NOTREACHED */	exit(0);	/* Make the compiler happy */}