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