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