⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ping.c

📁 This is a short linux ping program
💻 C
📖 第 1 页 / 共 3 页
字号:
		     inet_ntoa(whereto.sin_addr), datalen);	/* 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.	 */	while (0 > setsockopt(s, SOL_SOCKET, SO_RCVBUF,			      (char*)&bufspace, sizeof(bufspace))) {		if ((bufspace -= 4096) <= 0)			err(1, "Cannot set the receive buffer size");	}	/* make it possible to send giant probes, but do not worry now	 * if it fails, since we probably won't send giant probes.	 */	(void)setsockopt(s, SOL_SOCKET, SO_SNDBUF,			 (char*)&bufspace, sizeof(bufspace));	(void)signal(SIGINT, prefinish);#if defined(SIGINFO) && defined(NOKERNINFO)	if (tcgetattr (0, &ts) != -1) {		reset_kerninfo = !(ts.c_lflag & NOKERNINFO);		ts.c_lflag |= NOKERNINFO;		tcsetattr (STDIN_FILENO, TCSANOW, &ts);	}#endif#ifdef SIGINFO	(void)signal(SIGINFO, prtsig);#else	(void)signal(SIGQUIT, prtsig);#endif	(void)signal(SIGCONT, prtsig);	/* fire off them quickies */	for (i = 0; i < preload; i++) {		(void)gettimeofday(&now, 0);		pinger();	}	doit();	return 0;}static voiddoit(void){	int cc;	struct sockaddr_in from;	int fromlen;	double sec, last, d_last;	struct pollfd fdmaskp[1];	(void)gettimeofday(&clear_cache,0);	if (maxwait != 0) {		last = timeval_to_sec(&clear_cache) + maxwait;		d_last = 0;	} else {		last = 0;		d_last = 365*24*60*60;	}	do {		(void)gettimeofday(&now,0);		if (last != 0)			d_last = last - timeval_to_sec(&now);		if (ntransmitted < npackets && d_last > 0) {			/* send if within 100 usec or late for next packet */			sec = diffsec(&next_tx,&now);			if (sec <= 0.0001 ||			    (lastrcvd && (pingflags & F_FLOOD))) {				pinger();				sec = diffsec(&next_tx,&now);			}			if (sec < 0.0)				sec = 0.0;			if (d_last < sec)				sec = d_last;		} else {			/* For the last response, wait twice as long as the			 * worst case seen, or 10 times as long as the			 * maximum interpacket interval, whichever is longer.			 */			sec = MAX(2 * tmax, 10 * interval) -			    diffsec(&now, &last_tx);			if (d_last < sec)				sec = d_last;			if (sec <= 0)				break;		}		fdmaskp[0].fd = s;		fdmaskp[0].events = POLLIN;		cc = poll(fdmaskp, 1, (int)(sec * 1000));		if (cc <= 0) {			if (cc < 0) {				if (errno == EINTR)					continue;				jiggle_flush(1);				err(1, "poll");			}			continue;		}		fromlen  = sizeof(from);		cc = recvfrom(s, (char *) packet, packlen,			      0, (struct sockaddr *)&from,			      &fromlen);		if (cc < 0) {			if (errno != EINTR) {				jiggle_flush(1);				warn("recvfrom");				(void)fflush(stderr);			}			continue;		}		(void)gettimeofday(&now, 0);		pr_pack(packet, cc, &from);	} while (nreceived < npackets		 && (nreceived == 0 || !(pingflags & F_ONCE)));	finish(0);}static voidjiggle_flush(int nl)			/* new line if there are dots */{	int serrno = errno;	if (jiggle_cnt > 0) {		total_jiggled += jiggle_cnt;		jiggle_direction = 1;		do {			(void)putchar('.');		} while (--jiggle_cnt > 0);	} else if (jiggle_cnt < 0) {		total_jiggled -= jiggle_cnt;		jiggle_direction = -1;		do {			(void)putchar('\b');		} while (++jiggle_cnt < 0);	}	if (nl) {		if (total_jiggled != 0)			(void)putchar('\n');		total_jiggled = 0;		jiggle_direction = -1;	}	(void)fflush(stdout);	(void)fflush(stderr);	jiggle_time = now;	errno = serrno;}/* jiggle the cursor for flood-ping */static voidjiggle(int delta){	double dt;	if (pingflags & F_QUIET)		return;	/* do not back up into messages */	if (total_jiggled+jiggle_cnt+delta < 0)		return;	jiggle_cnt += delta;	/* flush the FLOOD dots when things are quiet	 * or occassionally to make the cursor jiggle.	 */	dt = diffsec(&last_tx, &jiggle_time);	if (dt > 0.2 || (dt >= 0.15 && delta*jiggle_direction < 0))		jiggle_flush(0);}/* * 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 PHDR_LEN bytes * of the data portion are used to hold a UNIX "timeval" struct in VAX * byte-order, to compute the round-trip time. */static voidpinger(void){	struct tv32 tv32;	int i, cc, sw;	opack_icmp.icmp_code = 0;	opack_icmp.icmp_seq = htons((u_int16_t)(ntransmitted));	/* clear the cached route in the kernel after an ICMP	 * response such as a Redirect is seen to stop causing	 * more such packets.  Also clear the cached route	 * periodically in case of routing changes that make	 * black holes come and go.	 */	if (clear_cache.tv_sec != now.tv_sec) {		opack_icmp.icmp_type = ICMP_ECHOREPLY;		opack_icmp.icmp_id = ~ident;		opack_icmp.icmp_cksum = 0;		opack_icmp.icmp_cksum = in_cksum((u_int16_t *)&opack_icmp,		    PHDR_LEN);		sw = 0;		if (setsockopt(sloop,IPPROTO_IP,IP_HDRINCL,			       (char *)&sw,sizeof(sw)) < 0)			err(1, "Can't turn off special IP header");		if (sendto(sloop, (char *) &opack_icmp, PHDR_LEN, MSG_DONTROUTE,			   (struct sockaddr *)&loc_addr,			   sizeof(struct sockaddr_in)) < 0) {			/*			 * XXX: we only report this as a warning in verbose			 * mode because people get confused when they see			 * this error when they are running in single user			 * mode and they have not configured lo0			 */			if (pingflags & F_VERBOSE)				warn("failed to clear cached route");		}		sw = 1;		if (setsockopt(sloop,IPPROTO_IP,IP_HDRINCL,			       (char *)&sw, sizeof(sw)) < 0)			err(1, "Can't set special IP header");				(void)gettimeofday(&clear_cache,0);	}	opack_icmp.icmp_type = ICMP_ECHO;	opack_icmp.icmp_id = ident;	tv32.tv32_sec = htonl(now.tv_sec);	tv32.tv32_usec = htonl(now.tv_usec);	if (pingflags & F_TIMING)		(void) memcpy(&opack_icmp.icmp_data[0], &tv32, sizeof(tv32));	cc = datalen + PHDR_LEN;	opack_icmp.icmp_cksum = 0;	opack_icmp.icmp_cksum = in_cksum((u_int16_t *)&opack_icmp, cc);	cc += opack_ip->ip_hl<<2;	opack_ip->ip_len = cc;	i = sendto(s, (char *) opack_ip, cc, 0,		   (struct sockaddr *)&send_addr, sizeof(struct sockaddr_in));	if (i != cc) {		jiggle_flush(1);		if (i < 0)			warn("sendto");		else			warnx("wrote %s %d chars, ret=%d", hostname, cc, i);		(void)fflush(stderr);	}	lastrcvd = 0;	CLR(ntransmitted);	ntransmitted++;	last_tx = now;	if (next_tx.tv_sec == 0) {		first_tx = now;		next_tx = now;	}	/* Transmit regularly, at always the same microsecond in the	 * second when going at one packet per second.	 * If we are at most 100 ms behind, send extras to get caught up.	 * Otherwise, skip packets we were too slow to send.	 */	if (diffsec(&next_tx, &now) <= interval) {		do {			timevaladd(&next_tx, &interval_tv);		} while (diffsec(&next_tx, &now) < -0.1);	}	if (pingflags & F_FLOOD)		jiggle(1);	/* While the packet is going out, ready buffer for the next	 * packet. Use a fast but not very good random number generator.	 */	if (pingflags & F_PING_RANDOM)		rnd_fill();}static voidpr_pack_sub(int cc,	    char *addr,	    int seqno,	    int dupflag,	    int ttl,	    double triptime){	jiggle_flush(1);	if (pingflags & F_FLOOD)		return;	(void)printf("%d bytes from %s: icmp_seq=%u", cc, addr, seqno);	if (dupflag)		(void)printf(" DUP!");	(void)printf(" ttl=%d", ttl);	if (pingflags & F_TIMING)		(void)printf(" time=%.3f ms", triptime*1000.0);	/*	 * Send beep to stderr, since that's more likely than stdout	 * to go to a terminal..	 */	if (pingflags & F_AUDIBLE && !dupflag)		(void)fprintf(stderr,"\a");}/* * Print out the packet, if it came from us.  This logic is necessary * because ALL readers of the ICMP socket get a copy of ALL ICMP packets * which arrive ('tis only fair).  This permits multiple copies of this * program to be run without having intermingled output (or statistics!). */static voidpr_pack(u_char *buf,	int tot_len,	struct sockaddr_in *from){	struct ip *ip;	struct icmp *icp;	int i, j, net_len;	u_char *cp;	static int old_rrlen;	static char old_rr[MAX_IPOPTLEN];	int hlen, dupflag = 0, dumped;	double triptime = 0.0;#define PR_PACK_SUB() {if (!dumped) {			\	dumped = 1;					\	pr_pack_sub(net_len, inet_ntoa(from->sin_addr),	\		    ntohs((u_int16_t)icp->icmp_seq),	\		    dupflag, ip->ip_ttl, triptime);}}	/* Check the IP header */	ip = (struct ip *) buf;	hlen = ip->ip_hl << 2;	if (tot_len < hlen + ICMP_MINLEN) {		if (pingflags & F_VERBOSE) {			jiggle_flush(1);			(void)printf("packet too short (%d bytes) from %s\n",				     tot_len, inet_ntoa(from->sin_addr));		}		return;	}	/* Now the ICMP part */	dumped = 0;	net_len = tot_len - hlen;	icp = (struct icmp *)(buf + hlen);	if (icp->icmp_type == ICMP_ECHOREPLY	    && icp->icmp_id == ident) {		if (icp->icmp_seq == htons((u_int16_t)(ntransmitted-1)))			lastrcvd = 1;		last_rx = now;		if (first_rx.tv_sec == 0)			first_rx = last_rx;		nreceived++;		if (pingflags & F_TIMING) {			struct timeval tv;			struct tv32 tv32;			(void) memcpy(&tv32, icp->icmp_data, sizeof(tv32));			tv.tv_sec = ntohl(tv32.tv32_sec);			tv.tv_usec = ntohl(tv32.tv32_usec);			triptime = diffsec(&last_rx, &tv);			tsum += triptime;			tsumsq += triptime * triptime;			if (triptime < tmin)				tmin = triptime;			if (triptime > tmax)				tmax = triptime;		}		if (TST(ntohs((u_int16_t)icp->icmp_seq))) {			nrepeats++, nreceived--;			dupflag=1;		} else {			SET(ntohs((u_int16_t)icp->icmp_seq));		}		if (tot_len != opack_ip->ip_len) {			PR_PACK_SUB();			(void)printf("\nwrong total length %d instead of %d",				     tot_len, opack_ip->ip_len);		}		if (!dupflag) {			static u_int16_t last_seqno = 0xffff;			u_int16_t seqno = ntohs((u_int16_t)icp->icmp_seq);			u_int16_t gap = seqno - (last_seqno + 1);			if (gap > 0 && gap < 0x8000 &&			    (pingflags & F_VERBOSE)) {				(void)printf("[*** sequence gap of %u "				    "packets from %u ... %u ***]\n", gap,				    (u_int16_t) (last_seqno + 1),				    (u_int16_t) (seqno - 1));				if (pingflags & F_QUIET)					summary(0);			}			if (gap < 0x8000)				last_seqno = seqno;		}		if (pingflags & F_QUIET)			return;		if (!(pingflags & F_FLOOD))			PR_PACK_SUB();		/* check the data */		if (datalen > PHDR_LEN		    && !(pingflags & F_PING_RANDOM)		    && memcmp(&icp->icmp_data[PHDR_LEN],			    &opack_icmp.icmp_data[PHDR_LEN],			    datalen-PHDR_LEN)) {			for (i=PHDR_LEN; i<datalen; i++) {				if (icp->icmp_data[i] !=				    opack_icmp.icmp_data[i])					break;			}			PR_PACK_SUB();			(void)printf("\nwrong data byte #%d should have been"				     " %#x but was %#x", i,				     (u_char)opack_icmp.icmp_data[i],				     (u_char)icp->icmp_data[i]);			for (i=PHDR_LEN; i<datalen; i++) {				if ((i%16) == PHDR_LEN)					(void)printf("\n\t");				(void)printf("%2x ",(u_char)icp->icmp_data[i]);			}		}	} else {		if (!pr_icmph(icp, from, net_len))			return;		dumped = 2;	}	/* Display any IP options */	cp = buf + sizeof(struct ip);	while (hlen > (int)sizeof(struct ip)) {		switch (*cp) {		case IPOPT_EOL:			hlen = 0;			break;		case IPOPT_LSRR:			hlen -= 2;			j = *++cp;			++cp;			j -= IPOPT_MINOFF;			if (j <= 0)				continue;			if (dumped <= 1) {				j = ((j+3)/4)*4;				hlen -= j;				cp += j;				break;			}			PR_PACK_SUB();			(void)printf("\nLSRR: ");			for (;;) {				pr_saddr(cp);				cp += 4;				hlen -= 4;				j -= 4;				if (j <= 0)					break;				(void)putchar('\n');			}			break;		case IPOPT_RR:			j = *++cp;	/* get length */			i = *++cp;	/* and pointer */			hlen -= 2;			if (i > j)				i = j;			i -= IPOPT_MINOFF;			if (i <= 0)				continue;			if (dumped <= 1) {				if (i == old_rrlen				    && !memcmp(cp, old_rr, i)) {					if (dumped)					    (void)printf("\t(same route)");					j = ((i+3)/4)*4;					hlen -= j;					cp += j;					break;				}				old_rrlen = i;				(void) memcpy(old_rr, cp, i);			}			if (!dumped) {				jiggle_flush(1);				(void)printf("RR: ");				dumped = 1;			} else {				(void)printf("\nRR: ");			}			for (;;) {				pr_saddr(cp);				cp += 4;				hlen -= 4;				i -= 4;				if (i <= 0)					break;				(void)putchar('\n');			}			break;		case IPOPT_NOP:			if (dumped <= 1)				break;			PR_PACK_SUB();			(void)printf("\nNOP");			break;#ifdef sgi		case IPOPT_SECURITY:	/* RFC 1108 RIPSO BSO */		case IPOPT_ESO:		/* RFC 1108 RIPSO ESO */		case IPOPT_CIPSO:	/* Commercial IPSO */			if ((sysconf(_SC_IP_SECOPTS)) > 0) {				i = (unsigned)cp[1];				hlen -= i - 1;				PR_PACK_SUB();				(void)printf("\nSEC:");				while (i--) {					(void)printf(" %02x", *cp++);				}				cp--;				break;			}#endif		default:			PR_PACK_SUB();			(void)printf("\nunknown option 0x%x", *cp);			break;		}		hlen--;		cp++;	}	if (dumped) {		(void)putchar('\n');		(void)fflush(stdout);	} else {		jiggle(-1);	}}/* Compute the IP checksum *	This assumes the packet is less than 32K long. */static u_int16_tin_cksum(u_int16_t *p, u_int len){	u_int32_t sum = 0;	int nwords = len >> 1;	while (nwords-- != 0)		sum += *p++;	if (len & 1) {		union {			u_int16_t w;			u_int8_t c[2];		} u;		u.c[0] = *(u_char *)p;		u.c[1] = 0;		sum += u.w;	}	/* end-around-carry */	sum = (sum >> 16) + (sum & 0xffff);	sum += (sum >> 16);	return (~sum);}/* * compute the difference of two timevals in seconds */static doublediffsec(struct timeval *timenow,	struct timeval *then){	return ((timenow->tv_sec - then->tv_sec)*1.0		+ (timenow->tv_usec - then->tv_usec)/1000000.0);}static voidtimevaladd(struct timeval *t1,	   struct timeval *t2){	t1->tv_sec += t2->tv_sec;	if ((t1->tv_usec += t2->tv_usec) >= 1000000) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -