ntpq.c revision 1.16.2.2 1 /* $NetBSD: ntpq.c,v 1.16.2.2 2017/04/26 02:52:44 pgoyette Exp $ */
2
3 /*
4 * ntpq - query an NTP server using mode 6 commands
5 */
6 #include <config.h>
7 #include <stdio.h>
8 #include <ctype.h>
9 #include <signal.h>
10 #include <setjmp.h>
11 #include <sys/types.h>
12 #include <sys/time.h>
13 #ifdef HAVE_UNISTD_H
14 # include <unistd.h>
15 #endif
16 #ifdef HAVE_FCNTL_H
17 # include <fcntl.h>
18 #endif
19 #ifdef SYS_WINNT
20 # include <mswsock.h>
21 #endif
22 #include <isc/net.h>
23 #include <isc/result.h>
24
25 #include "ntpq.h"
26 #include "ntp_assert.h"
27 #include "ntp_stdlib.h"
28 #include "ntp_unixtime.h"
29 #include "ntp_calendar.h"
30 #include "ntp_select.h"
31 #include "ntp_assert.h"
32 #include "lib_strbuf.h"
33 #include "ntp_lineedit.h"
34 #include "ntp_debug.h"
35 #ifdef OPENSSL
36 #include "openssl/evp.h"
37 #include "openssl/objects.h"
38 #include "openssl/err.h"
39 #include "libssl_compat.h"
40 #endif
41 #include <ssl_applink.c>
42
43 #include "ntp_libopts.h"
44 #include "safecast.h"
45
46 #ifdef SYS_VXWORKS /* vxWorks needs mode flag -casey*/
47 # define open(name, flags) open(name, flags, 0777)
48 # define SERVER_PORT_NUM 123
49 #endif
50
51 /* we use COMMAND as an autogen keyword */
52 #ifdef COMMAND
53 # undef COMMAND
54 #endif
55
56 /*
57 * Because we potentially understand a lot of commands we will run
58 * interactive if connected to a terminal.
59 */
60 int interactive = 0; /* set to 1 when we should prompt */
61 const char *prompt = "ntpq> "; /* prompt to ask him about */
62
63 /*
64 * use old readvars behavior? --old-rv processing in ntpq resets
65 * this value based on the presence or absence of --old-rv. It is
66 * initialized to 1 here to maintain backward compatibility with
67 * libntpq clients such as ntpsnmpd, which are free to reset it as
68 * desired.
69 */
70 int old_rv = 1;
71
72 /*
73 * How should we display the refid?
74 * REFID_HASH, REFID_IPV4
75 */
76 te_Refid drefid = -1;
77
78 /*
79 * for get_systime()
80 */
81 s_char sys_precision; /* local clock precision (log2 s) */
82
83 /*
84 * Keyid used for authenticated requests. Obtained on the fly.
85 */
86 u_long info_auth_keyid = 0;
87
88 static int info_auth_keytype = NID_md5; /* MD5 */
89 static size_t info_auth_hashlen = 16; /* MD5 */
90 u_long current_time; /* needed by authkeys; not used */
91
92 /*
93 * Flag which indicates we should always send authenticated requests
94 */
95 int always_auth = 0;
96
97 /*
98 * Flag which indicates raw mode output.
99 */
100 int rawmode = 0;
101
102 /*
103 * Packet version number we use
104 */
105 u_char pktversion = NTP_OLDVERSION + 1;
106
107 /*
108 * Don't jump if no set jmp.
109 */
110 volatile int jump = 0;
111
112 /*
113 * Format values
114 */
115 #define PADDING 0
116 #define HA 1 /* host address */
117 #define NA 2 /* network address */
118 #define LP 3 /* leap (print in binary) */
119 #define RF 4 /* refid (sometimes string, sometimes not) */
120 #define AR 5 /* array of times */
121 #define FX 6 /* test flags */
122 #define TS 7 /* l_fp timestamp in hex */
123 #define OC 8 /* integer, print in octal */
124 #define EOV 255 /* end of table */
125
126 /*
127 * For the most part ntpq simply displays what ntpd provides in the
128 * mostly plain-text mode 6 responses. A few variable names are by
129 * default "cooked" to provide more human-friendly output.
130 */
131 const var_format cookedvars[] = {
132 { "leap", LP },
133 { "reach", OC },
134 { "refid", RF },
135 { "reftime", TS },
136 { "clock", TS },
137 { "org", TS },
138 { "rec", TS },
139 { "xmt", TS },
140 { "flash", FX },
141 { "srcadr", HA },
142 { "peeradr", HA }, /* compat with others */
143 { "dstadr", NA },
144 { "filtdelay", AR },
145 { "filtoffset", AR },
146 { "filtdisp", AR },
147 { "filterror", AR }, /* compat with others */
148 };
149
150
151
152 /*
153 * flasher bits
154 */
155 static const char *tstflagnames[] = {
156 "pkt_dup", /* TEST1 */
157 "pkt_bogus", /* TEST2 */
158 "pkt_unsync", /* TEST3 */
159 "pkt_denied", /* TEST4 */
160 "pkt_auth", /* TEST5 */
161 "pkt_stratum", /* TEST6 */
162 "pkt_header", /* TEST7 */
163 "pkt_autokey", /* TEST8 */
164 "pkt_crypto", /* TEST9 */
165 "peer_stratum", /* TEST10 */
166 "peer_dist", /* TEST11 */
167 "peer_loop", /* TEST12 */
168 "peer_unreach" /* TEST13 */
169 };
170
171
172 int ntpqmain (int, char **);
173 /*
174 * Built in command handler declarations
175 */
176 static int openhost (const char *, int);
177 static void dump_hex_printable(const void *, size_t);
178 static int sendpkt (void *, size_t);
179 static int getresponse (int, int, u_short *, size_t *, const char **, int);
180 static int sendrequest (int, associd_t, int, size_t, const char *);
181 static char * tstflags (u_long);
182 #ifndef BUILD_AS_LIB
183 static void getcmds (void);
184 #ifndef SYS_WINNT
185 static int abortcmd (void);
186 #endif /* SYS_WINNT */
187 static void docmd (const char *);
188 static void tokenize (const char *, char **, int *);
189 static int getarg (const char *, int, arg_v *);
190 #endif /* BUILD_AS_LIB */
191 static int findcmd (const char *, struct xcmd *,
192 struct xcmd *, struct xcmd **);
193 static int rtdatetolfp (char *, l_fp *);
194 static int decodearr (char *, int *, l_fp *);
195 static void help (struct parse *, FILE *);
196 static int helpsort (const void *, const void *);
197 static void printusage (struct xcmd *, FILE *);
198 static void timeout (struct parse *, FILE *);
199 static void auth_delay (struct parse *, FILE *);
200 static void host (struct parse *, FILE *);
201 static void ntp_poll (struct parse *, FILE *);
202 static void keyid (struct parse *, FILE *);
203 static void keytype (struct parse *, FILE *);
204 static void passwd (struct parse *, FILE *);
205 static void hostnames (struct parse *, FILE *);
206 static void setdebug (struct parse *, FILE *);
207 static void quit (struct parse *, FILE *);
208 static void showdrefid (struct parse *, FILE *);
209 static void version (struct parse *, FILE *);
210 static void raw (struct parse *, FILE *);
211 static void cooked (struct parse *, FILE *);
212 static void authenticate (struct parse *, FILE *);
213 static void ntpversion (struct parse *, FILE *);
214 static void warning (const char *, ...)
215 __attribute__((__format__(__printf__, 1, 2)));
216 static void error (const char *, ...)
217 __attribute__((__format__(__printf__, 1, 2)));
218 static u_long getkeyid (const char *);
219 static void atoascii (const char *, size_t, char *, size_t);
220 static void cookedprint (int, size_t, const char *, int, int, FILE *);
221 static void rawprint (int, size_t, const char *, int, int, FILE *);
222 static void startoutput (void);
223 static void output (FILE *, const char *, const char *);
224 static void endoutput (FILE *);
225 static void outputarr (FILE *, char *, int, l_fp *);
226 static int assoccmp (const void *, const void *);
227 static void on_ctrlc (void);
228 u_short varfmt (const char *);
229 static int my_easprintf (char**, const char *, ...) NTP_PRINTF(2, 3);
230 void ntpq_custom_opt_handler (tOptions *, tOptDesc *);
231
232 #ifdef OPENSSL
233 # ifdef HAVE_EVP_MD_DO_ALL_SORTED
234 static void list_md_fn(const EVP_MD *m, const char *from,
235 const char *to, void *arg );
236 # endif
237 #endif
238 static char *list_digest_names(void);
239
240 /*
241 * Built-in commands we understand
242 */
243 struct xcmd builtins[] = {
244 { "?", help, { OPT|NTP_STR, NO, NO, NO },
245 { "command", "", "", "" },
246 "tell the use and syntax of commands" },
247 { "help", help, { OPT|NTP_STR, NO, NO, NO },
248 { "command", "", "", "" },
249 "tell the use and syntax of commands" },
250 { "timeout", timeout, { OPT|NTP_UINT, NO, NO, NO },
251 { "msec", "", "", "" },
252 "set the primary receive time out" },
253 { "delay", auth_delay, { OPT|NTP_INT, NO, NO, NO },
254 { "msec", "", "", "" },
255 "set the delay added to encryption time stamps" },
256 { "host", host, { OPT|NTP_STR, OPT|NTP_STR, NO, NO },
257 { "-4|-6", "hostname", "", "" },
258 "specify the host whose NTP server we talk to" },
259 { "poll", ntp_poll, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
260 { "n", "verbose", "", "" },
261 "poll an NTP server in client mode `n' times" },
262 { "passwd", passwd, { OPT|NTP_STR, NO, NO, NO },
263 { "", "", "", "" },
264 "specify a password to use for authenticated requests"},
265 { "hostnames", hostnames, { OPT|NTP_STR, NO, NO, NO },
266 { "yes|no", "", "", "" },
267 "specify whether hostnames or net numbers are printed"},
268 { "debug", setdebug, { OPT|NTP_STR, NO, NO, NO },
269 { "no|more|less", "", "", "" },
270 "set/change debugging level" },
271 { "quit", quit, { NO, NO, NO, NO },
272 { "", "", "", "" },
273 "exit ntpq" },
274 { "exit", quit, { NO, NO, NO, NO },
275 { "", "", "", "" },
276 "exit ntpq" },
277 { "keyid", keyid, { OPT|NTP_UINT, NO, NO, NO },
278 { "key#", "", "", "" },
279 "set keyid to use for authenticated requests" },
280 { "drefid", showdrefid, { OPT|NTP_STR, NO, NO, NO },
281 { "hash|ipv4", "", "", "" },
282 "display refid's as IPv4 or hash" },
283 { "version", version, { NO, NO, NO, NO },
284 { "", "", "", "" },
285 "print version number" },
286 { "raw", raw, { NO, NO, NO, NO },
287 { "", "", "", "" },
288 "do raw mode variable output" },
289 { "cooked", cooked, { NO, NO, NO, NO },
290 { "", "", "", "" },
291 "do cooked mode variable output" },
292 { "authenticate", authenticate, { OPT|NTP_STR, NO, NO, NO },
293 { "yes|no", "", "", "" },
294 "always authenticate requests to this server" },
295 { "ntpversion", ntpversion, { OPT|NTP_UINT, NO, NO, NO },
296 { "version number", "", "", "" },
297 "set the NTP version number to use for requests" },
298 { "keytype", keytype, { OPT|NTP_STR, NO, NO, NO },
299 { "key type %s", "", "", "" },
300 NULL },
301 { 0, 0, { NO, NO, NO, NO },
302 { "", "", "", "" }, "" }
303 };
304
305
306 /*
307 * Default values we use.
308 */
309 #define DEFHOST "localhost" /* default host name */
310 #define DEFTIMEOUT 5 /* wait 5 seconds for 1st pkt */
311 #define DEFSTIMEOUT 3 /* and 3 more for each additional */
312 /*
313 * Requests are automatically retried once, so total timeout with no
314 * response is a bit over 2 * DEFTIMEOUT, or 10 seconds. At the other
315 * extreme, a request eliciting 32 packets of responses each for some
316 * reason nearly DEFSTIMEOUT seconds after the prior in that series,
317 * with a single packet dropped, would take around 32 * DEFSTIMEOUT, or
318 * 93 seconds to fail each of two times, or 186 seconds.
319 * Some commands involve a series of requests, such as "peers" and
320 * "mrulist", so the cumulative timeouts are even longer for those.
321 */
322 #define DEFDELAY 0x51EB852 /* 20 milliseconds, l_fp fraction */
323 #define LENHOSTNAME 256 /* host name is 256 characters long */
324 #define MAXCMDS 100 /* maximum commands on cmd line */
325 #define MAXHOSTS 200 /* maximum hosts on cmd line */
326 #define MAXLINE 512 /* maximum line length */
327 #define MAXTOKENS (1+MAXARGS+2) /* maximum number of usable tokens */
328 #define MAXVARLEN 256 /* maximum length of a variable name */
329 #define MAXVALLEN 2048 /* maximum length of a variable value */
330 #define MAXOUTLINE 72 /* maximum length of an output line */
331 #define SCREENWIDTH 76 /* nominal screen width in columns */
332
333 /*
334 * Some variables used and manipulated locally
335 */
336 struct sock_timeval tvout = { DEFTIMEOUT, 0 }; /* time out for reads */
337 struct sock_timeval tvsout = { DEFSTIMEOUT, 0 };/* secondary time out */
338 l_fp delay_time; /* delay time */
339 char currenthost[LENHOSTNAME]; /* current host name */
340 int currenthostisnum; /* is prior text from IP? */
341 struct sockaddr_in hostaddr; /* host address */
342 int showhostnames = 1; /* show host names by default */
343 int wideremote = 0; /* show wide remote names? */
344
345 int ai_fam_templ; /* address family */
346 int ai_fam_default; /* default address family */
347 SOCKET sockfd; /* fd socket is opened on */
348 int havehost = 0; /* set to 1 when host open */
349 int s_port = 0;
350 struct servent *server_entry = NULL; /* server entry for ntp */
351
352
353 /*
354 * Sequence number used for requests. It is incremented before
355 * it is used.
356 */
357 u_short sequence;
358
359 /*
360 * Holds data returned from queries. Declare buffer long to be sure of
361 * alignment.
362 */
363 #define DATASIZE (MAXFRAGS*480) /* maximum amount of data */
364 long pktdata[DATASIZE/sizeof(long)];
365
366 /*
367 * assoc_cache[] is a dynamic array which allows references to
368 * associations using &1 ... &N for n associations, avoiding manual
369 * lookup of the current association IDs for a given ntpd. It also
370 * caches the status word for each association, retrieved incidentally.
371 */
372 struct association * assoc_cache;
373 u_int assoc_cache_slots;/* count of allocated array entries */
374 u_int numassoc; /* number of cached associations */
375
376 /*
377 * For commands typed on the command line (with the -c option)
378 */
379 size_t numcmds = 0;
380 const char *ccmds[MAXCMDS];
381 #define ADDCMD(cp) if (numcmds < MAXCMDS) ccmds[numcmds++] = (cp)
382
383 /*
384 * When multiple hosts are specified.
385 */
386
387 u_int numhosts;
388
389 chost chosts[MAXHOSTS];
390 #define ADDHOST(cp) \
391 do { \
392 if (numhosts < MAXHOSTS) { \
393 chosts[numhosts].name = (cp); \
394 chosts[numhosts].fam = ai_fam_templ; \
395 numhosts++; \
396 } \
397 } while (0)
398
399 /*
400 * Macro definitions we use
401 */
402 #define ISSPACE(c) ((c) == ' ' || (c) == '\t')
403 #define ISEOL(c) ((c) == '\n' || (c) == '\r' || (c) == '\0')
404 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
405
406 /*
407 * Jump buffer for longjumping back to the command level
408 */
409 jmp_buf interrupt_buf;
410
411 /*
412 * Points at file being currently printed into
413 */
414 FILE *current_output;
415
416 /*
417 * Command table imported from ntpdc_ops.c
418 */
419 extern struct xcmd opcmds[];
420
421 char const *progname;
422
423 #ifdef NO_MAIN_ALLOWED
424 #ifndef BUILD_AS_LIB
425 CALL(ntpq,"ntpq",ntpqmain);
426
427 void clear_globals(void)
428 {
429 extern int ntp_optind;
430 showhostnames = 0; /* don'tshow host names by default */
431 ntp_optind = 0;
432 server_entry = NULL; /* server entry for ntp */
433 havehost = 0; /* set to 1 when host open */
434 numassoc = 0; /* number of cached associations */
435 numcmds = 0;
436 numhosts = 0;
437 }
438 #endif /* !BUILD_AS_LIB */
439 #endif /* NO_MAIN_ALLOWED */
440
441 /*
442 * main - parse arguments and handle options
443 */
444 #ifndef NO_MAIN_ALLOWED
445 int
446 main(
447 int argc,
448 char *argv[]
449 )
450 {
451 return ntpqmain(argc, argv);
452 }
453 #endif
454
455 #ifndef BUILD_AS_LIB
456 int
457 ntpqmain(
458 int argc,
459 char *argv[]
460 )
461 {
462 u_int ihost;
463 size_t icmd;
464
465
466 #ifdef SYS_VXWORKS
467 clear_globals();
468 taskPrioritySet(taskIdSelf(), 100 );
469 #endif
470
471 delay_time.l_ui = 0;
472 delay_time.l_uf = DEFDELAY;
473
474 init_lib(); /* sets up ipv4_works, ipv6_works */
475 ssl_applink();
476 init_auth();
477
478 /* Check to see if we have IPv6. Otherwise default to IPv4 */
479 if (!ipv6_works)
480 ai_fam_default = AF_INET;
481
482 /* Fixup keytype's help based on available digest names */
483
484 {
485 char *list;
486 char *msg;
487
488 list = list_digest_names();
489 for (icmd = 0; icmd < sizeof(builtins)/sizeof(builtins[0]); icmd++) {
490 if (strcmp("keytype", builtins[icmd].keyword) == 0)
491 break;
492 }
493
494 /* CID: 1295478 */
495 /* This should only "trip" if "keytype" is removed from builtins */
496 INSIST(icmd < sizeof(builtins)/sizeof(builtins[0]));
497
498 #ifdef OPENSSL
499 builtins[icmd].desc[0] = "digest-name";
500 my_easprintf(&msg,
501 "set key type to use for authenticated requests, one of:%s",
502 list);
503 #else
504 builtins[icmd].desc[0] = "md5";
505 my_easprintf(&msg,
506 "set key type to use for authenticated requests (%s)",
507 list);
508 #endif
509 builtins[icmd].comment = msg;
510 free(list);
511 }
512
513 progname = argv[0];
514
515 {
516 int optct = ntpOptionProcess(&ntpqOptions, argc, argv);
517 argc -= optct;
518 argv += optct;
519 }
520
521 /*
522 * Process options other than -c and -p, which are specially
523 * handled by ntpq_custom_opt_handler().
524 */
525
526 debug = OPT_VALUE_SET_DEBUG_LEVEL;
527
528 if (HAVE_OPT(IPV4))
529 ai_fam_templ = AF_INET;
530 else if (HAVE_OPT(IPV6))
531 ai_fam_templ = AF_INET6;
532 else
533 ai_fam_templ = ai_fam_default;
534
535 if (HAVE_OPT(INTERACTIVE))
536 interactive = 1;
537
538 if (HAVE_OPT(NUMERIC))
539 showhostnames = 0;
540
541 if (HAVE_OPT(WIDE))
542 wideremote = 1;
543
544 old_rv = HAVE_OPT(OLD_RV);
545
546 drefid = OPT_VALUE_REFID;
547
548 if (0 == argc) {
549 ADDHOST(DEFHOST);
550 } else {
551 for (ihost = 0; ihost < (u_int)argc; ihost++) {
552 if ('-' == *argv[ihost]) {
553 //
554 // If I really cared I'd also check:
555 // 0 == argv[ihost][2]
556 //
557 // and there are other cases as well...
558 //
559 if ('4' == argv[ihost][1]) {
560 ai_fam_templ = AF_INET;
561 continue;
562 } else if ('6' == argv[ihost][1]) {
563 ai_fam_templ = AF_INET6;
564 continue;
565 } else {
566 // XXX Throw a usage error
567 }
568 }
569 ADDHOST(argv[ihost]);
570 }
571 }
572
573 if (numcmds == 0 && interactive == 0
574 && isatty(fileno(stdin)) && isatty(fileno(stderr))) {
575 interactive = 1;
576 }
577
578 set_ctrl_c_hook(on_ctrlc);
579 #ifndef SYS_WINNT /* Under NT cannot handle SIGINT, WIN32 spawns a handler */
580 if (interactive)
581 push_ctrl_c_handler(abortcmd);
582 #endif /* SYS_WINNT */
583
584 if (numcmds == 0) {
585 (void) openhost(chosts[0].name, chosts[0].fam);
586 getcmds();
587 } else {
588 for (ihost = 0; ihost < numhosts; ihost++) {
589 if (openhost(chosts[ihost].name, chosts[ihost].fam))
590 for (icmd = 0; icmd < numcmds; icmd++)
591 docmd(ccmds[icmd]);
592 }
593 }
594 #ifdef SYS_WINNT
595 WSACleanup();
596 #endif /* SYS_WINNT */
597 return 0;
598 }
599 #endif /* !BUILD_AS_LIB */
600
601 /*
602 * openhost - open a socket to a host
603 */
604 static int
605 openhost(
606 const char *hname,
607 int fam
608 )
609 {
610 const char svc[] = "ntp";
611 char temphost[LENHOSTNAME];
612 int a_info, i;
613 struct addrinfo hints, *ai;
614 sockaddr_u addr;
615 size_t octets;
616 register const char *cp;
617 char name[LENHOSTNAME];
618
619 /*
620 * We need to get by the [] if they were entered
621 */
622
623 cp = hname;
624
625 if (*cp == '[') {
626 cp++;
627 for (i = 0; *cp && *cp != ']'; cp++, i++)
628 name[i] = *cp;
629 if (*cp == ']') {
630 name[i] = '\0';
631 hname = name;
632 } else {
633 return 0;
634 }
635 }
636
637 /*
638 * First try to resolve it as an ip address and if that fails,
639 * do a fullblown (dns) lookup. That way we only use the dns
640 * when it is needed and work around some implementations that
641 * will return an "IPv4-mapped IPv6 address" address if you
642 * give it an IPv4 address to lookup.
643 */
644 ZERO(hints);
645 hints.ai_family = fam;
646 hints.ai_protocol = IPPROTO_UDP;
647 hints.ai_socktype = SOCK_DGRAM;
648 hints.ai_flags = Z_AI_NUMERICHOST;
649 ai = NULL;
650
651 a_info = getaddrinfo(hname, svc, &hints, &ai);
652 if (a_info == EAI_NONAME
653 #ifdef EAI_NODATA
654 || a_info == EAI_NODATA
655 #endif
656 ) {
657 hints.ai_flags = AI_CANONNAME;
658 #ifdef AI_ADDRCONFIG
659 hints.ai_flags |= AI_ADDRCONFIG;
660 #endif
661 a_info = getaddrinfo(hname, svc, &hints, &ai);
662 }
663 #ifdef AI_ADDRCONFIG
664 /* Some older implementations don't like AI_ADDRCONFIG. */
665 if (a_info == EAI_BADFLAGS) {
666 hints.ai_flags &= ~AI_ADDRCONFIG;
667 a_info = getaddrinfo(hname, svc, &hints, &ai);
668 }
669 #endif
670 if (a_info != 0) {
671 fprintf(stderr, "%s\n", gai_strerror(a_info));
672 return 0;
673 }
674
675 INSIST(ai != NULL);
676 ZERO(addr);
677 octets = min(sizeof(addr), ai->ai_addrlen);
678 memcpy(&addr, ai->ai_addr, octets);
679
680 if (ai->ai_canonname == NULL) {
681 strlcpy(temphost, stoa(&addr), sizeof(temphost));
682 currenthostisnum = TRUE;
683 } else {
684 strlcpy(temphost, ai->ai_canonname, sizeof(temphost));
685 currenthostisnum = FALSE;
686 }
687
688 if (debug > 2)
689 printf("Opening host %s (%s)\n",
690 temphost,
691 (ai->ai_family == AF_INET)
692 ? "AF_INET"
693 : (ai->ai_family == AF_INET6)
694 ? "AF_INET6"
695 : "AF-???"
696 );
697
698 if (havehost == 1) {
699 if (debug > 2)
700 printf("Closing old host %s\n", currenthost);
701 closesocket(sockfd);
702 havehost = 0;
703 }
704 strlcpy(currenthost, temphost, sizeof(currenthost));
705
706 /* port maps to the same location in both families */
707 s_port = NSRCPORT(&addr);
708 #ifdef SYS_VXWORKS
709 ((struct sockaddr_in6 *)&hostaddr)->sin6_port = htons(SERVER_PORT_NUM);
710 if (ai->ai_family == AF_INET)
711 *(struct sockaddr_in *)&hostaddr=
712 *((struct sockaddr_in *)ai->ai_addr);
713 else
714 *(struct sockaddr_in6 *)&hostaddr=
715 *((struct sockaddr_in6 *)ai->ai_addr);
716 #endif /* SYS_VXWORKS */
717
718 #ifdef SYS_WINNT
719 {
720 int optionValue = SO_SYNCHRONOUS_NONALERT;
721 int err;
722
723 err = setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
724 (char *)&optionValue, sizeof(optionValue));
725 if (err) {
726 mfprintf(stderr,
727 "setsockopt(SO_SYNCHRONOUS_NONALERT)"
728 " error: %m\n");
729 freeaddrinfo(ai);
730 exit(1);
731 }
732 }
733 #endif /* SYS_WINNT */
734
735 sockfd = socket(ai->ai_family, ai->ai_socktype,
736 ai->ai_protocol);
737 if (sockfd == INVALID_SOCKET) {
738 error("socket");
739 freeaddrinfo(ai);
740 return 0;
741 }
742
743
744 #ifdef NEED_RCVBUF_SLOP
745 # ifdef SO_RCVBUF
746 { int rbufsize = DATASIZE + 2048; /* 2K for slop */
747 if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
748 &rbufsize, sizeof(int)) == -1)
749 error("setsockopt");
750 }
751 # endif
752 #endif
753
754 if
755 #ifdef SYS_VXWORKS
756 (connect(sockfd, (struct sockaddr *)&hostaddr,
757 sizeof(hostaddr)) == -1)
758 #else
759 (connect(sockfd, (struct sockaddr *)ai->ai_addr,
760 ai->ai_addrlen) == -1)
761 #endif /* SYS_VXWORKS */
762 {
763 error("connect");
764 freeaddrinfo(ai);
765 return 0;
766 }
767 freeaddrinfo(ai);
768 havehost = 1;
769 numassoc = 0;
770
771 return 1;
772 }
773
774
775 static void
776 dump_hex_printable(
777 const void * data,
778 size_t len
779 )
780 {
781 /* every line shows at most 16 bytes, so we need a buffer of
782 * 4 * 16 (2 xdigits, 1 char, one sep for xdigits)
783 * + 2 * 1 (block separators)
784 * + <LF> + <NUL>
785 *---------------
786 * 68 bytes
787 */
788 static const char s_xdig[16] = "0123456789ABCDEF";
789
790 char lbuf[68];
791 int ch, rowlen;
792 const u_char * cdata = data;
793 char *xptr, *pptr;
794
795 while (len) {
796 memset(lbuf, ' ', sizeof(lbuf));
797 xptr = lbuf;
798 pptr = lbuf + 3*16 + 2;
799
800 rowlen = (len > 16) ? 16 : (int)len;
801 len -= rowlen;
802
803 do {
804 ch = *cdata++;
805
806 *xptr++ = s_xdig[ch >> 4 ];
807 *xptr++ = s_xdig[ch & 0x0F];
808 if (++xptr == lbuf + 3*8)
809 ++xptr;
810
811 *pptr++ = isprint(ch) ? (char)ch : '.';
812 } while (--rowlen);
813
814 *pptr++ = '\n';
815 *pptr = '\0';
816 fputs(lbuf, stdout);
817 }
818 }
819
820
821 /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
822 /*
823 * sendpkt - send a packet to the remote host
824 */
825 static int
826 sendpkt(
827 void * xdata,
828 size_t xdatalen
829 )
830 {
831 if (debug >= 3)
832 printf("Sending %zu octets\n", xdatalen);
833
834 if (send(sockfd, xdata, xdatalen, 0) == -1) {
835 warning("write to %s failed", currenthost);
836 return -1;
837 }
838
839 if (debug >= 4) {
840 printf("Request packet:\n");
841 dump_hex_printable(xdata, xdatalen);
842 }
843 return 0;
844 }
845
846 /*
847 * getresponse - get a (series of) response packet(s) and return the data
848 */
849 static int
850 getresponse(
851 int opcode,
852 int associd,
853 u_short *rstatus,
854 size_t *rsize,
855 const char **rdata,
856 int timeo
857 )
858 {
859 struct ntp_control rpkt;
860 struct sock_timeval tvo;
861 u_short offsets[MAXFRAGS+1];
862 u_short counts[MAXFRAGS+1];
863 u_short offset;
864 u_short count;
865 size_t numfrags;
866 size_t f;
867 size_t ff;
868 int seenlastfrag;
869 int shouldbesize;
870 fd_set fds;
871 int n;
872 int errcode;
873 /* absolute timeout checks. Not 'time_t' by intention! */
874 uint32_t tobase; /* base value for timeout */
875 uint32_t tospan; /* timeout span (max delay) */
876 uint32_t todiff; /* current delay */
877
878 memset(offsets, 0, sizeof(offsets));
879 memset(counts , 0, sizeof(counts ));
880
881 /*
882 * This is pretty tricky. We may get between 1 and MAXFRAG packets
883 * back in response to the request. We peel the data out of
884 * each packet and collect it in one long block. When the last
885 * packet in the sequence is received we'll know how much data we
886 * should have had. Note we use one long time out, should reconsider.
887 */
888 *rsize = 0;
889 if (rstatus)
890 *rstatus = 0;
891 *rdata = (char *)pktdata;
892
893 numfrags = 0;
894 seenlastfrag = 0;
895
896 tobase = (uint32_t)time(NULL);
897
898 FD_ZERO(&fds);
899
900 /*
901 * Loop until we have an error or a complete response. Nearly all
902 * code paths to loop again use continue.
903 */
904 for (;;) {
905
906 if (numfrags == 0)
907 tvo = tvout;
908 else
909 tvo = tvsout;
910 tospan = (uint32_t)tvo.tv_sec + (tvo.tv_usec != 0);
911
912 FD_SET(sockfd, &fds);
913 n = select(sockfd+1, &fds, NULL, NULL, &tvo);
914 if (n == -1) {
915 #if !defined(SYS_WINNT) && defined(EINTR)
916 /* Windows does not know about EINTR (until very
917 * recently) and the handling of console events
918 * is *very* different from POSIX/UNIX signal
919 * handling anyway.
920 *
921 * Under non-windows targets we map EINTR as
922 * 'last packet was received' and try to exit
923 * the receive sequence.
924 */
925 if (errno == EINTR) {
926 seenlastfrag = 1;
927 goto maybe_final;
928 }
929 #endif
930 warning("select fails");
931 return -1;
932 }
933
934 /*
935 * Check if this is already too late. Trash the data and
936 * fake a timeout if this is so.
937 */
938 todiff = (((uint32_t)time(NULL)) - tobase) & 0x7FFFFFFFu;
939 if ((n > 0) && (todiff > tospan)) {
940 n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
941 n -= n; /* faked timeout return from 'select()',
942 * execute RMW cycle on 'n'
943 */
944 }
945
946 if (n <= 0) {
947 /*
948 * Timed out. Return what we have
949 */
950 if (numfrags == 0) {
951 if (timeo)
952 fprintf(stderr,
953 "%s: timed out, nothing received\n",
954 currenthost);
955 return ERR_TIMEOUT;
956 }
957 if (timeo)
958 fprintf(stderr,
959 "%s: timed out with incomplete data\n",
960 currenthost);
961 if (debug) {
962 fprintf(stderr,
963 "ERR_INCOMPLETE: Received fragments:\n");
964 for (f = 0; f < numfrags; f++)
965 fprintf(stderr,
966 "%2u: %5d %5d\t%3d octets\n",
967 (u_int)f, offsets[f],
968 offsets[f] +
969 counts[f],
970 counts[f]);
971 fprintf(stderr,
972 "last fragment %sreceived\n",
973 (seenlastfrag)
974 ? ""
975 : "not ");
976 }
977 return ERR_INCOMPLETE;
978 }
979
980 n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
981 if (n < 0) {
982 warning("read");
983 return -1;
984 }
985
986 if (debug >= 4) {
987 printf("Response packet:\n");
988 dump_hex_printable(&rpkt, n);
989 }
990
991 /*
992 * Check for format errors. Bug proofing.
993 */
994 if (n < (int)CTL_HEADER_LEN) {
995 if (debug)
996 printf("Short (%d byte) packet received\n", n);
997 continue;
998 }
999 if (PKT_VERSION(rpkt.li_vn_mode) > NTP_VERSION
1000 || PKT_VERSION(rpkt.li_vn_mode) < NTP_OLDVERSION) {
1001 if (debug)
1002 printf("Packet received with version %d\n",
1003 PKT_VERSION(rpkt.li_vn_mode));
1004 continue;
1005 }
1006 if (PKT_MODE(rpkt.li_vn_mode) != MODE_CONTROL) {
1007 if (debug)
1008 printf("Packet received with mode %d\n",
1009 PKT_MODE(rpkt.li_vn_mode));
1010 continue;
1011 }
1012 if (!CTL_ISRESPONSE(rpkt.r_m_e_op)) {
1013 if (debug)
1014 printf("Received request packet, wanted response\n");
1015 continue;
1016 }
1017
1018 /*
1019 * Check opcode and sequence number for a match.
1020 * Could be old data getting to us.
1021 */
1022 if (ntohs(rpkt.sequence) != sequence) {
1023 if (debug)
1024 printf("Received sequnce number %d, wanted %d\n",
1025 ntohs(rpkt.sequence), sequence);
1026 continue;
1027 }
1028 if (CTL_OP(rpkt.r_m_e_op) != opcode) {
1029 if (debug)
1030 printf(
1031 "Received opcode %d, wanted %d (sequence number okay)\n",
1032 CTL_OP(rpkt.r_m_e_op), opcode);
1033 continue;
1034 }
1035
1036 /*
1037 * Check the error code. If non-zero, return it.
1038 */
1039 if (CTL_ISERROR(rpkt.r_m_e_op)) {
1040 errcode = (ntohs(rpkt.status) >> 8) & 0xff;
1041 if (CTL_ISMORE(rpkt.r_m_e_op))
1042 TRACE(1, ("Error code %d received on not-final packet\n",
1043 errcode));
1044 if (errcode == CERR_UNSPEC)
1045 return ERR_UNSPEC;
1046 return errcode;
1047 }
1048
1049 /*
1050 * Check the association ID to make sure it matches what
1051 * we sent.
1052 */
1053 if (ntohs(rpkt.associd) != associd) {
1054 TRACE(1, ("Association ID %d doesn't match expected %d\n",
1055 ntohs(rpkt.associd), associd));
1056 /*
1057 * Hack for silly fuzzballs which, at the time of writing,
1058 * return an assID of sys.peer when queried for system variables.
1059 */
1060 #ifdef notdef
1061 continue;
1062 #endif
1063 }
1064
1065 /*
1066 * Collect offset and count. Make sure they make sense.
1067 */
1068 offset = ntohs(rpkt.offset);
1069 count = ntohs(rpkt.count);
1070
1071 /*
1072 * validate received payload size is padded to next 32-bit
1073 * boundary and no smaller than claimed by rpkt.count
1074 */
1075 if (n & 0x3) {
1076 TRACE(1, ("Response packet not padded, size = %d\n",
1077 n));
1078 continue;
1079 }
1080
1081 shouldbesize = (CTL_HEADER_LEN + count + 3) & ~3;
1082
1083 if (n < shouldbesize) {
1084 printf("Response packet claims %u octets payload, above %ld received\n",
1085 count, (long)(n - CTL_HEADER_LEN));
1086 return ERR_INCOMPLETE;
1087 }
1088
1089 if (debug >= 3 && shouldbesize > n) {
1090 u_int32 key;
1091 u_int32 *lpkt;
1092 int maclen;
1093
1094 /*
1095 * Usually we ignore authentication, but for debugging purposes
1096 * we watch it here.
1097 */
1098 /* round to 8 octet boundary */
1099 shouldbesize = (shouldbesize + 7) & ~7;
1100
1101 maclen = n - shouldbesize;
1102 if (maclen >= (int)MIN_MAC_LEN) {
1103 printf(
1104 "Packet shows signs of authentication (total %d, data %d, mac %d)\n",
1105 n, shouldbesize, maclen);
1106 lpkt = (u_int32 *)&rpkt;
1107 printf("%08lx %08lx %08lx %08lx %08lx %08lx\n",
1108 (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) - 3]),
1109 (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) - 2]),
1110 (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) - 1]),
1111 (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32)]),
1112 (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) + 1]),
1113 (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) + 2]));
1114 key = ntohl(lpkt[(n - maclen) / sizeof(u_int32)]);
1115 printf("Authenticated with keyid %lu\n", (u_long)key);
1116 if (key != 0 && key != info_auth_keyid) {
1117 printf("We don't know that key\n");
1118 } else {
1119 if (authdecrypt(key, (u_int32 *)&rpkt,
1120 n - maclen, maclen)) {
1121 printf("Auth okay!\n");
1122 } else {
1123 printf("Auth failed!\n");
1124 }
1125 }
1126 }
1127 }
1128
1129 TRACE(2, ("Got packet, size = %d\n", n));
1130 if (count > (n - CTL_HEADER_LEN)) {
1131 TRACE(1, ("Received count of %u octets, data in packet is %ld\n",
1132 count, (long)n - CTL_HEADER_LEN));
1133 continue;
1134 }
1135 if (count == 0 && CTL_ISMORE(rpkt.r_m_e_op)) {
1136 TRACE(1, ("Received count of 0 in non-final fragment\n"));
1137 continue;
1138 }
1139 if (offset + count > sizeof(pktdata)) {
1140 TRACE(1, ("Offset %u, count %u, too big for buffer\n",
1141 offset, count));
1142 return ERR_TOOMUCH;
1143 }
1144 if (seenlastfrag && !CTL_ISMORE(rpkt.r_m_e_op)) {
1145 TRACE(1, ("Received second last fragment packet\n"));
1146 continue;
1147 }
1148
1149 /*
1150 * So far, so good. Record this fragment, making sure it doesn't
1151 * overlap anything.
1152 */
1153 TRACE(2, ("Packet okay\n"));
1154
1155 if (numfrags > (MAXFRAGS - 1)) {
1156 TRACE(2, ("Number of fragments exceeds maximum %d\n",
1157 MAXFRAGS - 1));
1158 return ERR_TOOMUCH;
1159 }
1160
1161 /*
1162 * Find the position for the fragment relative to any
1163 * previously received.
1164 */
1165 for (f = 0;
1166 f < numfrags && offsets[f] < offset;
1167 f++) {
1168 /* empty body */ ;
1169 }
1170
1171 if (f < numfrags && offset == offsets[f]) {
1172 TRACE(1, ("duplicate %u octets at %u ignored, prior %u at %u\n",
1173 count, offset, counts[f], offsets[f]));
1174 continue;
1175 }
1176
1177 if (f > 0 && (offsets[f-1] + counts[f-1]) > offset) {
1178 TRACE(1, ("received frag at %u overlaps with %u octet frag at %u\n",
1179 offset, counts[f-1], offsets[f-1]));
1180 continue;
1181 }
1182
1183 if (f < numfrags && (offset + count) > offsets[f]) {
1184 TRACE(1, ("received %u octet frag at %u overlaps with frag at %u\n",
1185 count, offset, offsets[f]));
1186 continue;
1187 }
1188
1189 for (ff = numfrags; ff > f; ff--) {
1190 offsets[ff] = offsets[ff-1];
1191 counts[ff] = counts[ff-1];
1192 }
1193 offsets[f] = offset;
1194 counts[f] = count;
1195 numfrags++;
1196
1197 /*
1198 * Got that stuffed in right. Figure out if this was the last.
1199 * Record status info out of the last packet.
1200 */
1201 if (!CTL_ISMORE(rpkt.r_m_e_op)) {
1202 seenlastfrag = 1;
1203 if (rstatus != 0)
1204 *rstatus = ntohs(rpkt.status);
1205 }
1206
1207 /*
1208 * Copy the data into the data buffer, and bump the
1209 * timout base in case we need more.
1210 */
1211 memcpy((char *)pktdata + offset, &rpkt.u, count);
1212 tobase = (uint32_t)time(NULL);
1213
1214 /*
1215 * If we've seen the last fragment, look for holes in the sequence.
1216 * If there aren't any, we're done.
1217 */
1218 #if !defined(SYS_WINNT) && defined(EINTR)
1219 maybe_final:
1220 #endif
1221
1222 if (seenlastfrag && offsets[0] == 0) {
1223 for (f = 1; f < numfrags; f++)
1224 if (offsets[f-1] + counts[f-1] !=
1225 offsets[f])
1226 break;
1227 if (f == numfrags) {
1228 *rsize = offsets[f-1] + counts[f-1];
1229 TRACE(1, ("%lu packets reassembled into response\n",
1230 (u_long)numfrags));
1231 return 0;
1232 }
1233 }
1234 } /* giant for (;;) collecting response packets */
1235 } /* getresponse() */
1236
1237
1238 /*
1239 * sendrequest - format and send a request packet
1240 */
1241 static int
1242 sendrequest(
1243 int opcode,
1244 associd_t associd,
1245 int auth,
1246 size_t qsize,
1247 const char *qdata
1248 )
1249 {
1250 struct ntp_control qpkt;
1251 size_t pktsize;
1252 u_long key_id;
1253 char * pass;
1254 size_t maclen;
1255
1256 /*
1257 * Check to make sure the data will fit in one packet
1258 */
1259 if (qsize > CTL_MAX_DATA_LEN) {
1260 fprintf(stderr,
1261 "***Internal error! qsize (%zu) too large\n",
1262 qsize);
1263 return 1;
1264 }
1265
1266 /*
1267 * Fill in the packet
1268 */
1269 qpkt.li_vn_mode = PKT_LI_VN_MODE(0, pktversion, MODE_CONTROL);
1270 qpkt.r_m_e_op = (u_char)(opcode & CTL_OP_MASK);
1271 qpkt.sequence = htons(sequence);
1272 qpkt.status = 0;
1273 qpkt.associd = htons((u_short)associd);
1274 qpkt.offset = 0;
1275 qpkt.count = htons((u_short)qsize);
1276
1277 pktsize = CTL_HEADER_LEN;
1278
1279 /*
1280 * If we have data, copy and pad it out to a 32-bit boundary.
1281 */
1282 if (qsize > 0) {
1283 memcpy(&qpkt.u, qdata, (size_t)qsize);
1284 pktsize += qsize;
1285 while (pktsize & (sizeof(u_int32) - 1)) {
1286 qpkt.u.data[qsize++] = 0;
1287 pktsize++;
1288 }
1289 }
1290
1291 /*
1292 * If it isn't authenticated we can just send it. Otherwise
1293 * we're going to have to think about it a little.
1294 */
1295 if (!auth && !always_auth) {
1296 return sendpkt(&qpkt, pktsize);
1297 }
1298
1299 /*
1300 * Pad out packet to a multiple of 8 octets to be sure
1301 * receiver can handle it.
1302 */
1303 while (pktsize & 7) {
1304 qpkt.u.data[qsize++] = 0;
1305 pktsize++;
1306 }
1307
1308 /*
1309 * Get the keyid and the password if we don't have one.
1310 */
1311 if (info_auth_keyid == 0) {
1312 key_id = getkeyid("Keyid: ");
1313 if (key_id == 0 || key_id > NTP_MAXKEY) {
1314 fprintf(stderr,
1315 "Invalid key identifier\n");
1316 return 1;
1317 }
1318 info_auth_keyid = key_id;
1319 }
1320 if (!authistrusted(info_auth_keyid)) {
1321 pass = getpass_keytype(info_auth_keytype);
1322 if ('\0' == pass[0]) {
1323 fprintf(stderr, "Invalid password\n");
1324 return 1;
1325 }
1326 authusekey(info_auth_keyid, info_auth_keytype,
1327 (u_char *)pass);
1328 authtrust(info_auth_keyid, 1);
1329 }
1330
1331 /*
1332 * Do the encryption.
1333 */
1334 maclen = authencrypt(info_auth_keyid, (void *)&qpkt, pktsize);
1335 if (!maclen) {
1336 fprintf(stderr, "Key not found\n");
1337 return 1;
1338 } else if ((size_t)maclen != (info_auth_hashlen + sizeof(keyid_t))) {
1339 fprintf(stderr,
1340 "%zu octet MAC, %zu expected with %zu octet digest\n",
1341 maclen, (info_auth_hashlen + sizeof(keyid_t)),
1342 info_auth_hashlen);
1343 return 1;
1344 }
1345
1346 return sendpkt((char *)&qpkt, pktsize + maclen);
1347 }
1348
1349
1350 /*
1351 * show_error_msg - display the error text for a mode 6 error response.
1352 */
1353 void
1354 show_error_msg(
1355 int m6resp,
1356 associd_t associd
1357 )
1358 {
1359 if (numhosts > 1)
1360 fprintf(stderr, "server=%s ", currenthost);
1361
1362 switch (m6resp) {
1363
1364 case CERR_BADFMT:
1365 fprintf(stderr,
1366 "***Server reports a bad format request packet\n");
1367 break;
1368
1369 case CERR_PERMISSION:
1370 fprintf(stderr,
1371 "***Server disallowed request (authentication?)\n");
1372 break;
1373
1374 case CERR_BADOP:
1375 fprintf(stderr,
1376 "***Server reports a bad opcode in request\n");
1377 break;
1378
1379 case CERR_BADASSOC:
1380 fprintf(stderr,
1381 "***Association ID %d unknown to server\n",
1382 associd);
1383 break;
1384
1385 case CERR_UNKNOWNVAR:
1386 fprintf(stderr,
1387 "***A request variable unknown to the server\n");
1388 break;
1389
1390 case CERR_BADVALUE:
1391 fprintf(stderr,
1392 "***Server indicates a request variable was bad\n");
1393 break;
1394
1395 case ERR_UNSPEC:
1396 fprintf(stderr,
1397 "***Server returned an unspecified error\n");
1398 break;
1399
1400 case ERR_TIMEOUT:
1401 fprintf(stderr, "***Request timed out\n");
1402 break;
1403
1404 case ERR_INCOMPLETE:
1405 fprintf(stderr,
1406 "***Response from server was incomplete\n");
1407 break;
1408
1409 case ERR_TOOMUCH:
1410 fprintf(stderr,
1411 "***Buffer size exceeded for returned data\n");
1412 break;
1413
1414 default:
1415 fprintf(stderr,
1416 "***Server returns unknown error code %d\n",
1417 m6resp);
1418 }
1419 }
1420
1421 /*
1422 * doquery - send a request and process the response, displaying
1423 * error messages for any error responses.
1424 */
1425 int
1426 doquery(
1427 int opcode,
1428 associd_t associd,
1429 int auth,
1430 size_t qsize,
1431 const char *qdata,
1432 u_short *rstatus,
1433 size_t *rsize,
1434 const char **rdata
1435 )
1436 {
1437 return doqueryex(opcode, associd, auth, qsize, qdata, rstatus,
1438 rsize, rdata, FALSE);
1439 }
1440
1441
1442 /*
1443 * doqueryex - send a request and process the response, optionally
1444 * displaying error messages for any error responses.
1445 */
1446 int
1447 doqueryex(
1448 int opcode,
1449 associd_t associd,
1450 int auth,
1451 size_t qsize,
1452 const char *qdata,
1453 u_short *rstatus,
1454 size_t *rsize,
1455 const char **rdata,
1456 int quiet
1457 )
1458 {
1459 int res;
1460 int done;
1461
1462 /*
1463 * Check to make sure host is open
1464 */
1465 if (!havehost) {
1466 fprintf(stderr, "***No host open, use `host' command\n");
1467 return -1;
1468 }
1469
1470 done = 0;
1471 sequence++;
1472
1473 again:
1474 /*
1475 * send a request
1476 */
1477 res = sendrequest(opcode, associd, auth, qsize, qdata);
1478 if (res != 0)
1479 return res;
1480
1481 /*
1482 * Get the response. If we got a standard error, print a message
1483 */
1484 res = getresponse(opcode, associd, rstatus, rsize, rdata, done);
1485
1486 if (res > 0) {
1487 if (!done && (res == ERR_TIMEOUT || res == ERR_INCOMPLETE)) {
1488 if (res == ERR_INCOMPLETE) {
1489 /*
1490 * better bump the sequence so we don't
1491 * get confused about differing fragments.
1492 */
1493 sequence++;
1494 }
1495 done = 1;
1496 goto again;
1497 }
1498 if (!quiet)
1499 show_error_msg(res, associd);
1500
1501 }
1502 return res;
1503 }
1504
1505
1506 #ifndef BUILD_AS_LIB
1507 /*
1508 * getcmds - read commands from the standard input and execute them
1509 */
1510 static void
1511 getcmds(void)
1512 {
1513 char * line;
1514 int count;
1515
1516 ntp_readline_init(interactive ? prompt : NULL);
1517
1518 for (;;) {
1519 line = ntp_readline(&count);
1520 if (NULL == line)
1521 break;
1522 docmd(line);
1523 free(line);
1524 }
1525
1526 ntp_readline_uninit();
1527 }
1528 #endif /* !BUILD_AS_LIB */
1529
1530
1531 #if !defined(SYS_WINNT) && !defined(BUILD_AS_LIB)
1532 /*
1533 * abortcmd - catch interrupts and abort the current command
1534 */
1535 static int
1536 abortcmd(void)
1537 {
1538 if (current_output == stdout)
1539 (void) fflush(stdout);
1540 putc('\n', stderr);
1541 (void) fflush(stderr);
1542 if (jump) {
1543 jump = 0;
1544 longjmp(interrupt_buf, 1);
1545 }
1546 return TRUE;
1547 }
1548 #endif /* !SYS_WINNT && !BUILD_AS_LIB */
1549
1550
1551 #ifndef BUILD_AS_LIB
1552 /*
1553 * docmd - decode the command line and execute a command
1554 */
1555 static void
1556 docmd(
1557 const char *cmdline
1558 )
1559 {
1560 char *tokens[1+MAXARGS+2];
1561 struct parse pcmd;
1562 int ntok;
1563 static int i;
1564 struct xcmd *xcmd;
1565
1566 /*
1567 * Tokenize the command line. If nothing on it, return.
1568 */
1569 tokenize(cmdline, tokens, &ntok);
1570 if (ntok == 0)
1571 return;
1572
1573 /*
1574 * Find the appropriate command description.
1575 */
1576 i = findcmd(tokens[0], builtins, opcmds, &xcmd);
1577 if (i == 0) {
1578 (void) fprintf(stderr, "***Command `%s' unknown\n",
1579 tokens[0]);
1580 return;
1581 } else if (i >= 2) {
1582 (void) fprintf(stderr, "***Command `%s' ambiguous\n",
1583 tokens[0]);
1584 return;
1585 }
1586
1587 /* Warn about ignored extra args */
1588 for (i = MAXARGS + 1; i < ntok ; ++i) {
1589 fprintf(stderr, "***Extra arg `%s' ignored\n", tokens[i]);
1590 }
1591
1592 /*
1593 * Save the keyword, then walk through the arguments, interpreting
1594 * as we go.
1595 */
1596 pcmd.keyword = tokens[0];
1597 pcmd.nargs = 0;
1598 for (i = 0; i < MAXARGS && xcmd->arg[i] != NO; i++) {
1599 if ((i+1) >= ntok) {
1600 if (!(xcmd->arg[i] & OPT)) {
1601 printusage(xcmd, stderr);
1602 return;
1603 }
1604 break;
1605 }
1606 if ((xcmd->arg[i] & OPT) && (*tokens[i+1] == '>'))
1607 break;
1608 if (!getarg(tokens[i+1], (int)xcmd->arg[i], &pcmd.argval[i]))
1609 return;
1610 pcmd.nargs++;
1611 }
1612
1613 i++;
1614 if (i < ntok && *tokens[i] == '>') {
1615 char *fname;
1616
1617 if (*(tokens[i]+1) != '\0')
1618 fname = tokens[i]+1;
1619 else if ((i+1) < ntok)
1620 fname = tokens[i+1];
1621 else {
1622 (void) fprintf(stderr, "***No file for redirect\n");
1623 return;
1624 }
1625
1626 current_output = fopen(fname, "w");
1627 if (current_output == NULL) {
1628 (void) fprintf(stderr, "***Error opening %s: ", fname);
1629 perror("");
1630 return;
1631 }
1632 i = 1; /* flag we need a close */
1633 } else {
1634 current_output = stdout;
1635 i = 0; /* flag no close */
1636 }
1637
1638 if (interactive && setjmp(interrupt_buf)) {
1639 jump = 0;
1640 return;
1641 } else {
1642 jump++;
1643 (xcmd->handler)(&pcmd, current_output);
1644 jump = 0; /* HMS: 961106: was after fclose() */
1645 if (i) (void) fclose(current_output);
1646 }
1647
1648 return;
1649 }
1650
1651
1652 /*
1653 * tokenize - turn a command line into tokens
1654 *
1655 * SK: Modified to allow a quoted string
1656 *
1657 * HMS: If the first character of the first token is a ':' then (after
1658 * eating inter-token whitespace) the 2nd token is the rest of the line.
1659 */
1660
1661 static void
1662 tokenize(
1663 const char *line,
1664 char **tokens,
1665 int *ntok
1666 )
1667 {
1668 register const char *cp;
1669 register char *sp;
1670 static char tspace[MAXLINE];
1671
1672 sp = tspace;
1673 cp = line;
1674 for (*ntok = 0; *ntok < MAXTOKENS; (*ntok)++) {
1675 tokens[*ntok] = sp;
1676
1677 /* Skip inter-token whitespace */
1678 while (ISSPACE(*cp))
1679 cp++;
1680
1681 /* If we're at EOL we're done */
1682 if (ISEOL(*cp))
1683 break;
1684
1685 /* If this is the 2nd token and the first token begins
1686 * with a ':', then just grab to EOL.
1687 */
1688
1689 if (*ntok == 1 && tokens[0][0] == ':') {
1690 do {
1691 if (sp - tspace >= MAXLINE)
1692 goto toobig;
1693 *sp++ = *cp++;
1694 } while (!ISEOL(*cp));
1695 }
1696
1697 /* Check if this token begins with a double quote.
1698 * If yes, continue reading till the next double quote
1699 */
1700 else if (*cp == '\"') {
1701 ++cp;
1702 do {
1703 if (sp - tspace >= MAXLINE)
1704 goto toobig;
1705 *sp++ = *cp++;
1706 } while ((*cp != '\"') && !ISEOL(*cp));
1707 /* HMS: a missing closing " should be an error */
1708 }
1709 else {
1710 do {
1711 if (sp - tspace >= MAXLINE)
1712 goto toobig;
1713 *sp++ = *cp++;
1714 } while ((*cp != '\"') && !ISSPACE(*cp) && !ISEOL(*cp));
1715 /* HMS: Why check for a " in the previous line? */
1716 }
1717
1718 if (sp - tspace >= MAXLINE)
1719 goto toobig;
1720 *sp++ = '\0';
1721 }
1722 return;
1723
1724 toobig:
1725 *ntok = 0;
1726 fprintf(stderr,
1727 "***Line `%s' is too big\n",
1728 line);
1729 return;
1730 }
1731
1732
1733 /*
1734 * getarg - interpret an argument token
1735 */
1736 static int
1737 getarg(
1738 const char *str,
1739 int code,
1740 arg_v *argp
1741 )
1742 {
1743 u_long ul;
1744
1745 switch (code & ~OPT) {
1746 case NTP_STR:
1747 argp->string = str;
1748 break;
1749
1750 case NTP_ADD:
1751 if (!getnetnum(str, &argp->netnum, NULL, 0))
1752 return 0;
1753 break;
1754
1755 case NTP_UINT:
1756 if ('&' == str[0]) {
1757 if (!atouint(&str[1], &ul)) {
1758 fprintf(stderr,
1759 "***Association index `%s' invalid/undecodable\n",
1760 str);
1761 return 0;
1762 }
1763 if (0 == numassoc) {
1764 dogetassoc(stdout);
1765 if (0 == numassoc) {
1766 fprintf(stderr,
1767 "***No associations found, `%s' unknown\n",
1768 str);
1769 return 0;
1770 }
1771 }
1772 ul = min(ul, numassoc);
1773 argp->uval = assoc_cache[ul - 1].assid;
1774 break;
1775 }
1776 if (!atouint(str, &argp->uval)) {
1777 fprintf(stderr, "***Illegal unsigned value %s\n",
1778 str);
1779 return 0;
1780 }
1781 break;
1782
1783 case NTP_INT:
1784 if (!atoint(str, &argp->ival)) {
1785 fprintf(stderr, "***Illegal integer value %s\n",
1786 str);
1787 return 0;
1788 }
1789 break;
1790
1791 case IP_VERSION:
1792 if (!strcmp("-6", str)) {
1793 argp->ival = 6;
1794 } else if (!strcmp("-4", str)) {
1795 argp->ival = 4;
1796 } else {
1797 fprintf(stderr, "***Version must be either 4 or 6\n");
1798 return 0;
1799 }
1800 break;
1801 }
1802
1803 return 1;
1804 }
1805 #endif /* !BUILD_AS_LIB */
1806
1807
1808 /*
1809 * findcmd - find a command in a command description table
1810 */
1811 static int
1812 findcmd(
1813 const char * str,
1814 struct xcmd * clist1,
1815 struct xcmd * clist2,
1816 struct xcmd ** cmd
1817 )
1818 {
1819 struct xcmd *cl;
1820 size_t clen;
1821 int nmatch;
1822 struct xcmd *nearmatch = NULL;
1823 struct xcmd *clist;
1824
1825 clen = strlen(str);
1826 nmatch = 0;
1827 if (clist1 != 0)
1828 clist = clist1;
1829 else if (clist2 != 0)
1830 clist = clist2;
1831 else
1832 return 0;
1833
1834 again:
1835 for (cl = clist; cl->keyword != 0; cl++) {
1836 /* do a first character check, for efficiency */
1837 if (*str != *(cl->keyword))
1838 continue;
1839 if (strncmp(str, cl->keyword, (unsigned)clen) == 0) {
1840 /*
1841 * Could be extact match, could be approximate.
1842 * Is exact if the length of the keyword is the
1843 * same as the str.
1844 */
1845 if (*((cl->keyword) + clen) == '\0') {
1846 *cmd = cl;
1847 return 1;
1848 }
1849 nmatch++;
1850 nearmatch = cl;
1851 }
1852 }
1853
1854 /*
1855 * See if there is more to do. If so, go again. Sorry about the
1856 * goto, too much looking at BSD sources...
1857 */
1858 if (clist == clist1 && clist2 != 0) {
1859 clist = clist2;
1860 goto again;
1861 }
1862
1863 /*
1864 * If we got extactly 1 near match, use it, else return number
1865 * of matches.
1866 */
1867 if (nmatch == 1) {
1868 *cmd = nearmatch;
1869 return 1;
1870 }
1871 return nmatch;
1872 }
1873
1874
1875 /*
1876 * getnetnum - given a host name, return its net number
1877 * and (optional) full name
1878 */
1879 int
1880 getnetnum(
1881 const char *hname,
1882 sockaddr_u *num,
1883 char *fullhost,
1884 int af
1885 )
1886 {
1887 struct addrinfo hints, *ai = NULL;
1888
1889 ZERO(hints);
1890 hints.ai_flags = AI_CANONNAME;
1891 #ifdef AI_ADDRCONFIG
1892 hints.ai_flags |= AI_ADDRCONFIG;
1893 #endif
1894
1895 /*
1896 * decodenetnum only works with addresses, but handles syntax
1897 * that getaddrinfo doesn't: [2001::1]:1234
1898 */
1899 if (decodenetnum(hname, num)) {
1900 if (fullhost != NULL)
1901 getnameinfo(&num->sa, SOCKLEN(num), fullhost,
1902 LENHOSTNAME, NULL, 0, 0);
1903 return 1;
1904 } else if (getaddrinfo(hname, "ntp", &hints, &ai) == 0) {
1905 INSIST(sizeof(*num) >= ai->ai_addrlen);
1906 memcpy(num, ai->ai_addr, ai->ai_addrlen);
1907 if (fullhost != NULL) {
1908 if (ai->ai_canonname != NULL)
1909 strlcpy(fullhost, ai->ai_canonname,
1910 LENHOSTNAME);
1911 else
1912 getnameinfo(&num->sa, SOCKLEN(num),
1913 fullhost, LENHOSTNAME, NULL,
1914 0, 0);
1915 }
1916 freeaddrinfo(ai);
1917 return 1;
1918 }
1919 fprintf(stderr, "***Can't find host %s\n", hname);
1920
1921 return 0;
1922 }
1923
1924
1925 /*
1926 * nntohost - convert network number to host name. This routine enforces
1927 * the showhostnames setting.
1928 */
1929 const char *
1930 nntohost(
1931 sockaddr_u *netnum
1932 )
1933 {
1934 return nntohost_col(netnum, LIB_BUFLENGTH - 1, FALSE);
1935 }
1936
1937
1938 /*
1939 * nntohost_col - convert network number to host name in fixed width.
1940 * This routine enforces the showhostnames setting.
1941 * When displaying hostnames longer than the width,
1942 * the first part of the hostname is displayed. When
1943 * displaying numeric addresses longer than the width,
1944 * Such as IPv6 addresses, the caller decides whether
1945 * the first or last of the numeric address is used.
1946 */
1947 const char *
1948 nntohost_col(
1949 sockaddr_u * addr,
1950 size_t width,
1951 int preserve_lowaddrbits
1952 )
1953 {
1954 const char * out;
1955
1956 if (!showhostnames || SOCK_UNSPEC(addr)) {
1957 if (preserve_lowaddrbits)
1958 out = trunc_left(stoa(addr), width);
1959 else
1960 out = trunc_right(stoa(addr), width);
1961 } else if (ISREFCLOCKADR(addr)) {
1962 out = refnumtoa(addr);
1963 } else {
1964 out = trunc_right(socktohost(addr), width);
1965 }
1966 return out;
1967 }
1968
1969
1970 /*
1971 * nntohostp() is the same as nntohost() plus a :port suffix
1972 */
1973 const char *
1974 nntohostp(
1975 sockaddr_u *netnum
1976 )
1977 {
1978 const char * hostn;
1979 char * buf;
1980
1981 if (!showhostnames || SOCK_UNSPEC(netnum))
1982 return sptoa(netnum);
1983 else if (ISREFCLOCKADR(netnum))
1984 return refnumtoa(netnum);
1985
1986 hostn = socktohost(netnum);
1987 LIB_GETBUF(buf);
1988 snprintf(buf, LIB_BUFLENGTH, "%s:%u", hostn, SRCPORT(netnum));
1989
1990 return buf;
1991 }
1992
1993 /*
1994 * rtdatetolfp - decode an RT-11 date into an l_fp
1995 */
1996 static int
1997 rtdatetolfp(
1998 char *str,
1999 l_fp *lfp
2000 )
2001 {
2002 register char *cp;
2003 register int i;
2004 struct calendar cal;
2005 char buf[4];
2006
2007 cal.yearday = 0;
2008
2009 /*
2010 * An RT-11 date looks like:
2011 *
2012 * d[d]-Mth-y[y] hh:mm:ss
2013 *
2014 * (No docs, but assume 4-digit years are also legal...)
2015 *
2016 * d[d]-Mth-y[y[y[y]]] hh:mm:ss
2017 */
2018 cp = str;
2019 if (!isdigit((int)*cp)) {
2020 if (*cp == '-') {
2021 /*
2022 * Catch special case
2023 */
2024 L_CLR(lfp);
2025 return 1;
2026 }
2027 return 0;
2028 }
2029
2030 cal.monthday = (u_char) (*cp++ - '0'); /* ascii dependent */
2031 if (isdigit((int)*cp)) {
2032 cal.monthday = (u_char)((cal.monthday << 3) + (cal.monthday << 1));
2033 cal.monthday = (u_char)(cal.monthday + *cp++ - '0');
2034 }
2035
2036 if (*cp++ != '-')
2037 return 0;
2038
2039 for (i = 0; i < 3; i++)
2040 buf[i] = *cp++;
2041 buf[3] = '\0';
2042
2043 for (i = 0; i < 12; i++)
2044 if (STREQ(buf, months[i]))
2045 break;
2046 if (i == 12)
2047 return 0;
2048 cal.month = (u_char)(i + 1);
2049
2050 if (*cp++ != '-')
2051 return 0;
2052
2053 if (!isdigit((int)*cp))
2054 return 0;
2055 cal.year = (u_short)(*cp++ - '0');
2056 if (isdigit((int)*cp)) {
2057 cal.year = (u_short)((cal.year << 3) + (cal.year << 1));
2058 cal.year = (u_short)(*cp++ - '0');
2059 }
2060 if (isdigit((int)*cp)) {
2061 cal.year = (u_short)((cal.year << 3) + (cal.year << 1));
2062 cal.year = (u_short)(cal.year + *cp++ - '0');
2063 }
2064 if (isdigit((int)*cp)) {
2065 cal.year = (u_short)((cal.year << 3) + (cal.year << 1));
2066 cal.year = (u_short)(cal.year + *cp++ - '0');
2067 }
2068
2069 /*
2070 * Catch special case. If cal.year == 0 this is a zero timestamp.
2071 */
2072 if (cal.year == 0) {
2073 L_CLR(lfp);
2074 return 1;
2075 }
2076
2077 if (*cp++ != ' ' || !isdigit((int)*cp))
2078 return 0;
2079 cal.hour = (u_char)(*cp++ - '0');
2080 if (isdigit((int)*cp)) {
2081 cal.hour = (u_char)((cal.hour << 3) + (cal.hour << 1));
2082 cal.hour = (u_char)(cal.hour + *cp++ - '0');
2083 }
2084
2085 if (*cp++ != ':' || !isdigit((int)*cp))
2086 return 0;
2087 cal.minute = (u_char)(*cp++ - '0');
2088 if (isdigit((int)*cp)) {
2089 cal.minute = (u_char)((cal.minute << 3) + (cal.minute << 1));
2090 cal.minute = (u_char)(cal.minute + *cp++ - '0');
2091 }
2092
2093 if (*cp++ != ':' || !isdigit((int)*cp))
2094 return 0;
2095 cal.second = (u_char)(*cp++ - '0');
2096 if (isdigit((int)*cp)) {
2097 cal.second = (u_char)((cal.second << 3) + (cal.second << 1));
2098 cal.second = (u_char)(cal.second + *cp++ - '0');
2099 }
2100
2101 /*
2102 * For RT-11, 1972 seems to be the pivot year
2103 */
2104 if (cal.year < 72)
2105 cal.year += 2000;
2106 if (cal.year < 100)
2107 cal.year += 1900;
2108
2109 lfp->l_ui = caltontp(&cal);
2110 lfp->l_uf = 0;
2111 return 1;
2112 }
2113
2114
2115 /*
2116 * decodets - decode a timestamp into an l_fp format number, with
2117 * consideration of fuzzball formats.
2118 */
2119 int
2120 decodets(
2121 char *str,
2122 l_fp *lfp
2123 )
2124 {
2125 char *cp;
2126 char buf[30];
2127 size_t b;
2128
2129 /*
2130 * If it starts with a 0x, decode as hex.
2131 */
2132 if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
2133 return hextolfp(str+2, lfp);
2134
2135 /*
2136 * If it starts with a '"', try it as an RT-11 date.
2137 */
2138 if (*str == '"') {
2139 cp = str + 1;
2140 b = 0;
2141 while ('"' != *cp && '\0' != *cp &&
2142 b < COUNTOF(buf) - 1)
2143 buf[b++] = *cp++;
2144 buf[b] = '\0';
2145 return rtdatetolfp(buf, lfp);
2146 }
2147
2148 /*
2149 * Might still be hex. Check out the first character. Talk
2150 * about heuristics!
2151 */
2152 if ((*str >= 'A' && *str <= 'F') || (*str >= 'a' && *str <= 'f'))
2153 return hextolfp(str, lfp);
2154
2155 /*
2156 * Try it as a decimal. If this fails, try as an unquoted
2157 * RT-11 date. This code should go away eventually.
2158 */
2159 if (atolfp(str, lfp))
2160 return 1;
2161
2162 return rtdatetolfp(str, lfp);
2163 }
2164
2165
2166 /*
2167 * decodetime - decode a time value. It should be in milliseconds
2168 */
2169 int
2170 decodetime(
2171 char *str,
2172 l_fp *lfp
2173 )
2174 {
2175 return mstolfp(str, lfp);
2176 }
2177
2178
2179 /*
2180 * decodeint - decode an integer
2181 */
2182 int
2183 decodeint(
2184 char *str,
2185 long *val
2186 )
2187 {
2188 if (*str == '0') {
2189 if (*(str+1) == 'x' || *(str+1) == 'X')
2190 return hextoint(str+2, (u_long *)val);
2191 return octtoint(str, (u_long *)val);
2192 }
2193 return atoint(str, val);
2194 }
2195
2196
2197 /*
2198 * decodeuint - decode an unsigned integer
2199 */
2200 int
2201 decodeuint(
2202 char *str,
2203 u_long *val
2204 )
2205 {
2206 if (*str == '0') {
2207 if (*(str + 1) == 'x' || *(str + 1) == 'X')
2208 return (hextoint(str + 2, val));
2209 return (octtoint(str, val));
2210 }
2211 return (atouint(str, val));
2212 }
2213
2214
2215 /*
2216 * decodearr - decode an array of time values
2217 */
2218 static int
2219 decodearr(
2220 char *str,
2221 int *narr,
2222 l_fp *lfparr
2223 )
2224 {
2225 register char *cp, *bp;
2226 register l_fp *lfp;
2227 char buf[60];
2228
2229 lfp = lfparr;
2230 cp = str;
2231 *narr = 0;
2232
2233 while (*narr < 8) {
2234 while (isspace((int)*cp))
2235 cp++;
2236 if (*cp == '\0')
2237 break;
2238
2239 bp = buf;
2240 while (!isspace((int)*cp) && *cp != '\0')
2241 *bp++ = *cp++;
2242 *bp++ = '\0';
2243
2244 if (!decodetime(buf, lfp))
2245 return 0;
2246 (*narr)++;
2247 lfp++;
2248 }
2249 return 1;
2250 }
2251
2252
2253 /*
2254 * Finally, the built in command handlers
2255 */
2256
2257 /*
2258 * help - tell about commands, or details of a particular command
2259 */
2260 static void
2261 help(
2262 struct parse *pcmd,
2263 FILE *fp
2264 )
2265 {
2266 struct xcmd *xcp = NULL; /* quiet warning */
2267 const char *cmd;
2268 const char *list[100];
2269 size_t word, words;
2270 size_t row, rows;
2271 size_t col, cols;
2272 size_t length;
2273
2274 if (pcmd->nargs == 0) {
2275 words = 0;
2276 for (xcp = builtins; xcp->keyword != NULL; xcp++) {
2277 if (*(xcp->keyword) != '?' &&
2278 words < COUNTOF(list))
2279 list[words++] = xcp->keyword;
2280 }
2281 for (xcp = opcmds; xcp->keyword != NULL; xcp++)
2282 if (words < COUNTOF(list))
2283 list[words++] = xcp->keyword;
2284
2285 qsort((void *)list, words, sizeof(list[0]), helpsort);
2286 col = 0;
2287 for (word = 0; word < words; word++) {
2288 length = strlen(list[word]);
2289 col = max(col, length);
2290 }
2291
2292 cols = SCREENWIDTH / ++col;
2293 rows = (words + cols - 1) / cols;
2294
2295 fprintf(fp, "ntpq commands:\n");
2296
2297 for (row = 0; row < rows; row++) {
2298 for (word = row; word < words; word += rows)
2299 fprintf(fp, "%-*.*s", (int)col,
2300 (int)col - 1, list[word]);
2301 fprintf(fp, "\n");
2302 }
2303 } else {
2304 cmd = pcmd->argval[0].string;
2305 words = findcmd(cmd, builtins, opcmds, &xcp);
2306 if (words == 0) {
2307 fprintf(stderr,
2308 "Command `%s' is unknown\n", cmd);
2309 return;
2310 } else if (words >= 2) {
2311 fprintf(stderr,
2312 "Command `%s' is ambiguous\n", cmd);
2313 return;
2314 }
2315 fprintf(fp, "function: %s\n", xcp->comment);
2316 printusage(xcp, fp);
2317 }
2318 }
2319
2320
2321 /*
2322 * helpsort - do hostname qsort comparisons
2323 */
2324 static int
2325 helpsort(
2326 const void *t1,
2327 const void *t2
2328 )
2329 {
2330 const char * const * name1 = t1;
2331 const char * const * name2 = t2;
2332
2333 return strcmp(*name1, *name2);
2334 }
2335
2336
2337 /*
2338 * printusage - print usage information for a command
2339 */
2340 static void
2341 printusage(
2342 struct xcmd *xcp,
2343 FILE *fp
2344 )
2345 {
2346 register int i;
2347
2348 /* XXX: Do we need to warn about extra args here too? */
2349
2350 (void) fprintf(fp, "usage: %s", xcp->keyword);
2351 for (i = 0; i < MAXARGS && xcp->arg[i] != NO; i++) {
2352 if (xcp->arg[i] & OPT)
2353 (void) fprintf(fp, " [ %s ]", xcp->desc[i]);
2354 else
2355 (void) fprintf(fp, " %s", xcp->desc[i]);
2356 }
2357 (void) fprintf(fp, "\n");
2358 }
2359
2360
2361 /*
2362 * timeout - set time out time
2363 */
2364 static void
2365 timeout(
2366 struct parse *pcmd,
2367 FILE *fp
2368 )
2369 {
2370 int val;
2371
2372 if (pcmd->nargs == 0) {
2373 val = (int)tvout.tv_sec * 1000 + tvout.tv_usec / 1000;
2374 (void) fprintf(fp, "primary timeout %d ms\n", val);
2375 } else {
2376 tvout.tv_sec = pcmd->argval[0].uval / 1000;
2377 tvout.tv_usec = (pcmd->argval[0].uval - ((long)tvout.tv_sec * 1000))
2378 * 1000;
2379 }
2380 }
2381
2382
2383 /*
2384 * auth_delay - set delay for auth requests
2385 */
2386 static void
2387 auth_delay(
2388 struct parse *pcmd,
2389 FILE *fp
2390 )
2391 {
2392 int isneg;
2393 u_long val;
2394
2395 if (pcmd->nargs == 0) {
2396 val = delay_time.l_ui * 1000 + delay_time.l_uf / 4294967;
2397 (void) fprintf(fp, "delay %lu ms\n", val);
2398 } else {
2399 if (pcmd->argval[0].ival < 0) {
2400 isneg = 1;
2401 val = (u_long)(-pcmd->argval[0].ival);
2402 } else {
2403 isneg = 0;
2404 val = (u_long)pcmd->argval[0].ival;
2405 }
2406
2407 delay_time.l_ui = val / 1000;
2408 val %= 1000;
2409 delay_time.l_uf = val * 4294967; /* 2**32/1000 */
2410
2411 if (isneg)
2412 L_NEG(&delay_time);
2413 }
2414 }
2415
2416
2417 /*
2418 * host - set the host we are dealing with.
2419 */
2420 static void
2421 host(
2422 struct parse *pcmd,
2423 FILE *fp
2424 )
2425 {
2426 int i;
2427
2428 if (pcmd->nargs == 0) {
2429 if (havehost)
2430 (void) fprintf(fp, "current host is %s\n",
2431 currenthost);
2432 else
2433 (void) fprintf(fp, "no current host\n");
2434 return;
2435 }
2436
2437 i = 0;
2438 ai_fam_templ = ai_fam_default;
2439 if (pcmd->nargs == 2) {
2440 if (!strcmp("-4", pcmd->argval[i].string))
2441 ai_fam_templ = AF_INET;
2442 else if (!strcmp("-6", pcmd->argval[i].string))
2443 ai_fam_templ = AF_INET6;
2444 else
2445 goto no_change;
2446 i = 1;
2447 }
2448 if (openhost(pcmd->argval[i].string, ai_fam_templ)) {
2449 fprintf(fp, "current host set to %s\n", currenthost);
2450 } else {
2451 no_change:
2452 if (havehost)
2453 fprintf(fp, "current host remains %s\n",
2454 currenthost);
2455 else
2456 fprintf(fp, "still no current host\n");
2457 }
2458 }
2459
2460
2461 /*
2462 * poll - do one (or more) polls of the host via NTP
2463 */
2464 /*ARGSUSED*/
2465 static void
2466 ntp_poll(
2467 struct parse *pcmd,
2468 FILE *fp
2469 )
2470 {
2471 (void) fprintf(fp, "poll not implemented yet\n");
2472 }
2473
2474
2475 /*
2476 * showdrefid2str - return a string explanation of the value of drefid
2477 */
2478 static const char *
2479 showdrefid2str(void)
2480 {
2481 switch (drefid) {
2482 case REFID_HASH:
2483 return "hash";
2484 case REFID_IPV4:
2485 return "ipv4";
2486 default:
2487 return "Unknown";
2488 }
2489 }
2490
2491
2492 /*
2493 * drefid - display/change "display hash"
2494 */
2495 static void
2496 showdrefid(
2497 struct parse *pcmd,
2498 FILE *fp
2499 )
2500 {
2501 if (pcmd->nargs == 0) {
2502 (void) fprintf(fp, "drefid value is %s\n", showdrefid2str());
2503 return;
2504 } else if (STREQ(pcmd->argval[0].string, "hash")) {
2505 drefid = REFID_HASH;
2506 } else if (STREQ(pcmd->argval[0].string, "ipv4")) {
2507 drefid = REFID_IPV4;
2508 } else {
2509 (void) fprintf(fp, "What?\n");
2510 return;
2511 }
2512 (void) fprintf(fp, "drefid value set to %s\n", showdrefid2str());
2513 }
2514
2515
2516 /*
2517 * keyid - get a keyid to use for authenticating requests
2518 */
2519 static void
2520 keyid(
2521 struct parse *pcmd,
2522 FILE *fp
2523 )
2524 {
2525 if (pcmd->nargs == 0) {
2526 if (info_auth_keyid == 0)
2527 (void) fprintf(fp, "no keyid defined\n");
2528 else
2529 (void) fprintf(fp, "keyid is %lu\n", (u_long)info_auth_keyid);
2530 } else {
2531 /* allow zero so that keyid can be cleared. */
2532 if(pcmd->argval[0].uval > NTP_MAXKEY)
2533 (void) fprintf(fp, "Invalid key identifier\n");
2534 info_auth_keyid = pcmd->argval[0].uval;
2535 }
2536 }
2537
2538 /*
2539 * keytype - get type of key to use for authenticating requests
2540 */
2541 static void
2542 keytype(
2543 struct parse *pcmd,
2544 FILE *fp
2545 )
2546 {
2547 const char * digest_name;
2548 size_t digest_len;
2549 int key_type;
2550
2551 if (!pcmd->nargs) {
2552 fprintf(fp, "keytype is %s with %lu octet digests\n",
2553 keytype_name(info_auth_keytype),
2554 (u_long)info_auth_hashlen);
2555 return;
2556 }
2557
2558 digest_name = pcmd->argval[0].string;
2559 digest_len = 0;
2560 key_type = keytype_from_text(digest_name, &digest_len);
2561
2562 if (!key_type) {
2563 fprintf(fp, "keytype is not valid. "
2564 #ifdef OPENSSL
2565 "Type \"help keytype\" for the available digest types.\n");
2566 #else
2567 "Only \"md5\" is available.\n");
2568 #endif
2569 return;
2570 }
2571
2572 info_auth_keytype = key_type;
2573 info_auth_hashlen = digest_len;
2574 }
2575
2576
2577 /*
2578 * passwd - get an authentication key
2579 */
2580 /*ARGSUSED*/
2581 static void
2582 passwd(
2583 struct parse *pcmd,
2584 FILE *fp
2585 )
2586 {
2587 const char *pass;
2588
2589 if (info_auth_keyid == 0) {
2590 info_auth_keyid = getkeyid("Keyid: ");
2591 if (info_auth_keyid == 0) {
2592 (void)fprintf(fp, "Keyid must be defined\n");
2593 return;
2594 }
2595 }
2596 if (pcmd->nargs >= 1)
2597 pass = pcmd->argval[0].string;
2598 else {
2599 pass = getpass_keytype(info_auth_keytype);
2600 if ('\0' == pass[0]) {
2601 fprintf(fp, "Password unchanged\n");
2602 return;
2603 }
2604 }
2605 authusekey(info_auth_keyid, info_auth_keytype,
2606 (const u_char *)pass);
2607 authtrust(info_auth_keyid, 1);
2608 }
2609
2610
2611 /*
2612 * hostnames - set the showhostnames flag
2613 */
2614 static void
2615 hostnames(
2616 struct parse *pcmd,
2617 FILE *fp
2618 )
2619 {
2620 if (pcmd->nargs == 0) {
2621 if (showhostnames)
2622 (void) fprintf(fp, "hostnames being shown\n");
2623 else
2624 (void) fprintf(fp, "hostnames not being shown\n");
2625 } else {
2626 if (STREQ(pcmd->argval[0].string, "yes"))
2627 showhostnames = 1;
2628 else if (STREQ(pcmd->argval[0].string, "no"))
2629 showhostnames = 0;
2630 else
2631 (void)fprintf(stderr, "What?\n");
2632 }
2633 }
2634
2635
2636
2637 /*
2638 * setdebug - set/change debugging level
2639 */
2640 static void
2641 setdebug(
2642 struct parse *pcmd,
2643 FILE *fp
2644 )
2645 {
2646 if (pcmd->nargs == 0) {
2647 (void) fprintf(fp, "debug level is %d\n", debug);
2648 return;
2649 } else if (STREQ(pcmd->argval[0].string, "no")) {
2650 debug = 0;
2651 } else if (STREQ(pcmd->argval[0].string, "more")) {
2652 debug++;
2653 } else if (STREQ(pcmd->argval[0].string, "less")) {
2654 debug--;
2655 } else {
2656 (void) fprintf(fp, "What?\n");
2657 return;
2658 }
2659 (void) fprintf(fp, "debug level set to %d\n", debug);
2660 }
2661
2662
2663 /*
2664 * quit - stop this nonsense
2665 */
2666 /*ARGSUSED*/
2667 static void
2668 quit(
2669 struct parse *pcmd,
2670 FILE *fp
2671 )
2672 {
2673 if (havehost)
2674 closesocket(sockfd); /* cleanliness next to godliness */
2675 exit(0);
2676 }
2677
2678
2679 /*
2680 * version - print the current version number
2681 */
2682 /*ARGSUSED*/
2683 static void
2684 version(
2685 struct parse *pcmd,
2686 FILE *fp
2687 )
2688 {
2689
2690 (void) fprintf(fp, "%s\n", Version);
2691 return;
2692 }
2693
2694
2695 /*
2696 * raw - set raw mode output
2697 */
2698 /*ARGSUSED*/
2699 static void
2700 raw(
2701 struct parse *pcmd,
2702 FILE *fp
2703 )
2704 {
2705 rawmode = 1;
2706 (void) fprintf(fp, "Output set to raw\n");
2707 }
2708
2709
2710 /*
2711 * cooked - set cooked mode output
2712 */
2713 /*ARGSUSED*/
2714 static void
2715 cooked(
2716 struct parse *pcmd,
2717 FILE *fp
2718 )
2719 {
2720 rawmode = 0;
2721 (void) fprintf(fp, "Output set to cooked\n");
2722 return;
2723 }
2724
2725
2726 /*
2727 * authenticate - always authenticate requests to this host
2728 */
2729 static void
2730 authenticate(
2731 struct parse *pcmd,
2732 FILE *fp
2733 )
2734 {
2735 if (pcmd->nargs == 0) {
2736 if (always_auth) {
2737 (void) fprintf(fp,
2738 "authenticated requests being sent\n");
2739 } else
2740 (void) fprintf(fp,
2741 "unauthenticated requests being sent\n");
2742 } else {
2743 if (STREQ(pcmd->argval[0].string, "yes")) {
2744 always_auth = 1;
2745 } else if (STREQ(pcmd->argval[0].string, "no")) {
2746 always_auth = 0;
2747 } else
2748 (void)fprintf(stderr, "What?\n");
2749 }
2750 }
2751
2752
2753 /*
2754 * ntpversion - choose the NTP version to use
2755 */
2756 static void
2757 ntpversion(
2758 struct parse *pcmd,
2759 FILE *fp
2760 )
2761 {
2762 if (pcmd->nargs == 0) {
2763 (void) fprintf(fp,
2764 "NTP version being claimed is %d\n", pktversion);
2765 } else {
2766 if (pcmd->argval[0].uval < NTP_OLDVERSION
2767 || pcmd->argval[0].uval > NTP_VERSION) {
2768 (void) fprintf(stderr, "versions %d to %d, please\n",
2769 NTP_OLDVERSION, NTP_VERSION);
2770 } else {
2771 pktversion = (u_char) pcmd->argval[0].uval;
2772 }
2773 }
2774 }
2775
2776
2777 static void __attribute__((__format__(__printf__, 1, 0)))
2778 vwarning(const char *fmt, va_list ap)
2779 {
2780 int serrno = errno;
2781 (void) fprintf(stderr, "%s: ", progname);
2782 vfprintf(stderr, fmt, ap);
2783 (void) fprintf(stderr, ": %s\n", strerror(serrno));
2784 }
2785
2786 /*
2787 * warning - print a warning message
2788 */
2789 static void __attribute__((__format__(__printf__, 1, 2)))
2790 warning(
2791 const char *fmt,
2792 ...
2793 )
2794 {
2795 va_list ap;
2796 va_start(ap, fmt);
2797 vwarning(fmt, ap);
2798 va_end(ap);
2799 }
2800
2801
2802 /*
2803 * error - print a message and exit
2804 */
2805 static void __attribute__((__format__(__printf__, 1, 2)))
2806 error(
2807 const char *fmt,
2808 ...
2809 )
2810 {
2811 va_list ap;
2812 va_start(ap, fmt);
2813 vwarning(fmt, ap);
2814 va_end(ap);
2815 exit(1);
2816 }
2817 /*
2818 * getkeyid - prompt the user for a keyid to use
2819 */
2820 static u_long
2821 getkeyid(
2822 const char *keyprompt
2823 )
2824 {
2825 int c;
2826 FILE *fi;
2827 char pbuf[20];
2828 size_t i;
2829 size_t ilim;
2830
2831 #ifndef SYS_WINNT
2832 if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
2833 #else
2834 if ((fi = _fdopen(open("CONIN$", _O_TEXT), "r")) == NULL)
2835 #endif /* SYS_WINNT */
2836 fi = stdin;
2837 else
2838 setbuf(fi, (char *)NULL);
2839 fprintf(stderr, "%s", keyprompt); fflush(stderr);
2840 for (i = 0, ilim = COUNTOF(pbuf) - 1;
2841 i < ilim && (c = getc(fi)) != '\n' && c != EOF;
2842 )
2843 pbuf[i++] = (char)c;
2844 pbuf[i] = '\0';
2845 if (fi != stdin)
2846 fclose(fi);
2847
2848 return (u_long) atoi(pbuf);
2849 }
2850
2851
2852 /*
2853 * atoascii - printable-ize possibly ascii data using the character
2854 * transformations cat -v uses.
2855 */
2856 static void
2857 atoascii(
2858 const char *in,
2859 size_t in_octets,
2860 char *out,
2861 size_t out_octets
2862 )
2863 {
2864 const u_char * pchIn;
2865 const u_char * pchInLimit;
2866 u_char * pchOut;
2867 u_char c;
2868
2869 pchIn = (const u_char *)in;
2870 pchInLimit = pchIn + in_octets;
2871 pchOut = (u_char *)out;
2872
2873 if (NULL == pchIn) {
2874 if (0 < out_octets)
2875 *pchOut = '\0';
2876 return;
2877 }
2878
2879 #define ONEOUT(c) \
2880 do { \
2881 if (0 == --out_octets) { \
2882 *pchOut = '\0'; \
2883 return; \
2884 } \
2885 *pchOut++ = (c); \
2886 } while (0)
2887
2888 for ( ; pchIn < pchInLimit; pchIn++) {
2889 c = *pchIn;
2890 if ('\0' == c)
2891 break;
2892 if (c & 0x80) {
2893 ONEOUT('M');
2894 ONEOUT('-');
2895 c &= 0x7f;
2896 }
2897 if (c < ' ') {
2898 ONEOUT('^');
2899 ONEOUT((u_char)(c + '@'));
2900 } else if (0x7f == c) {
2901 ONEOUT('^');
2902 ONEOUT('?');
2903 } else
2904 ONEOUT(c);
2905 }
2906 ONEOUT('\0');
2907
2908 #undef ONEOUT
2909 }
2910
2911
2912 /*
2913 * makeascii - print possibly ascii data using the character
2914 * transformations that cat -v uses.
2915 */
2916 void
2917 makeascii(
2918 size_t length,
2919 const char *data,
2920 FILE *fp
2921 )
2922 {
2923 const u_char *data_u_char;
2924 const u_char *cp;
2925 int c;
2926
2927 data_u_char = (const u_char *)data;
2928
2929 for (cp = data_u_char; cp < data_u_char + length; cp++) {
2930 c = (int)*cp;
2931 if (c & 0x80) {
2932 putc('M', fp);
2933 putc('-', fp);
2934 c &= 0x7f;
2935 }
2936
2937 if (c < ' ') {
2938 putc('^', fp);
2939 putc(c + '@', fp);
2940 } else if (0x7f == c) {
2941 putc('^', fp);
2942 putc('?', fp);
2943 } else
2944 putc(c, fp);
2945 }
2946 }
2947
2948
2949 /*
2950 * asciize - same thing as makeascii except add a newline
2951 */
2952 void
2953 asciize(
2954 int length,
2955 char *data,
2956 FILE *fp
2957 )
2958 {
2959 makeascii(length, data, fp);
2960 putc('\n', fp);
2961 }
2962
2963
2964 /*
2965 * truncate string to fit clipping excess at end.
2966 * "too long" -> "too l"
2967 * Used for hostnames.
2968 */
2969 const char *
2970 trunc_right(
2971 const char * src,
2972 size_t width
2973 )
2974 {
2975 size_t sl;
2976 char * out;
2977
2978
2979 sl = strlen(src);
2980 if (sl > width && LIB_BUFLENGTH - 1 > width && width > 0) {
2981 LIB_GETBUF(out);
2982 memcpy(out, src, width);
2983 out[width] = '\0';
2984
2985 return out;
2986 }
2987
2988 return src;
2989 }
2990
2991
2992 /*
2993 * truncate string to fit by preserving right side and using '_' to hint
2994 * "too long" -> "_long"
2995 * Used for local IPv6 addresses, where low bits differentiate.
2996 */
2997 const char *
2998 trunc_left(
2999 const char * src,
3000 size_t width
3001 )
3002 {
3003 size_t sl;
3004 char * out;
3005
3006
3007 sl = strlen(src);
3008 if (sl > width && LIB_BUFLENGTH - 1 > width && width > 1) {
3009 LIB_GETBUF(out);
3010 out[0] = '_';
3011 memcpy(&out[1], &src[sl + 1 - width], width);
3012
3013 return out;
3014 }
3015
3016 return src;
3017 }
3018
3019
3020 /*
3021 * Some circular buffer space
3022 */
3023 #define CBLEN 80
3024 #define NUMCB 6
3025
3026 char circ_buf[NUMCB][CBLEN];
3027 int nextcb = 0;
3028
3029 /*
3030 * nextvar - find the next variable in the buffer
3031 */
3032 int
3033 nextvar(
3034 size_t *datalen,
3035 const char **datap,
3036 char **vname,
3037 char **vvalue
3038 )
3039 {
3040 const char *cp;
3041 const char *np;
3042 const char *cpend;
3043 size_t srclen;
3044 size_t len;
3045 static char name[MAXVARLEN];
3046 static char value[MAXVALLEN];
3047
3048 cp = *datap;
3049 cpend = cp + *datalen;
3050
3051 /*
3052 * Space past commas and white space
3053 */
3054 while (cp < cpend && (*cp == ',' || isspace((int)*cp)))
3055 cp++;
3056 if (cp >= cpend)
3057 return 0;
3058
3059 /*
3060 * Copy name until we hit a ',', an '=', a '\r' or a '\n'. Backspace
3061 * over any white space and terminate it.
3062 */
3063 srclen = strcspn(cp, ",=\r\n");
3064 srclen = min(srclen, (size_t)(cpend - cp));
3065 len = srclen;
3066 while (len > 0 && isspace((unsigned char)cp[len - 1]))
3067 len--;
3068 if (len >= sizeof(name))
3069 return 0;
3070 if (len > 0)
3071 memcpy(name, cp, len);
3072 name[len] = '\0';
3073 *vname = name;
3074 cp += srclen;
3075
3076 /*
3077 * Check if we hit the end of the buffer or a ','. If so we are done.
3078 */
3079 if (cp >= cpend || *cp == ',' || *cp == '\r' || *cp == '\n') {
3080 if (cp < cpend)
3081 cp++;
3082 *datap = cp;
3083 *datalen = size2int_sat(cpend - cp);
3084 *vvalue = NULL;
3085 return 1;
3086 }
3087
3088 /*
3089 * So far, so good. Copy out the value
3090 */
3091 cp++; /* past '=' */
3092 while (cp < cpend && (isspace((unsigned char)*cp) && *cp != '\r' && *cp != '\n'))
3093 cp++;
3094 np = cp;
3095 if ('"' == *np) {
3096 do {
3097 np++;
3098 } while (np < cpend && '"' != *np);
3099 if (np < cpend && '"' == *np)
3100 np++;
3101 } else {
3102 while (np < cpend && ',' != *np && '\r' != *np)
3103 np++;
3104 }
3105 len = np - cp;
3106 if (np > cpend || len >= sizeof(value) ||
3107 (np < cpend && ',' != *np && '\r' != *np))
3108 return 0;
3109 memcpy(value, cp, len);
3110 /*
3111 * Trim off any trailing whitespace
3112 */
3113 while (len > 0 && isspace((unsigned char)value[len - 1]))
3114 len--;
3115 value[len] = '\0';
3116
3117 /*
3118 * Return this. All done.
3119 */
3120 if (np < cpend && ',' == *np)
3121 np++;
3122 *datap = np;
3123 *datalen = size2int_sat(cpend - np);
3124 *vvalue = value;
3125 return 1;
3126 }
3127
3128
3129 u_short
3130 varfmt(const char * varname)
3131 {
3132 u_int n;
3133
3134 for (n = 0; n < COUNTOF(cookedvars); n++)
3135 if (!strcmp(varname, cookedvars[n].varname))
3136 return cookedvars[n].fmt;
3137
3138 return PADDING;
3139 }
3140
3141
3142 /*
3143 * printvars - print variables returned in response packet
3144 */
3145 void
3146 printvars(
3147 size_t length,
3148 const char *data,
3149 int status,
3150 int sttype,
3151 int quiet,
3152 FILE *fp
3153 )
3154 {
3155 if (rawmode)
3156 rawprint(sttype, length, data, status, quiet, fp);
3157 else
3158 cookedprint(sttype, length, data, status, quiet, fp);
3159 }
3160
3161
3162 /*
3163 * rawprint - do a printout of the data in raw mode
3164 */
3165 static void
3166 rawprint(
3167 int datatype,
3168 size_t length,
3169 const char *data,
3170 int status,
3171 int quiet,
3172 FILE *fp
3173 )
3174 {
3175 const char *cp;
3176 const char *cpend;
3177
3178 /*
3179 * Essentially print the data as is. We reformat unprintables, though.
3180 */
3181 cp = data;
3182 cpend = data + length;
3183
3184 if (!quiet)
3185 (void) fprintf(fp, "status=0x%04x,\n", status);
3186
3187 while (cp < cpend) {
3188 if (*cp == '\r') {
3189 /*
3190 * If this is a \r and the next character is a
3191 * \n, supress this, else pretty print it. Otherwise
3192 * just output the character.
3193 */
3194 if (cp == (cpend - 1) || *(cp + 1) != '\n')
3195 makeascii(1, cp, fp);
3196 } else if (isspace((unsigned char)*cp) || isprint((unsigned char)*cp))
3197 putc(*cp, fp);
3198 else
3199 makeascii(1, cp, fp);
3200 cp++;
3201 }
3202 }
3203
3204
3205 /*
3206 * Global data used by the cooked output routines
3207 */
3208 int out_chars; /* number of characters output */
3209 int out_linecount; /* number of characters output on this line */
3210
3211
3212 /*
3213 * startoutput - get ready to do cooked output
3214 */
3215 static void
3216 startoutput(void)
3217 {
3218 out_chars = 0;
3219 out_linecount = 0;
3220 }
3221
3222
3223 /*
3224 * output - output a variable=value combination
3225 */
3226 static void
3227 output(
3228 FILE *fp,
3229 const char *name,
3230 const char *value
3231 )
3232 {
3233 int len;
3234
3235 /* strlen of "name=value" */
3236 len = size2int_sat(strlen(name) + 1 + strlen(value));
3237
3238 if (out_chars != 0) {
3239 out_chars += 2;
3240 if ((out_linecount + len + 2) > MAXOUTLINE) {
3241 fputs(",\n", fp);
3242 out_linecount = 0;
3243 } else {
3244 fputs(", ", fp);
3245 out_linecount += 2;
3246 }
3247 }
3248
3249 fputs(name, fp);
3250 putc('=', fp);
3251 fputs(value, fp);
3252 out_chars += len;
3253 out_linecount += len;
3254 }
3255
3256
3257 /*
3258 * endoutput - terminate a block of cooked output
3259 */
3260 static void
3261 endoutput(
3262 FILE *fp
3263 )
3264 {
3265 if (out_chars != 0)
3266 putc('\n', fp);
3267 }
3268
3269
3270 /*
3271 * outputarr - output an array of values
3272 */
3273 static void
3274 outputarr(
3275 FILE *fp,
3276 char *name,
3277 int narr,
3278 l_fp *lfp
3279 )
3280 {
3281 char *bp;
3282 char *cp;
3283 size_t i;
3284 size_t len;
3285 char buf[256];
3286
3287 bp = buf;
3288 /*
3289 * Hack to align delay and offset values
3290 */
3291 for (i = (int)strlen(name); i < 11; i++)
3292 *bp++ = ' ';
3293
3294 for (i = narr; i > 0; i--) {
3295 if (i != (size_t)narr)
3296 *bp++ = ' ';
3297 cp = lfptoms(lfp, 2);
3298 len = strlen(cp);
3299 if (len > 7) {
3300 cp[7] = '\0';
3301 len = 7;
3302 }
3303 while (len < 7) {
3304 *bp++ = ' ';
3305 len++;
3306 }
3307 while (*cp != '\0')
3308 *bp++ = *cp++;
3309 lfp++;
3310 }
3311 *bp = '\0';
3312 output(fp, name, buf);
3313 }
3314
3315 static char *
3316 tstflags(
3317 u_long val
3318 )
3319 {
3320 register char *cp, *s;
3321 size_t cb;
3322 register int i;
3323 register const char *sep;
3324
3325 sep = "";
3326 s = cp = circ_buf[nextcb];
3327 if (++nextcb >= NUMCB)
3328 nextcb = 0;
3329 cb = sizeof(circ_buf[0]);
3330
3331 snprintf(cp, cb, "%02lx", val);
3332 cp += strlen(cp);
3333 cb -= strlen(cp);
3334 if (!val) {
3335 strlcat(cp, " ok", cb);
3336 cp += strlen(cp);
3337 cb -= strlen(cp);
3338 } else {
3339 if (cb) {
3340 *cp++ = ' ';
3341 cb--;
3342 }
3343 for (i = 0; i < (int)COUNTOF(tstflagnames); i++) {
3344 if (val & 0x1) {
3345 snprintf(cp, cb, "%s%s", sep,
3346 tstflagnames[i]);
3347 sep = ", ";
3348 cp += strlen(cp);
3349 cb -= strlen(cp);
3350 }
3351 val >>= 1;
3352 }
3353 }
3354 if (cb)
3355 *cp = '\0';
3356
3357 return s;
3358 }
3359
3360 /*
3361 * cookedprint - output variables in cooked mode
3362 */
3363 static void
3364 cookedprint(
3365 int datatype,
3366 size_t length,
3367 const char *data,
3368 int status,
3369 int quiet,
3370 FILE *fp
3371 )
3372 {
3373 char *name;
3374 char *value;
3375 char output_raw;
3376 int fmt;
3377 l_fp lfp;
3378 sockaddr_u hval;
3379 u_long uval;
3380 int narr;
3381 size_t len;
3382 l_fp lfparr[8];
3383 char b[12];
3384 char bn[2 * MAXVARLEN];
3385 char bv[2 * MAXVALLEN];
3386
3387 UNUSED_ARG(datatype);
3388
3389 if (!quiet)
3390 fprintf(fp, "status=%04x %s,\n", status,
3391 statustoa(datatype, status));
3392
3393 startoutput();
3394 while (nextvar(&length, &data, &name, &value)) {
3395 fmt = varfmt(name);
3396 output_raw = 0;
3397 switch (fmt) {
3398
3399 case PADDING:
3400 output_raw = '*';
3401 break;
3402
3403 case TS:
3404 if (!decodets(value, &lfp))
3405 output_raw = '?';
3406 else
3407 output(fp, name, prettydate(&lfp));
3408 break;
3409
3410 case HA: /* fallthru */
3411 case NA:
3412 if (!decodenetnum(value, &hval)) {
3413 output_raw = '?';
3414 } else if (fmt == HA){
3415 output(fp, name, nntohost(&hval));
3416 } else {
3417 output(fp, name, stoa(&hval));
3418 }
3419 break;
3420
3421 case RF:
3422 if (decodenetnum(value, &hval)) {
3423 if (ISREFCLOCKADR(&hval))
3424 output(fp, name,
3425 refnumtoa(&hval));
3426 else
3427 output(fp, name, stoa(&hval));
3428 } else if (strlen(value) <= 4) {
3429 output(fp, name, value);
3430 } else {
3431 output_raw = '?';
3432 }
3433 break;
3434
3435 case LP:
3436 if (!decodeuint(value, &uval) || uval > 3) {
3437 output_raw = '?';
3438 } else {
3439 b[0] = (0x2 & uval)
3440 ? '1'
3441 : '0';
3442 b[1] = (0x1 & uval)
3443 ? '1'
3444 : '0';
3445 b[2] = '\0';
3446 output(fp, name, b);
3447 }
3448 break;
3449
3450 case OC:
3451 if (!decodeuint(value, &uval)) {
3452 output_raw = '?';
3453 } else {
3454 snprintf(b, sizeof(b), "%03lo", uval);
3455 output(fp, name, b);
3456 }
3457 break;
3458
3459 case AR:
3460 if (!decodearr(value, &narr, lfparr))
3461 output_raw = '?';
3462 else
3463 outputarr(fp, name, narr, lfparr);
3464 break;
3465
3466 case FX:
3467 if (!decodeuint(value, &uval))
3468 output_raw = '?';
3469 else
3470 output(fp, name, tstflags(uval));
3471 break;
3472
3473 default:
3474 fprintf(stderr, "Internal error in cookedprint, %s=%s, fmt %d\n",
3475 name, value, fmt);
3476 output_raw = '?';
3477 break;
3478 }
3479
3480 if (output_raw != 0) {
3481 /* TALOS-CAN-0063: avoid buffer overrun */
3482 atoascii(name, MAXVARLEN, bn, sizeof(bn));
3483 if (output_raw != '*') {
3484 atoascii(value, MAXVALLEN,
3485 bv, sizeof(bv) - 1);
3486 len = strlen(bv);
3487 bv[len] = output_raw;
3488 bv[len+1] = '\0';
3489 } else {
3490 atoascii(value, MAXVALLEN,
3491 bv, sizeof(bv));
3492 }
3493 output(fp, bn, bv);
3494 }
3495 }
3496 endoutput(fp);
3497 }
3498
3499
3500 /*
3501 * sortassoc - sort associations in the cache into ascending order
3502 */
3503 void
3504 sortassoc(void)
3505 {
3506 if (numassoc > 1)
3507 qsort(assoc_cache, (size_t)numassoc,
3508 sizeof(assoc_cache[0]), &assoccmp);
3509 }
3510
3511
3512 /*
3513 * assoccmp - compare two associations
3514 */
3515 static int
3516 assoccmp(
3517 const void *t1,
3518 const void *t2
3519 )
3520 {
3521 const struct association *ass1 = t1;
3522 const struct association *ass2 = t2;
3523
3524 if (ass1->assid < ass2->assid)
3525 return -1;
3526 if (ass1->assid > ass2->assid)
3527 return 1;
3528 return 0;
3529 }
3530
3531
3532 /*
3533 * grow_assoc_cache() - enlarge dynamic assoc_cache array
3534 *
3535 * The strategy is to add an assumed 4k page size at a time, leaving
3536 * room for malloc() bookkeeping overhead equivalent to 4 pointers.
3537 */
3538 void
3539 grow_assoc_cache(void)
3540 {
3541 static size_t prior_sz;
3542 size_t new_sz;
3543
3544 new_sz = prior_sz + 4 * 1024;
3545 if (0 == prior_sz) {
3546 new_sz -= 4 * sizeof(void *);
3547 }
3548 assoc_cache = erealloc_zero(assoc_cache, new_sz, prior_sz);
3549 prior_sz = new_sz;
3550 assoc_cache_slots = (u_int)(new_sz / sizeof(assoc_cache[0]));
3551 }
3552
3553
3554 /*
3555 * ntpq_custom_opt_handler - autoopts handler for -c and -p
3556 *
3557 * By default, autoopts loses the relative order of -c and -p options
3558 * on the command line. This routine replaces the default handler for
3559 * those routines and builds a list of commands to execute preserving
3560 * the order.
3561 */
3562 void
3563 ntpq_custom_opt_handler(
3564 tOptions *pOptions,
3565 tOptDesc *pOptDesc
3566 )
3567 {
3568 switch (pOptDesc->optValue) {
3569
3570 default:
3571 fprintf(stderr,
3572 "ntpq_custom_opt_handler unexpected option '%c' (%d)\n",
3573 pOptDesc->optValue, pOptDesc->optValue);
3574 exit(1);
3575
3576 case 'c':
3577 ADDCMD(pOptDesc->pzLastArg);
3578 break;
3579
3580 case 'p':
3581 ADDCMD("peers");
3582 break;
3583 }
3584 }
3585 /*
3586 * Obtain list of digest names
3587 */
3588
3589 #ifdef OPENSSL
3590 # ifdef HAVE_EVP_MD_DO_ALL_SORTED
3591 struct hstate {
3592 char *list;
3593 const char **seen;
3594 int idx;
3595 };
3596 #define K_PER_LINE 8
3597 #define K_NL_PFX_STR "\n "
3598 #define K_DELIM_STR ", "
3599 static void list_md_fn(const EVP_MD *m, const char *from, const char *to, void *arg )
3600 {
3601 size_t len, n;
3602 const char *name, *cp, **seen;
3603 struct hstate *hstate = arg;
3604 EVP_MD_CTX *ctx;
3605 u_int digest_len;
3606 u_char digest[EVP_MAX_MD_SIZE];
3607
3608 if (!m)
3609 return; /* Ignore aliases */
3610
3611 name = EVP_MD_name(m);
3612
3613 /* Lowercase names aren't accepted by keytype_from_text in ssl_init.c */
3614
3615 for( cp = name; *cp; cp++ ) {
3616 if( islower((unsigned char)*cp) )
3617 return;
3618 }
3619 len = (cp - name) + 1;
3620
3621 /* There are duplicates. Discard if name has been seen. */
3622
3623 for (seen = hstate->seen; *seen; seen++)
3624 if (!strcmp(*seen, name))
3625 return;
3626 n = (seen - hstate->seen) + 2;
3627 hstate->seen = erealloc(hstate->seen, n * sizeof(*seen));
3628 hstate->seen[n-2] = name;
3629 hstate->seen[n-1] = NULL;
3630
3631 /* Discard MACs that NTP won't accept.
3632 * Keep this consistent with keytype_from_text() in ssl_init.c.
3633 */
3634
3635 ctx = EVP_MD_CTX_new();
3636 EVP_DigestInit(ctx, EVP_get_digestbyname(name));
3637 EVP_DigestFinal(ctx, digest, &digest_len);
3638 EVP_MD_CTX_free(ctx);
3639 if (digest_len > (MAX_MAC_LEN - sizeof(keyid_t)))
3640 return;
3641
3642 if (hstate->list != NULL)
3643 len += strlen(hstate->list);
3644 len += (hstate->idx >= K_PER_LINE)? strlen(K_NL_PFX_STR): strlen(K_DELIM_STR);
3645
3646 if (hstate->list == NULL) {
3647 hstate->list = (char *)emalloc(len);
3648 hstate->list[0] = '\0';
3649 } else
3650 hstate->list = (char *)erealloc(hstate->list, len);
3651
3652 sprintf(hstate->list + strlen(hstate->list), "%s%s",
3653 ((hstate->idx >= K_PER_LINE)? K_NL_PFX_STR : K_DELIM_STR),
3654 name);
3655 if (hstate->idx >= K_PER_LINE)
3656 hstate->idx = 1;
3657 else
3658 hstate->idx++;
3659 }
3660 # endif
3661 #endif
3662
3663 static char *list_digest_names(void)
3664 {
3665 char *list = NULL;
3666
3667 #ifdef OPENSSL
3668 # ifdef HAVE_EVP_MD_DO_ALL_SORTED
3669 struct hstate hstate = { NULL, NULL, K_PER_LINE+1 };
3670
3671 hstate.seen = (const char **) emalloc_zero(1*sizeof( const char * )); // replaces -> calloc(1, sizeof( const char * ));
3672
3673 INIT_SSL();
3674 EVP_MD_do_all_sorted(list_md_fn, &hstate);
3675 list = hstate.list;
3676 free(hstate.seen);
3677 # else
3678 list = (char *)emalloc(sizeof("md5, others (upgrade to OpenSSL-1.0 for full list)"));
3679 strcpy(list, "md5, others (upgrade to OpenSSL-1.0 for full list)");
3680 # endif
3681 #else
3682 list = (char *)emalloc(sizeof("md5"));
3683 strcpy(list, "md5");
3684 #endif
3685
3686 return list;
3687 }
3688
3689 #define CTRLC_STACK_MAX 4
3690 static volatile size_t ctrlc_stack_len = 0;
3691 static volatile Ctrl_C_Handler ctrlc_stack[CTRLC_STACK_MAX];
3692
3693
3694
3695 int/*BOOL*/
3696 push_ctrl_c_handler(
3697 Ctrl_C_Handler func
3698 )
3699 {
3700 size_t size = ctrlc_stack_len;
3701 if (func && (size < CTRLC_STACK_MAX)) {
3702 ctrlc_stack[size] = func;
3703 ctrlc_stack_len = size + 1;
3704 return TRUE;
3705 }
3706 return FALSE;
3707 }
3708
3709 int/*BOOL*/
3710 pop_ctrl_c_handler(
3711 Ctrl_C_Handler func
3712 )
3713 {
3714 size_t size = ctrlc_stack_len;
3715 if (size) {
3716 --size;
3717 if (func == NULL || func == ctrlc_stack[size]) {
3718 ctrlc_stack_len = size;
3719 return TRUE;
3720 }
3721 }
3722 return FALSE;
3723 }
3724
3725 static void
3726 on_ctrlc(void)
3727 {
3728 size_t size = ctrlc_stack_len;
3729 while (size)
3730 if ((*ctrlc_stack[--size])())
3731 break;
3732 }
3733
3734 static int
3735 my_easprintf(
3736 char ** ppinto,
3737 const char * fmt ,
3738 ...
3739 )
3740 {
3741 va_list va;
3742 int prc;
3743 size_t len = 128;
3744 char * buf = emalloc(len);
3745
3746 again:
3747 /* Note: we expect the memory allocation to fail long before the
3748 * increment in buffer size actually overflows.
3749 */
3750 buf = (buf) ? erealloc(buf, len) : emalloc(len);
3751
3752 va_start(va, fmt);
3753 prc = vsnprintf(buf, len, fmt, va);
3754 va_end(va);
3755
3756 if (prc < 0) {
3757 /* might be very old vsnprintf. Or actually MSVC... */
3758 len += len >> 1;
3759 goto again;
3760 }
3761 if ((size_t)prc >= len) {
3762 /* at least we have the proper size now... */
3763 len = (size_t)prc + 1;
3764 goto again;
3765 }
3766 if ((size_t)prc < (len - 32))
3767 buf = erealloc(buf, (size_t)prc + 1);
3768 *ppinto = buf;
3769 return prc;
3770 }
3771