measure.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 216 行
C
216 行
#ifndef lintstatic char *sccsid = "@(#)measure.c 4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1988 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * static char sccsid[] = "@(#)measure.c 2.4 (Berkeley) 5/28/86"; */#include "globals.h"#include <protocols/timed.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h>#define BIASP 43199999#define BIASN -43200000#define MODULO 86400000#define PROCESSING_TIME 5 /* ms. to reduce error in measurement */#define PACKET_IN 1024extern int id;int measure_delta;extern int sock_raw;static n_short seqno = 0;/* * Measures the differences between machines' clocks using * ICMP timestamp messages. */measure(wait, addr)struct timeval *wait;struct sockaddr_in *addr;{ int length; int status; int msgcount, trials; int cc, count; fd_set ready; long sendtime, recvtime, histime; long min1, min2, diff; register long delta1, delta2; struct timeval tv1, 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; min1 = min2 = 0x7fffffff; status = HOSTDOWN; measure_delta = HOSTDOWN;/* empties the icmp input queue */ FD_ZERO(&ready);empty: tout.tv_sec = tout.tv_usec = 0; FD_SET(sock_raw, &ready); if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) { length = sizeof(struct sockaddr_in); cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0, (struct sockaddr_in *)NULL, &length); if (cc < 0) return(-1); goto empty; } /* * To measure the difference, select MSGS messages whose round-trip * time is smaller than RANGE if ckrange is 1, otherwise simply * select MSGS messages regardless of round-trip transmission time. * Choose the smallest transmission time in each of the two directions. * Use these two latter quantities to compute the delta between * the two clocks. */ length = sizeof(struct sockaddr_in); oicp->icmp_type = ICMP_TSTAMP; oicp->icmp_code = 0; oicp->icmp_cksum = 0; oicp->icmp_id = id; oicp->icmp_rtime = 0; oicp->icmp_ttime = 0; FD_ZERO(&ready); msgcount = 0; for (trials = 0; msgcount < MSGS && trials < TRIALS; ++trials) { oicp->icmp_seq = ++seqno; oicp->icmp_cksum = 0; tout.tv_sec = wait->tv_sec; tout.tv_usec = wait->tv_usec; (void)gettimeofday (&tv1, (struct timezone *)0); sendtime = oicp->icmp_otime = (tv1.tv_sec % (24*60*60)) * 1000 + tv1.tv_usec / 1000; oicp->icmp_cksum = in_cksum((u_short *)oicp, sizeof(*oicp)); count = sendto(sock_raw, (char *)opacket, sizeof(*oicp), 0, addr, sizeof(struct sockaddr_in)); if (count < 0) { status = UNREACHABLE; return(-1); } for (;;) { FD_SET(sock_raw, &ready); if ((count = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) <= 0) break; cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0, (struct sockaddr_in *)NULL, &length); (void)gettimeofday(&tv1, (struct timezone *)0); if (cc < 0) return(-1);/**//* icp = (struct icmp *) packet; *//**/ icp = (struct icmp *)(packet + (ip->ip_hl << 2)); if((icp->icmp_type == ICMP_TSTAMPREPLY) && icp->icmp_id == id && icp->icmp_seq == seqno) break; } if ((count < 0) && (errno != ETIMEDOUT)) { perror("select"); return(-1); } else if (count <= 0) { continue; /* resend */ } recvtime = (tv1.tv_sec % (24*60*60)) * 1000 + tv1.tv_usec / 1000; diff = recvtime - sendtime; /* * diff can be less than 0 aroud midnight */ if (diff < 0) continue; msgcount++; histime = ntohl((u_long)icp->icmp_rtime); /* * a hosts using a time format different from * ms. since midnight UT (as per RFC792) should * set the high order bit of the 32-bit time * value it transmits. */ if ((histime & 0x80000000) != 0) { status = NONSTDTIME; break; } status = GOOD; delta1 = histime - sendtime; /* * Handles wrap-around to avoid that around * midnight small time differences appear * enormous. However, the two machine's clocks * must be within 12 hours from each other. */ if (delta1 < BIASN) delta1 += MODULO; else if (delta1 > BIASP) delta1 -= MODULO; delta2 = recvtime - histime; if (delta2 < BIASN) delta2 += MODULO; else if (delta2 > BIASP) delta2 -= MODULO; if (delta1 < min1) min1 = delta1; if (delta2 < min2) min2 = delta2; if (diff < RANGE) { min1 = delta1; min2 = delta2; break; } } /* * If no answer is received for TRIALS consecutive times, * the machine is assumed to be down */ if (status == GOOD) { measure_delta = (min1 - min2)/2 + PROCESSING_TIME; } return(status);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?