1: #ifndef lint
   2: static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntp.c,v $ $Revision: 3.4.1.6 $ $Date: 89/05/18 18:21:29 $";
   3: #endif	lint
   4: 
   5: /*
   6:  *  $Log:	ntp.c,v $
   7:  * Revision 3.4.1.6  89/05/18  18:21:29  louie
   8:  * A few cosmetic changes in ntp.c for the case when udp/ntp is not in the
   9:  * /etc/services file.
  10:  *
  11:  * Revision 3.4.1.5  89/05/03  15:09:53  louie
  12:  * Fix minor problem in ntp.c to get sin_family set in the proper place.
  13:  *
  14:  * Revision 3.4.1.4  89/04/07  18:04:49  louie
  15:  * Removed unused variables from ntp.c program.
  16:  *
  17:  * Revision 3.4.1.3  89/03/22  18:29:22  louie
  18:  * patch3: Use new RCS headers.
  19:  *
  20:  * Revision 3.4.1.2  89/03/22  17:51:13  louie
  21:  * Use a connect UDP socket so we can pick up ICMP error messages.
  22:  *
  23:  * Revision 3.4.1.1  89/03/20  00:02:32  louie
  24:  * patch1: Shorten timeout interval and clean up timeout message.
  25:  *
  26:  * Revision 3.4  89/03/17  18:36:54  louie
  27:  * Latest test release.
  28:  *
  29:  * Revision 3.3.1.1  89/03/17  18:23:14  louie
  30:  * Fix code that sets time.
  31:  *
  32:  * Revision 3.3  89/03/15  14:19:30  louie
  33:  * New baseline for next release.
  34:  *
  35:  * Revision 3.2.1.2  89/03/15  13:45:13  louie
  36:  * Fix use of NTP_PORT when getservbyname() fails.  Use "%f" in printf format
  37:  * strings rather than "%lf".
  38:  *
  39:  *
  40:  * Revision 3.2.1.1  89/03/10  11:26:23  louie
  41:  * Add (primitive) facility to set the time from an NTP timer server,
  42:  * much the same way as various UDP/TIME based programs do.  The
  43:  * default output format is a one line listing of delay, offset and time.  The
  44:  * previous, longer format can be had by using the -v option.
  45:  *
  46:  * Revision 3.2  89/03/07  18:20:55  louie
  47:  * Cleaned up displays of NTP header fields, also dumping in useful formats
  48:  * (floating point and ctime strings) as well as hex fields.
  49:  *
  50:  * Revision 3.1.1.1  89/02/15  08:53:30  louie
  51:  * Bug fixes to last released version.
  52:  *
  53:  *
  54:  * Revision 3.1  89/01/30  14:43:05  louie
  55:  * Second UNIX NTP test release.
  56:  *
  57:  * Revision 3.0  88/12/12  15:56:10  louie
  58:  * Test release of new UNIX NTP software.  This version should conform to the
  59:  * revised NTP protocol specification.
  60:  *
  61:  */
  62: 
  63: /*
  64:  * This program expects a list of host names.  It will send off a
  65:  * network time protocol packet and print out the replies on the
  66:  * terminal.
  67:  *
  68:  * Example:
  69:  *
  70:  *  % ntp umd1.umd.edu
  71:  *  Packet from: [128.8.10.1]
  72:  *  Leap 0, version 1, mode Server, poll 6, precision -10 stratum 1 (WWVB)
  73:  *  Synch Distance is 0000.1999  0.099991
  74:  *  Synch Dispersion is 0000.0000  0.000000
  75:  *  Reference Timestamp is a7bea6c3.88b40000 Tue Mar  7 14:06:43 1989
  76:  *  Originate Timestamp is a7bea6d7.d7e6e652 Tue Mar  7 14:07:03 1989
  77:  *  Receive Timestamp is   a7bea6d7.cf1a0000 Tue Mar  7 14:07:03 1989
  78:  *  Transmit Timestamp is  a7bea6d8.0ccc0000 Tue Mar  7 14:07:04 1989
  79:  *  Input Timestamp is     a7bea6d8.1a77e5ea Tue Mar  7 14:07:04 1989
  80:  *  umd1: delay:0.019028 offset:-0.043890
  81:  *  Tue Mar  7 14:07:04 1989
  82:  *
  83:  */
  84: 
  85: #include <stdio.h>
  86: #include <sys/types.h>
  87: #include <sys/param.h>
  88: #include <sys/time.h>
  89: #include <sys/uio.h>
  90: #include <sys/socket.h>
  91: #include <sys/ioctl.h>
  92: 
  93: #include <netinet/in.h>
  94: #include <netinet/in_systm.h>
  95: #include <netinet/ip.h>
  96: #include <netinet/udp.h>
  97: 
  98: #include <arpa/inet.h>
  99: #include <netdb.h>
 100: #include <strings.h>
 101: #include <errno.h>
 102: #include "ntp.h"
 103: 
 104: char *modename[8] = {
 105:     "Unspecified",
 106:     "Symmetric Active",
 107:     "Symmetric Passive",
 108:     "Client",
 109:     "Server",
 110:     "Broadcast",
 111:     "Reserved-1",
 112:     "Reserved-2"
 113:     };
 114: 
 115: #define RETRY_COUNT 2   /* number of times we want to retry */
 116: #define TIME_OUT        10  /* time to wait for reply, in secs */
 117: 
 118: 
 119: struct sockaddr_in sin = {AF_INET};
 120: struct sockaddr_in dst = {AF_INET};
 121: struct servent *sp;
 122: extern double ul_fixed_to_double(), s_fixed_to_double();
 123: extern int errno;
 124: int set, verbose, force;
 125: int debug;
 126: extern int optind;
 127: 
 128: main(argc, argv)
 129:     int argc;
 130:     char *argv[];
 131: {
 132:     struct hostent *hp;
 133:     struct in_addr clock_host;
 134:     struct l_fixedpt in_timestamp;
 135:     static struct ntpdata ntp_data;
 136:     struct ntpdata *pkt = &ntp_data;
 137:     struct timeval tp, timeout;
 138:     int host, n, retry, s;
 139:     fd_set readfds;
 140:     int dstlen = sizeof(dst);
 141:     double t1, t2, t3, t4, offset, delay;
 142:     char ref_clock[5];
 143:     time_t net_time;
 144:     ref_clock[4] = '\0';
 145: 
 146:     timeout.tv_sec = TIME_OUT;
 147:     timeout.tv_usec = 0;
 148:     retry = RETRY_COUNT;
 149: 
 150:     sp = getservbyname("ntp", "udp");
 151:     if (sp == NULL) {
 152:         fprintf(stderr, "udp/ntp: service unknown; using default %d\n",
 153:             NTP_PORT);
 154:         dst.sin_port = htons(NTP_PORT);
 155:     } else
 156:         dst.sin_port = sp->s_port;
 157: 
 158:     dst.sin_family = AF_INET;
 159:     while ((n = getopt(argc, argv, "vsf")) != EOF) {
 160:         switch (n) {
 161:         case 'v':
 162:             verbose = 1;
 163:             break;
 164:         case 's':
 165:             set = 1;
 166:             break;
 167:         case 'f':
 168:             force = 1;
 169:             break;
 170:         }
 171:     }
 172:     for (host = optind; host < argc; ++host) {
 173:         long    HostAddr;
 174: 
 175:         if (argv[host] == NULL)
 176:             continue;
 177: 
 178:         hp = NULL;
 179:         HostAddr = inet_addr(argv[host]);
 180:         dst.sin_addr.s_addr = (u_long) HostAddr;
 181:         if (HostAddr == -1) {
 182:             hp = gethostbyname(argv[host]);
 183:             if (hp == NULL) {
 184:                 fprintf(stderr, "\nNo such host: %s\n",
 185:                     argv[host]);
 186:                 continue;
 187:             }
 188:             bcopy(hp->h_addr, (char *) &dst.sin_addr,hp->h_length);
 189:         }
 190: 
 191:         bzero((char *)pkt, sizeof(ntp_data));
 192: 
 193:         pkt->status = NTPVERSION_1 | NO_WARNING | MODE_CLIENT;
 194:         pkt->stratum = UNSPECIFIED;
 195:         pkt->ppoll = 0;
 196: 
 197:         if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 198:             perror("ntp socket");
 199:             exit(1);
 200:         }
 201: 
 202:         FD_ZERO(&readfds);
 203:         FD_SET(s, &readfds);    /* since it's always modified on ret */
 204: 
 205:         if (connect(s, (struct sockaddr *)&dst, dstlen)) {
 206:             perror("connect");
 207:             exit(1);
 208:         }
 209: 
 210:         /*
 211: 		 * Needed to fill in the time stamp fields
 212: 		 */
 213:         (void) gettimeofday(&tp, (struct timezone *) 0);
 214:         tstamp(&pkt->xmt, &tp);
 215: 
 216:         if (send(s, (char *) pkt, sizeof(ntp_data), 0) < 0) {
 217:             perror("send");
 218:             exit(1);
 219:         }
 220: 
 221:         /*
 222: 		 * Wait for the reply by watching the file descriptor
 223: 		 */
 224:         if ((n = select(FD_SETSIZE, (fd_set *) & readfds, (fd_set *) 0,
 225:                 (fd_set *) 0, &timeout)) < 0) {
 226:             perror("ntp select");
 227:             exit(1);
 228:         }
 229: 
 230:         if (n == 0) {
 231:             fprintf(stderr,"*Timeout*\n");
 232:             if (--retry)
 233:                 --host;
 234:             else {
 235:                 fprintf(stderr,"Host %s is not responding\n",
 236:                        argv[host]);
 237:                 retry = RETRY_COUNT;
 238:             }
 239:             continue;
 240:         }
 241:         if ((recvfrom(s, (char *) pkt, sizeof(ntp_data), 0,
 242:                   (struct sockaddr *) &sin, &dstlen)) < 0) {
 243:             perror("recvfrom");
 244:             exit(1);
 245:         }
 246:         (void) gettimeofday(&tp, (struct timezone *) 0);
 247:         tstamp(&in_timestamp, &tp);
 248: 
 249:         close(s);
 250:         if (verbose) {
 251:             printf("Packet from: [%s]\n", inet_ntoa(sin.sin_addr));
 252:             printf("Leap %d, version %d, mode %s, poll %d, precision %d stratum %d",
 253:                    (pkt->status & LEAPMASK) >> 6,
 254:                    (pkt->status & VERSIONMASK) >> 3,
 255:                    modename[pkt->status & MODEMASK],
 256:                    pkt->ppoll, pkt->precision, pkt->stratum);
 257:             switch (pkt->stratum) {
 258:             case 0:
 259:             case 1:
 260:                 (void) strncpy(ref_clock, (char *) &pkt->refid, 4);
 261:                 ref_clock[4] = '\0';
 262:                 printf(" (%s)\n", ref_clock);
 263:                 break;
 264:             default:
 265:                 clock_host.s_addr = (u_long) pkt->refid;
 266:                 printf(" [%s]\n", inet_ntoa(clock_host));
 267:                 break;
 268:             }
 269:             printf("Synch Distance is %04x.%04x  %f\n",
 270:                    ntohs(pkt->distance.int_part),
 271:                    ntohs(pkt->distance.fraction),
 272:                    s_fixed_to_double(&pkt->distance));
 273: 
 274:             printf("Synch Dispersion is %04x.%04x  %f\n",
 275:                    ntohs(pkt->dispersion.int_part),
 276:                    ntohs(pkt->dispersion.fraction),
 277:                    s_fixed_to_double(&pkt->dispersion));
 278: 
 279:             net_time = ntohl(pkt->reftime.int_part) - JAN_1970;
 280:             printf("Reference Timestamp is %08lx.%08lx %s",
 281:                    ntohl(pkt->reftime.int_part),
 282:                    ntohl(pkt->reftime.fraction),
 283:                    ctime(&net_time));
 284: 
 285:             net_time = ntohl(pkt->org.int_part) - JAN_1970;
 286:             printf("Originate Timestamp is %08lx.%08lx %s",
 287:                    ntohl(pkt->org.int_part),
 288:                    ntohl(pkt->org.fraction),
 289:                    ctime(&net_time));
 290: 
 291:             net_time = ntohl(pkt->rec.int_part) - JAN_1970;
 292:             printf("Receive Timestamp is   %08lx.%08lx %s",
 293:                    ntohl(pkt->rec.int_part),
 294:                    ntohl(pkt->rec.fraction),
 295:                    ctime(&net_time));
 296: 
 297:             net_time = ntohl(pkt->xmt.int_part) - JAN_1970;
 298:             printf("Transmit Timestamp is  %08lx.%08lx %s",
 299:                    ntohl(pkt->xmt.int_part),
 300:                    ntohl(pkt->xmt.fraction),
 301:                    ctime(&net_time));
 302:         }
 303:         t1 = ul_fixed_to_double(&pkt->org);
 304:         t2 = ul_fixed_to_double(&pkt->rec);
 305:         t3 = ul_fixed_to_double(&pkt->xmt);
 306:         t4 = ul_fixed_to_double(&in_timestamp);
 307: 
 308:         net_time = ntohl(in_timestamp.int_part) - JAN_1970;
 309:         if (verbose)
 310:             printf("Input Timestamp is     %08lx.%08lx %s",
 311:                    ntohl(in_timestamp.int_part),
 312:                    ntohl(in_timestamp.fraction), ctime(&net_time));
 313: 
 314:         delay = (t4 - t1) - (t3 - t2);
 315:         offset = (t2 - t1) + (t3 - t4);
 316:         offset = offset / 2.0;
 317:         printf("%.20s: delay:%f offset:%f  ",
 318:                hp ? hp->h_name : argv[host],
 319:                delay, offset);
 320:         net_time = ntohl(pkt->xmt.int_part) - JAN_1970 + delay;
 321:         fputs(ctime(&net_time), stdout);
 322:         (void)fflush(stdout);
 323: 
 324:         if (!set)
 325:             continue;
 326: 
 327:         if ((offset < 0 ? -offset  : offset) > WAYTOOBIG && !force) {
 328:             fprintf(stderr, "Offset too large - use -f option to force clock set.\n");
 329:             continue;
 330:         }
 331: 
 332:         if (pkt->status & LEAPMASK == ALARM) {
 333:             fprintf(stderr, "Can't set time from %s - unsynchronized\n",
 334:                 argv[host]);
 335:             continue;
 336:         }
 337: 
 338:         /* set the clock */
 339:         gettimeofday(&tp, (struct timezone *) 0);
 340:         offset += tp.tv_sec;
 341:         offset += tp.tv_usec / 1000000.0;
 342:         tp.tv_sec = offset;
 343:         tp.tv_usec = (offset - tp.tv_sec) * 1000000.0;
 344: 
 345:         if (settimeofday(&tp, (struct timezone *) 0)) {
 346:             perror("Can't set time (settimeofday)");
 347:         } else
 348:             set = 0;
 349:     }           /* end of for each host */
 350:     exit(0);
 351: }               /* end of main */

Defined functions

main defined in line 128; never used

Defined variables

debug defined in line 125; never used
dst defined in line 120; used 7 times
force defined in line 124; used 2 times
modename defined in line 104; used 1 times
rcsid defined in line 2; never used
set defined in line 124; used 3 times
sin defined in line 119; used 2 times
sp defined in line 121; used 3 times
verbose defined in line 124; used 3 times

Defined macros

RETRY_COUNT defined in line 115; used 2 times
TIME_OUT defined in line 116; used 1 times
Last modified: 1989-07-25
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 806
Valid CSS Valid XHTML 1.0 Strict