60
63
static int openhost P((const char *));
61
64
static int sendpkt P((char *, int));
62
65
static void growpktdata P((void));
63
static int getresponse P((int, int, int *, int *, char **));
66
static int getresponse P((int, int, int *, int *, char **, int));
64
67
static int sendrequest P((int, int, int, int, int, char *));
65
68
static void getcmds P((void));
66
69
static RETSIGTYPE abortcmd P((int));
68
71
static void tokenize P((const char *, char **, int *));
69
72
static int findcmd P((char *, struct xcmd *, struct xcmd *, struct xcmd **));
70
73
static int getarg P((char *, int, arg_v *));
71
static int getnetnum P((const char *, u_int32 *, char *));
74
static int getnetnum P((const char *, struct sockaddr_storage *, char *, int));
72
75
static void help P((struct parse *, FILE *));
73
76
#ifdef QSORT_USES_VOID_P
74
77
static int helpsort P((const void *, const void *));
108
111
{ "delay", my_delay, { OPT|INT, NO, NO, NO },
109
112
{ "msec", "", "", "" },
110
113
"set the delay added to encryption time stamps" },
111
{ "host", host, { OPT|NTP_STR, NO, NO, NO },
112
{ "hostname", "", "", "" },
114
{ "host", host, { OPT|NTP_STR, OPT|NTP_STR, NO, NO },
115
{ "-4|-6", "hostname", "", "" },
113
116
"specify the host whose NTP server we talk to" },
114
117
{ "passwd", passwd, { OPT|NTP_STR, NO, NO, NO },
115
118
{ "", "", "", "" },
151
154
#define MAXCMDS 100 /* maximum commands on cmd line */
152
155
#define MAXHOSTS 200 /* maximum hosts on cmd line */
153
156
#define MAXLINE 512 /* maximum line length */
154
#define MAXTOKENS (1+MAXARGS+2) /* maximum number of usable tokens */
157
#define MAXTOKENS (1+1+MAXARGS+2) /* maximum number of usable tokens */
158
/* command + -4|-6 + MAXARGS + */
157
162
* Some variables used and manipulated locally
160
165
static struct timeval tvsout = { DEFSTIMEOUT, 0 }; /* secondary time out */
161
166
static l_fp delay_time; /* delay time */
162
167
static char currenthost[LENHOSTNAME]; /* current host name */
163
static struct sockaddr_in hostaddr = { 0 }; /* host address */
164
static int showhostnames = 1; /* show host names by default */
168
int showhostnames = 1; /* show host names by default */
166
static int sockfd; /* fd socket is openned on */
170
static int ai_fam_templ; /* address family */
171
static int ai_fam_default; /* default address family */
172
static SOCKET sockfd; /* fd socket is opened on */
167
173
static int havehost = 0; /* set to 1 when host open */
168
struct servent *server_entry = NULL; /* server entry for ntp */
170
176
#if defined (SYS_WINNT) || defined (SYS_VXWORKS)
171
177
char password[9];
172
178
#endif /* SYS_WINNT || SYS_VXWORKS */
175
WORD wVersionRequested;
177
181
DWORD NumberOfBytesWritten;
179
183
HANDLE TimerThreadHandle = NULL; /* 1998/06/03 - Used in ntplib/machines.c */
292
301
taskPrioritySet(taskIdSelf(), 100 );
305
if (!Win32InitSockets())
307
fprintf(stderr, "No useable winsock.dll:");
310
#endif /* SYS_WINNT */
312
/* Check to see if we have IPv6. Otherwise force the -4 flag */
313
if (isc_net_probeipv6() != ISC_R_SUCCESS) {
314
ai_fam_default = AF_INET;
295
317
progname = argv[0];
296
while ((c = ntp_getopt(argc, argv, "c:dilnps")) != EOF)
318
ai_fam_templ = ai_fam_default;
319
while ((c = ntp_getopt(argc, argv, "46c:dilnps")) != EOF)
322
ai_fam_templ = AF_INET;
325
ai_fam_templ = AF_INET6;
299
328
ADDCMD(ntp_optarg);
392
413
const char *hname
396
416
char temphost[LENHOSTNAME];
398
if (server_entry == NULL) {
399
server_entry = getservbyname("ntp", "udp");
400
if (server_entry == NULL) {
401
#ifdef VMS /* UCX getservbyname() doesn't work [yet], but we do know better */
402
server_entry = (struct servent *)
403
malloc(sizeof(struct servent));
404
server_entry->s_port = htons(NTP_PORT);
406
(void) fprintf(stderr, "%s: ntp/udp: unknown service\n",
409
#endif /* VMS & UCX */
412
printf("Got ntp/udp service entry\n");
415
if (!getnetnum(hname, &netnum, temphost))
418
struct addrinfo hints, *ai = NULL;
419
register const char *cp;
420
char name[LENHOSTNAME];
424
* We need to get by the [] if they were entered
431
for(i = 0; *cp != ']'; cp++, i++)
438
* First try to resolve it as an ip address and if that fails,
439
* do a fullblown (dns) lookup. That way we only use the dns
440
* when it is needed and work around some implementations that
441
* will return an "IPv4-mapped IPv6 address" address if you
442
* give it an IPv4 address to lookup.
444
strcpy(service, "ntp");
445
memset((char *)&hints, 0, sizeof(struct addrinfo));
446
hints.ai_family = ai_fam_templ;
447
hints.ai_protocol = IPPROTO_UDP;
448
hints.ai_socktype = SOCK_DGRAM;
449
hints.ai_flags = AI_NUMERICHOST;
451
a_info = getaddrinfo(hname, service, &hints, &ai);
452
if (a_info == EAI_NONAME || a_info == EAI_NODATA) {
453
hints.ai_flags = AI_CANONNAME;
455
hints.ai_flags |= AI_ADDRCONFIG;
457
a_info = getaddrinfo(hname, service, &hints, &ai);
459
/* Some older implementations don't like AI_ADDRCONFIG. */
460
if (a_info == EAI_BADFLAGS) {
461
hints.ai_flags = AI_CANONNAME;
462
a_info = getaddrinfo(hname, service, &hints, &ai);
465
(void) fprintf(stderr, "%s\n", gai_strerror(a_info));
469
if (ai->ai_canonname == NULL) {
470
strncpy(temphost, stoa((struct sockaddr_storage *)ai->ai_addr),
472
temphost[LENHOSTNAME-1] = '\0';
474
strncpy(temphost, ai->ai_canonname, LENHOSTNAME);
475
temphost[LENHOSTNAME-1] = '\0';
419
479
printf("Opening host %s\n", temphost);
427
487
(void) strcpy(currenthost, temphost);
429
hostaddr.sin_family = AF_INET;
431
hostaddr.sin_port = server_entry->s_port;
433
hostaddr.sin_port = htons(SERVER_PORT_NUM);
435
hostaddr.sin_addr.s_addr = netnum;
489
/* port maps to the same in both families */
490
s_port = ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port;
492
((struct sockaddr_in6 *)&hostaddr)->sin6_port = htons(SERVER_PORT_NUM);
493
if (ai->ai_family == AF_INET)
494
*(struct sockaddr_in *)&hostaddr=
495
*((struct sockaddr_in *)ai->ai_addr);
497
*(struct sockaddr_in6 *)&hostaddr=
498
*((struct sockaddr_in6 *)ai->ai_addr);
499
#endif /* SYS_VXWORKS */
439
503
int optionValue = SO_SYNCHRONOUS_NONALERT;
441
506
err = setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&optionValue, sizeof(optionValue));
442
507
if (err != NO_ERROR) {
443
508
(void) fprintf(stderr, "cannot open nonoverlapped sockets\n");
448
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
513
sockfd = socket(ai->ai_family, SOCK_DGRAM, 0);
449
514
if (sockfd == INVALID_SOCKET) {
450
515
error("socket", "", "");
454
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
519
sockfd = socket(ai->ai_family, SOCK_DGRAM, 0);
455
520
if (sockfd == -1)
456
521
error("socket", "", "");
457
522
#endif /* SYS_WINNT */
472
if (connect(sockfd, (struct sockaddr *)&hostaddr,
538
if (connect(sockfd, (struct sockaddr *)&hostaddr,
473
539
sizeof(hostaddr)) == -1)
541
if (connect(sockfd, (struct sockaddr *)ai->ai_addr,
542
ai->ai_addrlen) == -1)
543
#endif /* SYS_VXWORKS */
474
544
error("connect", "", "");
548
req_pkt_size = REQ_LEN_NOMAC;
549
impl_ver = IMPL_XNTPD;
679
758
* If this isn't our first packet, make sure the size matches
680
759
* the other ones.
682
if (!firstpkt && size != *rsize) {
761
if (!firstpkt && esize != *rsize) {
684
763
printf("Received itemsize %d, previous %d\n",
690
* If we've received this before, toss it
768
* If we've received this before, +toss it
692
770
seq = INFO_SEQ(rpkt.auth_seq);
693
771
if (haveseq[seq]) {
712
790
* So far, so good. Copy this data into the output array.
714
if ((datap + datasize) > (pktdata + pktdatasize)) {
792
if ((datap + datasize + (pad * items)) > (pktdata + pktdatasize)) {
715
793
int offset = datap - pktdata;
717
795
*rdata = pktdata; /* might have been realloced ! */
718
796
datap = pktdata + offset;
720
memmove(datap, (char *)rpkt.data, (unsigned)datasize);
799
* We now move the pointer along according to size and number of
800
* items. This is so we can play nice with older implementations
803
tmp_data = (char *)rpkt.data;
804
for(i = 0; i <items; i++){
805
memmove(datap, tmp_data, (unsigned)size);
807
memset(datap + size, 0, pad);
726
815
*ritems += items;
772
861
qpkt.auth_seq = AUTH_SEQ(0, 0);
773
return sendpkt((char *)&qpkt, REQ_LEN_NOMAC);
862
return sendpkt((char *)&qpkt, req_pkt_size);
777
866
const char *pass = "\0";
867
struct req_pkt_tail *qpktail;
869
qpktail = (struct req_pkt_tail *)((char *)&qpkt + req_pkt_size
870
+ MAX_MAC_LEN - sizeof(struct req_pkt_tail));
779
872
if (info_auth_keyid == 0) {
780
873
maclen = getkeyid("Keyid: ");
797
889
authusekey(info_auth_keyid, info_auth_keytype, (const u_char *)pass);
798
890
authtrust(info_auth_keyid, 1);
799
891
qpkt.auth_seq = AUTH_SEQ(1, 0);
800
qpkt.keyid = htonl(info_auth_keyid);
892
qpktail->keyid = htonl(info_auth_keyid);
801
893
get_systime(&ts);
802
894
L_ADD(&ts, &delay_time);
803
HTONL_FP(&ts, &qpkt.tstamp);
895
HTONL_FP(&ts, &qpktail->tstamp);
804
896
maclen = authencrypt(info_auth_keyid, (u_int32 *)&qpkt,
806
898
if (maclen == 0) {
807
899
(void) fprintf(stderr, "Key not found\n");
810
return sendpkt((char *)&qpkt, (int)(REQ_LEN_NOMAC + maclen));
902
return sendpkt((char *)&qpkt, (int)(req_pkt_size + maclen));
872
966
* Get the response. If we got a standard error, print a message
874
res = getresponse(implcode, reqcode, ritems, rsize, rdata);
968
res = getresponse(implcode, reqcode, ritems, rsize, rdata, esize);
971
* Try to be compatible with older implementations of ntpd.
973
if (res == INFO_ERR_FMT && req_pkt_size != 48) {
976
oldsize = req_pkt_size;
978
switch(req_pkt_size) {
986
if (impl_ver == IMPL_XNTPD) {
988
"***Warning changing to older implementation\n");
989
return INFO_ERR_IMPL;
993
"***Warning changing the request packet size from %d to %d\n",
994
oldsize, req_pkt_size);
876
998
/* log error message if not told to be quiet */
877
999
if ((res > 0) && (((1 << res) & quiet_mask) == 0)) {
879
1001
case INFO_ERR_IMPL:
1002
/* Give us a chance to try the older implementation. */
1003
if (implcode == IMPL_XNTPD)
880
1005
(void) fprintf(stderr,
881
1006
"***Server implementation incompatable with our own\n");
1007
1135
pcmd.keyword = tokens[0];
1008
1136
pcmd.nargs = 0;
1009
for (i = 0; i < MAXARGS && xcmd->arg[i] != NO; i++) {
1010
if ((i+1) >= ntok) {
1138
for (i = 0; i < MAXARGS && xcmd->arg[i] != NO;) {
1139
if ((i+ti) >= ntok) {
1011
1140
if (!(xcmd->arg[i] & OPT)) {
1012
1141
printusage(xcmd, stderr);
1017
if ((xcmd->arg[i] & OPT) && (*tokens[i+1] == '>'))
1019
if (!getarg(tokens[i+1], (int)xcmd->arg[i], &pcmd.argval[i]))
1146
if ((xcmd->arg[i] & OPT) && (*tokens[i+ti] == '>'))
1148
rval = getarg(tokens[i+ti], (int)xcmd->arg[i], &pcmd.argval[i]);
1025
1160
if (i < ntok && *tokens[i] == '>') {
1224
1381
const char *hname,
1382
struct sockaddr_storage *num,
1388
struct addrinfo hints, *ai = NULL;
1390
sockaddr_len = (af == AF_INET)
1391
? sizeof(struct sockaddr_in)
1392
: sizeof(struct sockaddr_in6);
1393
memset((char *)&hints, 0, sizeof(struct addrinfo));
1394
hints.ai_flags = AI_CANONNAME;
1395
#ifdef AI_ADDRCONFIG
1396
hints.ai_flags |= AI_ADDRCONFIG;
1399
/* decodenetnum only works with addresses */
1231
1400
if (decodenetnum(hname, num)) {
1232
1401
if (fullhost != 0) {
1233
(void) sprintf(fullhost,
1234
"%u.%u.%u.%u", (u_int)((htonl(*num)>>24)&0xff),
1235
(u_int)((htonl(*num)>>16)&0xff), (u_int)((htonl(*num)>>8)&0xff),
1236
(u_int)(htonl(*num)&0xff));
1402
getnameinfo((struct sockaddr *)num, sockaddr_len,
1403
fullhost, sizeof(fullhost), NULL, 0,
1239
} else if ((hp = gethostbyname(hname)) != 0) {
1240
memmove((char *)num, hp->h_addr, sizeof(u_int32));
1407
} else if (getaddrinfo(hname, "ntp", &hints, &ai) == 0) {
1408
memmove((char *)num, ai->ai_addr, ai->ai_addrlen);
1241
1409
if (fullhost != 0)
1242
(void) strcpy(fullhost, hp->h_name);
1410
(void) strcpy(fullhost, ai->ai_canonname);
1245
1413
(void) fprintf(stderr, "***Can't find host %s\n", hname);
1380
1550
(void) fprintf(fp, "usage: %s", xcp->keyword);
1381
1551
for (i = 0; i < MAXARGS && xcp->arg[i] != NO; i++) {
1552
if (opt46 == 0 && (xcp->arg[i] & ~OPT) == ADD) {
1553
(void) fprintf(fp, " [ -4|-6 ]");
1382
1556
if (xcp->arg[i] & OPT)
1383
1557
(void) fprintf(fp, " [ %s ]", xcp->desc[i]);
1456
1632
if (pcmd->nargs == 0) {
1458
1634
(void) fprintf(fp, "current host is %s\n", currenthost);
1460
1636
(void) fprintf(fp, "no current host\n");
1461
} else if (openhost(pcmd->argval[0].string)) {
1641
if (pcmd->nargs == 2) {
1642
if (!strcmp("-4", pcmd->argval[i].string))
1643
ai_fam_templ = AF_INET;
1644
else if (!strcmp("-6", pcmd->argval[i].string))
1645
ai_fam_templ = AF_INET6;
1649
"current host remains %s\n", currenthost);
1651
(void) fprintf(fp, "still no current host\n");
1656
if (openhost(pcmd->argval[i].string)) {
1462
1657
(void) fprintf(fp, "current host set to %s\n", currenthost);