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

📄 measure.c

📁 早期freebsd实现
💻 C
字号:
/*- * Copyright (c) 1985, 1993 *	The Regents of the University of California.  All rights reserved. * * 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. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 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. */#ifndef lintstatic char sccsid[] = "@(#)measure.c	8.1 (Berkeley) 6/6/93";#endif /* not lint */#ifdef sgi#ident "$Revision: 1.8 $"#endif#include "globals.h"#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h>#define MSEC_DAY	(SECDAY*1000)#define PACKET_IN	1024#define MSGS		5		/* timestamps to average */#define TRIALS		10		/* max # of timestamps sent */extern int sock_raw;int measure_delta;static n_short seqno = 0;/* * Measures the differences between machines' clocks using * ICMP timestamp messages. */int					/* status val defined in globals.h */measure(maxmsec, wmsec, hname, addr, print)	u_long maxmsec;			/* wait this many msec at most */	u_long wmsec;			/* msec to wait for an answer */	char *hname;	struct sockaddr_in *addr;	int print;			/* print complaints on stderr */{	int length;	int measure_status;	int rcvcount, trials;	int cc, count;	fd_set ready;	long sendtime, recvtime, histime1, histime2;	long idelta, odelta, total;	long min_idelta, min_odelta;	struct timeval tdone, tcur, ttrans, twait, tout;	u_char packet[PACKET_IN], opacket[64];	register struct icmp *icp = (struct icmp *) packet;	register struct icmp *oicp = (struct icmp *) opacket;	struct ip *ip = (struct ip *) packet;	min_idelta = min_odelta = 0x7fffffff;	measure_status = HOSTDOWN;	measure_delta = HOSTDOWN;	errno = 0;	/* open raw socket used to measure time differences */	if (sock_raw < 0) {		sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);		if (sock_raw < 0)  {			syslog(LOG_ERR, "opening raw socket: %m");			goto quit;		}	}	    	/*	 * empty the icmp input queue	 */	FD_ZERO(&ready);	for (;;) {		tout.tv_sec = tout.tv_usec = 0;		FD_SET(sock_raw, &ready);		if (select(sock_raw+1, &ready, 0,0, &tout)) {			length = sizeof(struct sockaddr_in);			cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,				      0,&length);			if (cc < 0)				goto quit;			continue;		}		break;	}	/*	 * Choose the smallest transmission time in each of the two	 * directions. Use these two latter quantities to compute the delta	 * between the two clocks.	 */	oicp->icmp_type = ICMP_TSTAMP;	oicp->icmp_code = 0;	oicp->icmp_id = getpid();	oicp->icmp_rtime = 0;	oicp->icmp_ttime = 0;	oicp->icmp_seq = seqno;	FD_ZERO(&ready);#ifdef sgi	sginap(1);			/* start at a clock tick */#endif /* sgi */	(void)gettimeofday(&tdone, 0);	mstotvround(&tout, maxmsec);	timevaladd(&tdone, &tout);		/* when we give up */	mstotvround(&twait, wmsec);	rcvcount = 0;	trials = 0;	while (rcvcount < MSGS) {		(void)gettimeofday(&tcur, 0);		/*		 * keep sending until we have sent the max		 */		if (trials < TRIALS) {			trials++;			oicp->icmp_otime = ((tcur.tv_sec % SECDAY) * 1000					    + tcur.tv_usec / 1000);			oicp->icmp_cksum = 0;			oicp->icmp_cksum = in_cksum((u_short*)oicp,						    sizeof(*oicp));			count = sendto(sock_raw, opacket, sizeof(*oicp), 0,				       (struct sockaddr*)addr,				       sizeof(struct sockaddr));			if (count < 0) {				if (measure_status == HOSTDOWN)					measure_status = UNREACHABLE;				goto quit;			}			++oicp->icmp_seq;			ttrans = tcur;			timevaladd(&ttrans, &twait);		} else {			ttrans = tdone;		}		while (rcvcount < trials) {			timevalsub(&tout, &ttrans, &tcur);			if (tout.tv_sec < 0)				tout.tv_sec = 0;			FD_SET(sock_raw, &ready);			count = select(sock_raw+1, &ready, (fd_set *)0,				       (fd_set *)0, &tout);			(void)gettimeofday(&tcur, (struct timezone *)0);			if (count <= 0)				break;			length = sizeof(struct sockaddr_in);			cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0,				      0,&length);			if (cc < 0)				goto quit;			/* 			 * got something.  See if it is ours			 */			icp = (struct icmp *)(packet + (ip->ip_hl << 2));			if (cc < sizeof(*ip)			    || icp->icmp_type != ICMP_TSTAMPREPLY			    || icp->icmp_id != oicp->icmp_id			    || icp->icmp_seq < seqno			    || icp->icmp_seq >= oicp->icmp_seq)				continue;			sendtime = ntohl(icp->icmp_otime);			recvtime = ((tcur.tv_sec % SECDAY) * 1000 +				    tcur.tv_usec / 1000);			total = recvtime-sendtime;			if (total < 0)	/* do not hassle midnight */				continue;			rcvcount++;			histime1 = ntohl(icp->icmp_rtime);			histime2 = ntohl(icp->icmp_ttime);			/*			 * a host using a time format different from			 * msec. since midnight UT (as per RFC792) should			 * set the high order bit of the 32-bit time			 * value it transmits.			 */			if ((histime1 & 0x80000000) != 0) {				measure_status = NONSTDTIME;				goto quit;			}			measure_status = GOOD;			idelta = recvtime-histime2;			odelta = histime1-sendtime;			/* do not be confused by midnight */			if (idelta < -MSEC_DAY/2) idelta += MSEC_DAY;			else if (idelta > MSEC_DAY/2) idelta -= MSEC_DAY;			if (odelta < -MSEC_DAY/2) odelta += MSEC_DAY;			else if (odelta > MSEC_DAY/2) odelta -= MSEC_DAY;			/* save the quantization error so that we can get a			 * measurement finer than our system clock.			 */			if (total < MIN_ROUND) {				measure_delta = (odelta - idelta)/2;				goto quit;			}			if (idelta < min_idelta)				min_idelta = idelta;			if (odelta < min_odelta)				min_odelta = odelta;			measure_delta = (min_odelta - min_idelta)/2;		}		if (tcur.tv_sec > tdone.tv_sec		    || (tcur.tv_sec == tdone.tv_sec			&& tcur.tv_usec >= tdone.tv_usec))			break;	}quit:	seqno += TRIALS;		/* allocate our sequence numbers */	/*	 * If no answer is received for TRIALS consecutive times,	 * the machine is assumed to be down	 */	if (measure_status == GOOD) {		if (trace) {			fprintf(fd,				"measured delta %4d, %d trials to %-15s %s\n",			   	measure_delta, trials,				inet_ntoa(addr->sin_addr), hname);		}	} else if (print) {		if (errno != 0)			fprintf(stderr, "measure %s: %s\n", hname,				strerror(errno));	} else {		if (errno != 0) {			syslog(LOG_ERR, "measure %s: %m", hname);		} else {			syslog(LOG_ERR, "measure: %s did not respond", hname);		}		if (trace) {			fprintf(fd,				"measure: %s failed after %d trials\n",				hname, trials);			(void)fflush(fd);		}	}	return(measure_status);}/* * round a number of milliseconds into a struct timeval */voidmstotvround(res, x)	struct timeval *res;	long x;{#ifndef sgi	if (x < 0)		x = -((-x + 3)/5);	else		x = (x+3)/5;	x *= 5;#endif /* sgi */	res->tv_sec = x/1000;	res->tv_usec = (x-res->tv_sec*1000)*1000;	if (res->tv_usec < 0) {		res->tv_usec += 1000000;		res->tv_sec--;	}}voidtimevaladd(tv1, tv2)	struct timeval *tv1, *tv2;{	tv1->tv_sec += tv2->tv_sec;	tv1->tv_usec += tv2->tv_usec;	if (tv1->tv_usec >= 1000000) {		tv1->tv_sec++;		tv1->tv_usec -= 1000000;	}	if (tv1->tv_usec < 0) {		tv1->tv_sec--;		tv1->tv_usec += 1000000;	}}voidtimevalsub(res, tv1, tv2)	struct timeval *res, *tv1, *tv2;{	res->tv_sec = tv1->tv_sec - tv2->tv_sec;	res->tv_usec = tv1->tv_usec - tv2->tv_usec;	if (res->tv_usec >= 1000000) {		res->tv_sec++;		res->tv_usec -= 1000000;	}	if (res->tv_usec < 0) {		res->tv_sec--;		res->tv_usec += 1000000;	}}

⌨️ 快捷键说明

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