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