|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)measure.c 2.4 (Berkeley) 5/28/86"; ! 9: #endif not lint ! 10: ! 11: #include "globals.h" ! 12: #include <protocols/timed.h> ! 13: #include <netinet/in_systm.h> ! 14: #include <netinet/ip.h> ! 15: #include <netinet/ip_icmp.h> ! 16: ! 17: #define BIASP 43199999 ! 18: #define BIASN -43200000 ! 19: #define MODULO 86400000 ! 20: #define PROCESSING_TIME 5 /* ms. to reduce error in measurement */ ! 21: ! 22: #define PACKET_IN 1024 ! 23: ! 24: extern int id; ! 25: int measure_delta; ! 26: extern int sock_raw; ! 27: static n_short seqno = 0; ! 28: ! 29: /* ! 30: * Measures the differences between machines' clocks using ! 31: * ICMP timestamp messages. ! 32: */ ! 33: ! 34: measure(wait, addr) ! 35: struct timeval *wait; ! 36: struct sockaddr_in *addr; ! 37: { ! 38: int length; ! 39: int status; ! 40: int msgcount, trials; ! 41: int cc, count; ! 42: fd_set ready; ! 43: long sendtime, recvtime, histime; ! 44: long min1, min2, diff; ! 45: register long delta1, delta2; ! 46: struct timeval tv1, tout; ! 47: u_char packet[PACKET_IN], opacket[64]; ! 48: register struct icmp *icp = (struct icmp *) packet; ! 49: register struct icmp *oicp = (struct icmp *) opacket; ! 50: struct ip *ip = (struct ip *) packet; ! 51: ! 52: min1 = min2 = 0x7fffffff; ! 53: status = HOSTDOWN; ! 54: measure_delta = HOSTDOWN; ! 55: ! 56: /* empties the icmp input queue */ ! 57: FD_ZERO(&ready); ! 58: empty: ! 59: tout.tv_sec = tout.tv_usec = 0; ! 60: FD_SET(sock_raw, &ready); ! 61: if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) { ! 62: length = sizeof(struct sockaddr_in); ! 63: cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0, ! 64: (struct sockaddr_in *)NULL, &length); ! 65: if (cc < 0) ! 66: return(-1); ! 67: goto empty; ! 68: } ! 69: ! 70: /* ! 71: * To measure the difference, select MSGS messages whose round-trip ! 72: * time is smaller than RANGE if ckrange is 1, otherwise simply ! 73: * select MSGS messages regardless of round-trip transmission time. ! 74: * Choose the smallest transmission time in each of the two directions. ! 75: * Use these two latter quantities to compute the delta between ! 76: * the two clocks. ! 77: */ ! 78: ! 79: length = sizeof(struct sockaddr_in); ! 80: oicp->icmp_type = ICMP_TSTAMP; ! 81: oicp->icmp_code = 0; ! 82: oicp->icmp_cksum = 0; ! 83: oicp->icmp_id = id; ! 84: oicp->icmp_rtime = 0; ! 85: oicp->icmp_ttime = 0; ! 86: FD_ZERO(&ready); ! 87: msgcount = 0; ! 88: for (trials = 0; msgcount < MSGS && trials < TRIALS; ++trials) { ! 89: oicp->icmp_seq = ++seqno; ! 90: oicp->icmp_cksum = 0; ! 91: ! 92: tout.tv_sec = wait->tv_sec; ! 93: tout.tv_usec = wait->tv_usec; ! 94: ! 95: (void)gettimeofday (&tv1, (struct timezone *)0); ! 96: sendtime = oicp->icmp_otime = (tv1.tv_sec % (24*60*60)) * 1000 ! 97: + tv1.tv_usec / 1000; ! 98: oicp->icmp_cksum = in_cksum((u_short *)oicp, sizeof(*oicp)); ! 99: ! 100: count = sendto(sock_raw, (char *)opacket, sizeof(*oicp), 0, ! 101: addr, sizeof(struct sockaddr_in)); ! 102: if (count < 0) { ! 103: status = UNREACHABLE; ! 104: return(-1); ! 105: } ! 106: for (;;) { ! 107: FD_SET(sock_raw, &ready); ! 108: if ((count = select(FD_SETSIZE, &ready, (fd_set *)0, ! 109: (fd_set *)0, &tout)) <= 0) ! 110: break; ! 111: cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0, ! 112: (struct sockaddr_in *)NULL, &length); ! 113: (void)gettimeofday(&tv1, (struct timezone *)0); ! 114: if (cc < 0) ! 115: return(-1); ! 116: icp = (struct icmp *)(packet + (ip->ip_hl << 2)); ! 117: if((icp->icmp_type == ICMP_TSTAMPREPLY) && ! 118: icp->icmp_id == id && icp->icmp_seq == seqno) ! 119: break; ! 120: } ! 121: if (count <= 0) ! 122: continue; /* resend */ ! 123: recvtime = (tv1.tv_sec % (24*60*60)) * 1000 + ! 124: tv1.tv_usec / 1000; ! 125: diff = recvtime - sendtime; ! 126: /* ! 127: * diff can be less than 0 aroud midnight ! 128: */ ! 129: if (diff < 0) ! 130: continue; ! 131: msgcount++; ! 132: histime = ntohl((u_long)icp->icmp_rtime); ! 133: /* ! 134: * a hosts using a time format different from ! 135: * ms. since midnight UT (as per RFC792) should ! 136: * set the high order bit of the 32-bit time ! 137: * value it transmits. ! 138: */ ! 139: if ((histime & 0x80000000) != 0) { ! 140: status = NONSTDTIME; ! 141: break; ! 142: } ! 143: status = GOOD; ! 144: delta1 = histime - sendtime; ! 145: /* ! 146: * Handles wrap-around to avoid that around ! 147: * midnight small time differences appear ! 148: * enormous. However, the two machine's clocks ! 149: * must be within 12 hours from each other. ! 150: */ ! 151: if (delta1 < BIASN) ! 152: delta1 += MODULO; ! 153: else if (delta1 > BIASP) ! 154: delta1 -= MODULO; ! 155: delta2 = recvtime - histime; ! 156: if (delta2 < BIASN) ! 157: delta2 += MODULO; ! 158: else if (delta2 > BIASP) ! 159: delta2 -= MODULO; ! 160: if (delta1 < min1) ! 161: min1 = delta1; ! 162: if (delta2 < min2) ! 163: min2 = delta2; ! 164: if (diff < RANGE) { ! 165: min1 = delta1; ! 166: min2 = delta2; ! 167: break; ! 168: } ! 169: } ! 170: ! 171: /* ! 172: * If no answer is received for TRIALS consecutive times, ! 173: * the machine is assumed to be down ! 174: */ ! 175: if (status == GOOD) { ! 176: measure_delta = (min1 - min2)/2 + PROCESSING_TIME; ! 177: } ! 178: return(status); ! 179: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.