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: }

Defined functions

measure defined in line 34; used 4 times

Defined variables

measure_delta defined in line 25; used 7 times
sccsid defined in line 8; never used

Defined macros

BIASN defined in line 18; used 2 times
BIASP defined in line 17; used 2 times
MODULO defined in line 19; used 4 times
PACKET_IN defined in line 22; used 3 times
PROCESSING_TIME defined in line 20; used 1 times
Last modified: 1986-05-29
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1198
Valid CSS Valid XHTML 1.0 Strict