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