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 size_t 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 size_t 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 /* every line shows at most 16 bytes, so we need a buffer of 780 * 4 * 16 (2 xdigits, 1 char, one sep for xdigits) 781 * + 2 * 1 (block separators) 782 * + <LF> + <NUL> 783 *--------------- 784 * 68 bytes 785 */ 786 static const char s_xdig[16] = "0123456789ABCDEF"; 787 788 char lbuf[68]; 789 int ch, rowlen; 790 const u_char * cdata = data; 791 char *xptr, *pptr; 792 793 while (len) { 794 memset(lbuf, ' ', sizeof(lbuf)); 795 xptr = lbuf; 796 pptr = lbuf + 3*16 + 2; 797 798 rowlen = (len > 16) ? 16 : (int)len; 799 len -= rowlen; 800 801 do { 802 ch = *cdata++; 803 804 *xptr++ = s_xdig[ch >> 4 ]; 805 *xptr++ = s_xdig[ch & 0x0F]; 806 if (++xptr == lbuf + 3*8) 807 ++xptr; 808 809 *pptr++ = isprint(ch) ? (char)ch : '.'; 810 } while (--rowlen); 811 812 *pptr++ = '\n'; 813 *pptr = '\0'; 814 fputs(lbuf, stdout); 815 } 816 } 817 818 819 /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */ 820 /* 821 * sendpkt - send a packet to the remote host 822 */ 823 static int 824 sendpkt( 825 void * xdata, 826 size_t xdatalen 827 ) 828 { 829 if (debug >= 3) 830 printf("Sending %zu octets\n", xdatalen); 831 832 if (send(sockfd, xdata, xdatalen, 0) == -1) { 833 warning("write to %s failed", currenthost); 834 return -1; 835 } 836 837 if (debug >= 4) { 838 printf("Request packet:\n"); 839 dump_hex_printable(xdata, xdatalen); 840 } 841 return 0; 842 } 843 844 /* 845 * getresponse - get a (series of) response packet(s) and return the data 846 */ 847 static int 848 getresponse( 849 int opcode, 850 int associd, 851 u_short *rstatus, 852 size_t *rsize, 853 const char **rdata, 854 int timeo 855 ) 856 { 857 struct ntp_control rpkt; 858 struct sock_timeval tvo; 859 u_short offsets[MAXFRAGS+1]; 860 u_short counts[MAXFRAGS+1]; 861 u_short offset; 862 u_short count; 863 size_t numfrags; 864 size_t f; 865 size_t ff; 866 int seenlastfrag; 867 int shouldbesize; 868 fd_set fds; 869 int n; 870 int errcode; 871 /* absolute timeout checks. Not 'time_t' by intention! */ 872 uint32_t tobase; /* base value for timeout */ 873 uint32_t tospan; /* timeout span (max delay) */ 874 uint32_t todiff; /* current delay */ 875 876 memset(offsets, 0, sizeof(offsets)); 877 memset(counts , 0, sizeof(counts )); 878 879 /* 880 * This is pretty tricky. We may get between 1 and MAXFRAG packets 881 * back in response to the request. We peel the data out of 882 * each packet and collect it in one long block. When the last 883 * packet in the sequence is received we'll know how much data we 884 * should have had. Note we use one long time out, should reconsider. 885 */ 886 *rsize = 0; 887 if (rstatus) 888 *rstatus = 0; 889 *rdata = (char *)pktdata; 890 891 numfrags = 0; 892 seenlastfrag = 0; 893 894 tobase = (uint32_t)time(NULL); 895 896 FD_ZERO(&fds); 897 898 /* 899 * Loop until we have an error or a complete response. Nearly all 900 * code paths to loop again use continue. 901 */ 902 for (;;) { 903 904 if (numfrags == 0) 905 tvo = tvout; 906 else 907 tvo = tvsout; 908 tospan = (uint32_t)tvo.tv_sec + (tvo.tv_usec != 0); 909 910 FD_SET(sockfd, &fds); 911 n = select(sockfd+1, &fds, NULL, NULL, &tvo); 912 if (n == -1) { 913 #if !defined(SYS_WINNT) && defined(EINTR) 914 /* Windows does not know about EINTR (until very 915 * recently) and the handling of console events 916 * is *very* different from POSIX/UNIX signal 917 * handling anyway. 918 * 919 * Under non-windows targets we map EINTR as 920 * 'last packet was received' and try to exit 921 * the receive sequence. 922 */ 923 if (errno == EINTR) { 924 seenlastfrag = 1; 925 goto maybe_final; 926 } 927 #endif 928 warning("select fails"); 929 return -1; 930 } 931 932 /* 933 * Check if this is already too late. Trash the data and 934 * fake a timeout if this is so. 935 */ 936 todiff = (((uint32_t)time(NULL)) - tobase) & 0x7FFFFFFFu; 937 if ((n > 0) && (todiff > tospan)) { 938 n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0); 939 n -= n; /* faked timeout return from 'select()', 940 * execute RMW cycle on 'n' 941 */ 942 } 943 944 if (n <= 0) { 945 /* 946 * Timed out. Return what we have 947 */ 948 if (numfrags == 0) { 949 if (timeo) 950 fprintf(stderr, 951 "%s: timed out, nothing received\n", 952 currenthost); 953 return ERR_TIMEOUT; 954 } 955 if (timeo) 956 fprintf(stderr, 957 "%s: timed out with incomplete data\n", 958 currenthost); 959 if (debug) { 960 fprintf(stderr, 961 "ERR_INCOMPLETE: Received fragments:\n"); 962 for (f = 0; f < numfrags; f++) 963 fprintf(stderr, 964 "%2u: %5d %5d\t%3d octets\n", 965 (u_int)f, offsets[f], 966 offsets[f] + 967 counts[f], 968 counts[f]); 969 fprintf(stderr, 970 "last fragment %sreceived\n", 971 (seenlastfrag) 972 ? "" 973 : "not "); 974 } 975 return ERR_INCOMPLETE; 976 } 977 978 n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0); 979 if (n < 0) { 980 warning("read"); 981 return -1; 982 } 983 984 if (debug >= 4) { 985 printf("Response packet:\n"); 986 dump_hex_printable(&rpkt, n); 987 } 988 989 /* 990 * Check for format errors. Bug proofing. 991 */ 992 if (n < (int)CTL_HEADER_LEN) { 993 if (debug) 994 printf("Short (%d byte) packet received\n", n); 995 continue; 996 } 997 if (PKT_VERSION(rpkt.li_vn_mode) > NTP_VERSION 998 || PKT_VERSION(rpkt.li_vn_mode) < NTP_OLDVERSION) { 999 if (debug) 1000 printf("Packet received with version %d\n", 1001 PKT_VERSION(rpkt.li_vn_mode)); 1002 continue; 1003 } 1004 if (PKT_MODE(rpkt.li_vn_mode) != MODE_CONTROL) { 1005 if (debug) 1006 printf("Packet received with mode %d\n", 1007 PKT_MODE(rpkt.li_vn_mode)); 1008 continue; 1009 } 1010 if (!CTL_ISRESPONSE(rpkt.r_m_e_op)) { 1011 if (debug) 1012 printf("Received request packet, wanted response\n"); 1013 continue; 1014 } 1015 1016 /* 1017 * Check opcode and sequence number for a match. 1018 * Could be old data getting to us. 1019 */ 1020 if (ntohs(rpkt.sequence) != sequence) { 1021 if (debug) 1022 printf("Received sequnce number %d, wanted %d\n", 1023 ntohs(rpkt.sequence), sequence); 1024 continue; 1025 } 1026 if (CTL_OP(rpkt.r_m_e_op) != opcode) { 1027 if (debug) 1028 printf( 1029 "Received opcode %d, wanted %d (sequence number okay)\n", 1030 CTL_OP(rpkt.r_m_e_op), opcode); 1031 continue; 1032 } 1033 1034 /* 1035 * Check the error code. If non-zero, return it. 1036 */ 1037 if (CTL_ISERROR(rpkt.r_m_e_op)) { 1038 errcode = (ntohs(rpkt.status) >> 8) & 0xff; 1039 if (CTL_ISMORE(rpkt.r_m_e_op)) 1040 TRACE(1, ("Error code %d received on not-final packet\n", 1041 errcode)); 1042 if (errcode == CERR_UNSPEC) 1043 return ERR_UNSPEC; 1044 return errcode; 1045 } 1046 1047 /* 1048 * Check the association ID to make sure it matches what 1049 * we sent. 1050 */ 1051 if (ntohs(rpkt.associd) != associd) { 1052 TRACE(1, ("Association ID %d doesn't match expected %d\n", 1053 ntohs(rpkt.associd), associd)); 1054 /* 1055 * Hack for silly fuzzballs which, at the time of writing, 1056 * return an assID of sys.peer when queried for system variables. 1057 */ 1058 #ifdef notdef 1059 continue; 1060 #endif 1061 } 1062 1063 /* 1064 * Collect offset and count. Make sure they make sense. 1065 */ 1066 offset = ntohs(rpkt.offset); 1067 count = ntohs(rpkt.count); 1068 1069 /* 1070 * validate received payload size is padded to next 32-bit 1071 * boundary and no smaller than claimed by rpkt.count 1072 */ 1073 if (n & 0x3) { 1074 TRACE(1, ("Response packet not padded, size = %d\n", 1075 n)); 1076 continue; 1077 } 1078 1079 shouldbesize = (CTL_HEADER_LEN + count + 3) & ~3; 1080 1081 if (n < shouldbesize) { 1082 printf("Response packet claims %u octets payload, above %ld received\n", 1083 count, (long)(n - CTL_HEADER_LEN)); 1084 return ERR_INCOMPLETE; 1085 } 1086 1087 if (debug >= 3 && shouldbesize > n) { 1088 u_int32 key; 1089 u_int32 *lpkt; 1090 int maclen; 1091 1092 /* 1093 * Usually we ignore authentication, but for debugging purposes 1094 * we watch it here. 1095 */ 1096 /* round to 8 octet boundary */ 1097 shouldbesize = (shouldbesize + 7) & ~7; 1098 1099 maclen = n - shouldbesize; 1100 if (maclen >= (int)MIN_MAC_LEN) { 1101 printf( 1102 "Packet shows signs of authentication (total %d, data %d, mac %d)\n", 1103 n, shouldbesize, maclen); 1104 lpkt = (u_int32 *)&rpkt; 1105 printf("%08lx %08lx %08lx %08lx %08lx %08lx\n", 1106 (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) - 3]), 1107 (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) - 2]), 1108 (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) - 1]), 1109 (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32)]), 1110 (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) + 1]), 1111 (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_int32) + 2])); 1112 key = ntohl(lpkt[(n - maclen) / sizeof(u_int32)]); 1113 printf("Authenticated with keyid %lu\n", (u_long)key); 1114 if (key != 0 && key != info_auth_keyid) { 1115 printf("We don't know that key\n"); 1116 } else { 1117 if (authdecrypt(key, (u_int32 *)&rpkt, 1118 n - maclen, maclen)) { 1119 printf("Auth okay!\n"); 1120 } else { 1121 printf("Auth failed!\n"); 1122 } 1123 } 1124 } 1125 } 1126 1127 TRACE(2, ("Got packet, size = %d\n", n)); 1128 if (count > (n - CTL_HEADER_LEN)) { 1129 TRACE(1, ("Received count of %u octets, data in packet is %ld\n", 1130 count, (long)n - CTL_HEADER_LEN)); 1131 continue; 1132 } 1133 if (count == 0 && CTL_ISMORE(rpkt.r_m_e_op)) { 1134 TRACE(1, ("Received count of 0 in non-final fragment\n")); 1135 continue; 1136 } 1137 if (offset + count > sizeof(pktdata)) { 1138 TRACE(1, ("Offset %u, count %u, too big for buffer\n", 1139 offset, count)); 1140 return ERR_TOOMUCH; 1141 } 1142 if (seenlastfrag && !CTL_ISMORE(rpkt.r_m_e_op)) { 1143 TRACE(1, ("Received second last fragment packet\n")); 1144 continue; 1145 } 1146 1147 /* 1148 * So far, so good. Record this fragment, making sure it doesn't 1149 * overlap anything. 1150 */ 1151 TRACE(2, ("Packet okay\n")); 1152 1153 if (numfrags > (MAXFRAGS - 1)) { 1154 TRACE(2, ("Number of fragments exceeds maximum %d\n", 1155 MAXFRAGS - 1)); 1156 return ERR_TOOMUCH; 1157 } 1158 1159 /* 1160 * Find the position for the fragment relative to any 1161 * previously received. 1162 */ 1163 for (f = 0; 1164 f < numfrags && offsets[f] < offset; 1165 f++) { 1166 /* empty body */ ; 1167 } 1168 1169 if (f < numfrags && offset == offsets[f]) { 1170 TRACE(1, ("duplicate %u octets at %u ignored, prior %u at %u\n", 1171 count, offset, counts[f], offsets[f])); 1172 continue; 1173 } 1174 1175 if (f > 0 && (offsets[f-1] + counts[f-1]) > offset) { 1176 TRACE(1, ("received frag at %u overlaps with %u octet frag at %u\n", 1177 offset, counts[f-1], offsets[f-1])); 1178 continue; 1179 } 1180 1181 if (f < numfrags && (offset + count) > offsets[f]) { 1182 TRACE(1, ("received %u octet frag at %u overlaps with frag at %u\n", 1183 count, offset, offsets[f])); 1184 continue; 1185 } 1186 1187 for (ff = numfrags; ff > f; ff--) { 1188 offsets[ff] = offsets[ff-1]; 1189 counts[ff] = counts[ff-1]; 1190 } 1191 offsets[f] = offset; 1192 counts[f] = count; 1193 numfrags++; 1194 1195 /* 1196 * Got that stuffed in right. Figure out if this was the last. 1197 * Record status info out of the last packet. 1198 */ 1199 if (!CTL_ISMORE(rpkt.r_m_e_op)) { 1200 seenlastfrag = 1; 1201 if (rstatus != 0) 1202 *rstatus = ntohs(rpkt.status); 1203 } 1204 1205 /* 1206 * Copy the data into the data buffer, and bump the 1207 * timout base in case we need more. 1208 */ 1209 memcpy((char *)pktdata + offset, &rpkt.u, count); 1210 tobase = (uint32_t)time(NULL); 1211 1212 /* 1213 * If we've seen the last fragment, look for holes in the sequence. 1214 * If there aren't any, we're done. 1215 */ 1216 #if !defined(SYS_WINNT) && defined(EINTR) 1217 maybe_final: 1218 #endif 1219 1220 if (seenlastfrag && offsets[0] == 0) { 1221 for (f = 1; f < numfrags; f++) 1222 if (offsets[f-1] + counts[f-1] != 1223 offsets[f]) 1224 break; 1225 if (f == numfrags) { 1226 *rsize = offsets[f-1] + counts[f-1]; 1227 TRACE(1, ("%lu packets reassembled into response\n", 1228 (u_long)numfrags)); 1229 return 0; 1230 } 1231 } 1232 } /* giant for (;;) collecting response packets */ 1233 } /* getresponse() */ 1234 1235 1236 /* 1237 * sendrequest - format and send a request packet 1238 */ 1239 static int 1240 sendrequest( 1241 int opcode, 1242 associd_t associd, 1243 int auth, 1244 size_t qsize, 1245 const char *qdata 1246 ) 1247 { 1248 struct ntp_control qpkt; 1249 size_t pktsize; 1250 u_long key_id; 1251 char * pass; 1252 size_t maclen; 1253 1254 /* 1255 * Check to make sure the data will fit in one packet 1256 */ 1257 if (qsize > CTL_MAX_DATA_LEN) { 1258 fprintf(stderr, 1259 "***Internal error! qsize (%zu) too large\n", 1260 qsize); 1261 return 1; 1262 } 1263 1264 /* 1265 * Fill in the packet 1266 */ 1267 qpkt.li_vn_mode = PKT_LI_VN_MODE(0, pktversion, MODE_CONTROL); 1268 qpkt.r_m_e_op = (u_char)(opcode & CTL_OP_MASK); 1269 qpkt.sequence = htons(sequence); 1270 qpkt.status = 0; 1271 qpkt.associd = htons((u_short)associd); 1272 qpkt.offset = 0; 1273 qpkt.count = htons((u_short)qsize); 1274 1275 pktsize = CTL_HEADER_LEN; 1276 1277 /* 1278 * If we have data, copy and pad it out to a 32-bit boundary. 1279 */ 1280 if (qsize > 0) { 1281 memcpy(&qpkt.u, qdata, (size_t)qsize); 1282 pktsize += qsize; 1283 while (pktsize & (sizeof(u_int32) - 1)) { 1284 qpkt.u.data[qsize++] = 0; 1285 pktsize++; 1286 } 1287 } 1288 1289 /* 1290 * If it isn't authenticated we can just send it. Otherwise 1291 * we're going to have to think about it a little. 1292 */ 1293 if (!auth && !always_auth) { 1294 return sendpkt(&qpkt, pktsize); 1295 } 1296 1297 /* 1298 * Pad out packet to a multiple of 8 octets to be sure 1299 * receiver can handle it. 1300 */ 1301 while (pktsize & 7) { 1302 qpkt.u.data[qsize++] = 0; 1303 pktsize++; 1304 } 1305 1306 /* 1307 * Get the keyid and the password if we don't have one. 1308 */ 1309 if (info_auth_keyid == 0) { 1310 key_id = getkeyid("Keyid: "); 1311 if (key_id == 0 || key_id > NTP_MAXKEY) { 1312 fprintf(stderr, 1313 "Invalid key identifier\n"); 1314 return 1; 1315 } 1316 info_auth_keyid = key_id; 1317 } 1318 if (!authistrusted(info_auth_keyid)) { 1319 pass = getpass_keytype(info_auth_keytype); 1320 if ('\0' == pass[0]) { 1321 fprintf(stderr, "Invalid password\n"); 1322 return 1; 1323 } 1324 authusekey(info_auth_keyid, info_auth_keytype, 1325 (u_char *)pass); 1326 authtrust(info_auth_keyid, 1); 1327 } 1328 1329 /* 1330 * Do the encryption. 1331 */ 1332 maclen = authencrypt(info_auth_keyid, (void *)&qpkt, pktsize); 1333 if (!maclen) { 1334 fprintf(stderr, "Key not found\n"); 1335 return 1; 1336 } else if ((size_t)maclen != (info_auth_hashlen + sizeof(keyid_t))) { 1337 fprintf(stderr, 1338 "%zu octet MAC, %zu expected with %zu octet digest\n", 1339 maclen, (info_auth_hashlen + sizeof(keyid_t)), 1340 info_auth_hashlen); 1341 return 1; 1342 } 1343 1344 return sendpkt((char *)&qpkt, pktsize + maclen); 1345 } 1346 1347 1348 /* 1349 * show_error_msg - display the error text for a mode 6 error response. 1350 */ 1351 void 1352 show_error_msg( 1353 int m6resp, 1354 associd_t associd 1355 ) 1356 { 1357 if (numhosts > 1) 1358 fprintf(stderr, "server=%s ", currenthost); 1359 1360 switch (m6resp) { 1361 1362 case CERR_BADFMT: 1363 fprintf(stderr, 1364 "***Server reports a bad format request packet\n"); 1365 break; 1366 1367 case CERR_PERMISSION: 1368 fprintf(stderr, 1369 "***Server disallowed request (authentication?)\n"); 1370 break; 1371 1372 case CERR_BADOP: 1373 fprintf(stderr, 1374 "***Server reports a bad opcode in request\n"); 1375 break; 1376 1377 case CERR_BADASSOC: 1378 fprintf(stderr, 1379 "***Association ID %d unknown to server\n", 1380 associd); 1381 break; 1382 1383 case CERR_UNKNOWNVAR: 1384 fprintf(stderr, 1385 "***A request variable unknown to the server\n"); 1386 break; 1387 1388 case CERR_BADVALUE: 1389 fprintf(stderr, 1390 "***Server indicates a request variable was bad\n"); 1391 break; 1392 1393 case ERR_UNSPEC: 1394 fprintf(stderr, 1395 "***Server returned an unspecified error\n"); 1396 break; 1397 1398 case ERR_TIMEOUT: 1399 fprintf(stderr, "***Request timed out\n"); 1400 break; 1401 1402 case ERR_INCOMPLETE: 1403 fprintf(stderr, 1404 "***Response from server was incomplete\n"); 1405 break; 1406 1407 case ERR_TOOMUCH: 1408 fprintf(stderr, 1409 "***Buffer size exceeded for returned data\n"); 1410 break; 1411 1412 default: 1413 fprintf(stderr, 1414 "***Server returns unknown error code %d\n", 1415 m6resp); 1416 } 1417 } 1418 1419 /* 1420 * doquery - send a request and process the response, displaying 1421 * error messages for any error responses. 1422 */ 1423 int 1424 doquery( 1425 int opcode, 1426 associd_t associd, 1427 int auth, 1428 size_t qsize, 1429 const char *qdata, 1430 u_short *rstatus, 1431 size_t *rsize, 1432 const char **rdata 1433 ) 1434 { 1435 return doqueryex(opcode, associd, auth, qsize, qdata, rstatus, 1436 rsize, rdata, FALSE); 1437 } 1438 1439 1440 /* 1441 * doqueryex - send a request and process the response, optionally 1442 * displaying error messages for any error responses. 1443 */ 1444 int 1445 doqueryex( 1446 int opcode, 1447 associd_t associd, 1448 int auth, 1449 size_t qsize, 1450 const char *qdata, 1451 u_short *rstatus, 1452 size_t *rsize, 1453 const char **rdata, 1454 int quiet 1455 ) 1456 { 1457 int res; 1458 int done; 1459 1460 /* 1461 * Check to make sure host is open 1462 */ 1463 if (!havehost) { 1464 fprintf(stderr, "***No host open, use `host' command\n"); 1465 return -1; 1466 } 1467 1468 done = 0; 1469 sequence++; 1470 1471 again: 1472 /* 1473 * send a request 1474 */ 1475 res = sendrequest(opcode, associd, auth, qsize, qdata); 1476 if (res != 0) 1477 return res; 1478 1479 /* 1480 * Get the response. If we got a standard error, print a message 1481 */ 1482 res = getresponse(opcode, associd, rstatus, rsize, rdata, done); 1483 1484 if (res > 0) { 1485 if (!done && (res == ERR_TIMEOUT || res == ERR_INCOMPLETE)) { 1486 if (res == ERR_INCOMPLETE) { 1487 /* 1488 * better bump the sequence so we don't 1489 * get confused about differing fragments. 1490 */ 1491 sequence++; 1492 } 1493 done = 1; 1494 goto again; 1495 } 1496 if (!quiet) 1497 show_error_msg(res, associd); 1498 1499 } 1500 return res; 1501 } 1502 1503 1504 #ifndef BUILD_AS_LIB 1505 /* 1506 * getcmds - read commands from the standard input and execute them 1507 */ 1508 static void 1509 getcmds(void) 1510 { 1511 char * line; 1512 int count; 1513 1514 ntp_readline_init(interactive ? prompt : NULL); 1515 1516 for (;;) { 1517 line = ntp_readline(&count); 1518 if (NULL == line) 1519 break; 1520 docmd(line); 1521 free(line); 1522 } 1523 1524 ntp_readline_uninit(); 1525 } 1526 #endif /* !BUILD_AS_LIB */ 1527 1528 1529 #if !defined(SYS_WINNT) && !defined(BUILD_AS_LIB) 1530 /* 1531 * abortcmd - catch interrupts and abort the current command 1532 */ 1533 static int 1534 abortcmd(void) 1535 { 1536 if (current_output == stdout) 1537 (void) fflush(stdout); 1538 putc('\n', stderr); 1539 (void) fflush(stderr); 1540 if (jump) { 1541 jump = 0; 1542 longjmp(interrupt_buf, 1); 1543 } 1544 return TRUE; 1545 } 1546 #endif /* !SYS_WINNT && !BUILD_AS_LIB */ 1547 1548 1549 #ifndef BUILD_AS_LIB 1550 /* 1551 * docmd - decode the command line and execute a command 1552 */ 1553 static void 1554 docmd( 1555 const char *cmdline 1556 ) 1557 { 1558 char *tokens[1+MAXARGS+2]; 1559 struct parse pcmd; 1560 int ntok; 1561 static int i; 1562 struct xcmd *xcmd; 1563 1564 /* 1565 * Tokenize the command line. If nothing on it, return. 1566 */ 1567 tokenize(cmdline, tokens, &ntok); 1568 if (ntok == 0) 1569 return; 1570 1571 /* 1572 * Find the appropriate command description. 1573 */ 1574 i = findcmd(tokens[0], builtins, opcmds, &xcmd); 1575 if (i == 0) { 1576 (void) fprintf(stderr, "***Command `%s' unknown\n", 1577 tokens[0]); 1578 return; 1579 } else if (i >= 2) { 1580 (void) fprintf(stderr, "***Command `%s' ambiguous\n", 1581 tokens[0]); 1582 return; 1583 } 1584 1585 /* Warn about ignored extra args */ 1586 for (i = MAXARGS + 1; i < ntok ; ++i) { 1587 fprintf(stderr, "***Extra arg `%s' ignored\n", tokens[i]); 1588 } 1589 1590 /* 1591 * Save the keyword, then walk through the arguments, interpreting 1592 * as we go. 1593 */ 1594 pcmd.keyword = tokens[0]; 1595 pcmd.nargs = 0; 1596 for (i = 0; i < MAXARGS && xcmd->arg[i] != NO; i++) { 1597 if ((i+1) >= ntok) { 1598 if (!(xcmd->arg[i] & OPT)) { 1599 printusage(xcmd, stderr); 1600 return; 1601 } 1602 break; 1603 } 1604 if ((xcmd->arg[i] & OPT) && (*tokens[i+1] == '>')) 1605 break; 1606 if (!getarg(tokens[i+1], (int)xcmd->arg[i], &pcmd.argval[i])) 1607 return; 1608 pcmd.nargs++; 1609 } 1610 1611 i++; 1612 if (i < ntok && *tokens[i] == '>') { 1613 char *fname; 1614 1615 if (*(tokens[i]+1) != '\0') 1616 fname = tokens[i]+1; 1617 else if ((i+1) < ntok) 1618 fname = tokens[i+1]; 1619 else { 1620 (void) fprintf(stderr, "***No file for redirect\n"); 1621 return; 1622 } 1623 1624 current_output = fopen(fname, "w"); 1625 if (current_output == NULL) { 1626 (void) fprintf(stderr, "***Error opening %s: ", fname); 1627 perror(""); 1628 return; 1629 } 1630 i = 1; /* flag we need a close */ 1631 } else { 1632 current_output = stdout; 1633 i = 0; /* flag no close */ 1634 } 1635 1636 if (interactive && setjmp(interrupt_buf)) { 1637 jump = 0; 1638 return; 1639 } else { 1640 jump++; 1641 (xcmd->handler)(&pcmd, current_output); 1642 jump = 0; /* HMS: 961106: was after fclose() */ 1643 if (i) (void) fclose(current_output); 1644 } 1645 1646 return; 1647 } 1648 1649 1650 /* 1651 * tokenize - turn a command line into tokens 1652 * 1653 * SK: Modified to allow a quoted string 1654 * 1655 * HMS: If the first character of the first token is a ':' then (after 1656 * eating inter-token whitespace) the 2nd token is the rest of the line. 1657 */ 1658 1659 static void 1660 tokenize( 1661 const char *line, 1662 char **tokens, 1663 int *ntok 1664 ) 1665 { 1666 register const char *cp; 1667 register char *sp; 1668 static char tspace[MAXLINE]; 1669 1670 sp = tspace; 1671 cp = line; 1672 for (*ntok = 0; *ntok < MAXTOKENS; (*ntok)++) { 1673 tokens[*ntok] = sp; 1674 1675 /* Skip inter-token whitespace */ 1676 while (ISSPACE(*cp)) 1677 cp++; 1678 1679 /* If we're at EOL we're done */ 1680 if (ISEOL(*cp)) 1681 break; 1682 1683 /* If this is the 2nd token and the first token begins 1684 * with a ':', then just grab to EOL. 1685 */ 1686 1687 if (*ntok == 1 && tokens[0][0] == ':') { 1688 do { 1689 if (sp - tspace >= MAXLINE) 1690 goto toobig; 1691 *sp++ = *cp++; 1692 } while (!ISEOL(*cp)); 1693 } 1694 1695 /* Check if this token begins with a double quote. 1696 * If yes, continue reading till the next double quote 1697 */ 1698 else if (*cp == '\"') { 1699 ++cp; 1700 do { 1701 if (sp - tspace >= MAXLINE) 1702 goto toobig; 1703 *sp++ = *cp++; 1704 } while ((*cp != '\"') && !ISEOL(*cp)); 1705 /* HMS: a missing closing " should be an error */ 1706 } 1707 else { 1708 do { 1709 if (sp - tspace >= MAXLINE) 1710 goto toobig; 1711 *sp++ = *cp++; 1712 } while ((*cp != '\"') && !ISSPACE(*cp) && !ISEOL(*cp)); 1713 /* HMS: Why check for a " in the previous line? */ 1714 } 1715 1716 if (sp - tspace >= MAXLINE) 1717 goto toobig; 1718 *sp++ = '\0'; 1719 } 1720 return; 1721 1722 toobig: 1723 *ntok = 0; 1724 fprintf(stderr, 1725 "***Line `%s' is too big\n", 1726 line); 1727 return; 1728 } 1729 1730 1731 /* 1732 * getarg - interpret an argument token 1733 */ 1734 static int 1735 getarg( 1736 const char *str, 1737 int code, 1738 arg_v *argp 1739 ) 1740 { 1741 u_long ul; 1742 1743 switch (code & ~OPT) { 1744 case NTP_STR: 1745 argp->string = str; 1746 break; 1747 1748 case NTP_ADD: 1749 if (!getnetnum(str, &argp->netnum, NULL, 0)) 1750 return 0; 1751 break; 1752 1753 case NTP_UINT: 1754 if ('&' == str[0]) { 1755 if (!atouint(&str[1], &ul)) { 1756 fprintf(stderr, 1757 "***Association index `%s' invalid/undecodable\n", 1758 str); 1759 return 0; 1760 } 1761 if (0 == numassoc) { 1762 dogetassoc(stdout); 1763 if (0 == numassoc) { 1764 fprintf(stderr, 1765 "***No associations found, `%s' unknown\n", 1766 str); 1767 return 0; 1768 } 1769 } 1770 ul = min(ul, numassoc); 1771 argp->uval = assoc_cache[ul - 1].assid; 1772 break; 1773 } 1774 if (!atouint(str, &argp->uval)) { 1775 fprintf(stderr, "***Illegal unsigned value %s\n", 1776 str); 1777 return 0; 1778 } 1779 break; 1780 1781 case NTP_INT: 1782 if (!atoint(str, &argp->ival)) { 1783 fprintf(stderr, "***Illegal integer value %s\n", 1784 str); 1785 return 0; 1786 } 1787 break; 1788 1789 case IP_VERSION: 1790 if (!strcmp("-6", str)) { 1791 argp->ival = 6; 1792 } else if (!strcmp("-4", str)) { 1793 argp->ival = 4; 1794 } else { 1795 fprintf(stderr, "***Version must be either 4 or 6\n"); 1796 return 0; 1797 } 1798 break; 1799 } 1800 1801 return 1; 1802 } 1803 #endif /* !BUILD_AS_LIB */ 1804 1805 1806 /* 1807 * findcmd - find a command in a command description table 1808 */ 1809 static int 1810 findcmd( 1811 const char * str, 1812 struct xcmd * clist1, 1813 struct xcmd * clist2, 1814 struct xcmd ** cmd 1815 ) 1816 { 1817 struct xcmd *cl; 1818 size_t clen; 1819 int nmatch; 1820 struct xcmd *nearmatch = NULL; 1821 struct xcmd *clist; 1822 1823 clen = strlen(str); 1824 nmatch = 0; 1825 if (clist1 != 0) 1826 clist = clist1; 1827 else if (clist2 != 0) 1828 clist = clist2; 1829 else 1830 return 0; 1831 1832 again: 1833 for (cl = clist; cl->keyword != 0; cl++) { 1834 /* do a first character check, for efficiency */ 1835 if (*str != *(cl->keyword)) 1836 continue; 1837 if (strncmp(str, cl->keyword, (unsigned)clen) == 0) { 1838 /* 1839 * Could be extact match, could be approximate. 1840 * Is exact if the length of the keyword is the 1841 * same as the str. 1842 */ 1843 if (*((cl->keyword) + clen) == '\0') { 1844 *cmd = cl; 1845 return 1; 1846 } 1847 nmatch++; 1848 nearmatch = cl; 1849 } 1850 } 1851 1852 /* 1853 * See if there is more to do. If so, go again. Sorry about the 1854 * goto, too much looking at BSD sources... 1855 */ 1856 if (clist == clist1 && clist2 != 0) { 1857 clist = clist2; 1858 goto again; 1859 } 1860 1861 /* 1862 * If we got extactly 1 near match, use it, else return number 1863 * of matches. 1864 */ 1865 if (nmatch == 1) { 1866 *cmd = nearmatch; 1867 return 1; 1868 } 1869 return nmatch; 1870 } 1871 1872 1873 /* 1874 * getnetnum - given a host name, return its net number 1875 * and (optional) full name 1876 */ 1877 int 1878 getnetnum( 1879 const char *hname, 1880 sockaddr_u *num, 1881 char *fullhost, 1882 int af 1883 ) 1884 { 1885 struct addrinfo hints, *ai = NULL; 1886 1887 ZERO(hints); 1888 hints.ai_flags = AI_CANONNAME; 1889 #ifdef AI_ADDRCONFIG 1890 hints.ai_flags |= AI_ADDRCONFIG; 1891 #endif 1892 1893 /* 1894 * decodenetnum only works with addresses, but handles syntax 1895 * that getaddrinfo doesn't: [2001::1]:1234 1896 */ 1897 if (decodenetnum(hname, num)) { 1898 if (fullhost != NULL) 1899 getnameinfo(&num->sa, SOCKLEN(num), fullhost, 1900 LENHOSTNAME, NULL, 0, 0); 1901 return 1; 1902 } else if (getaddrinfo(hname, "ntp", &hints, &ai) == 0) { 1903 INSIST(sizeof(*num) >= ai->ai_addrlen); 1904 memcpy(num, ai->ai_addr, ai->ai_addrlen); 1905 if (fullhost != NULL) { 1906 if (ai->ai_canonname != NULL) 1907 strlcpy(fullhost, ai->ai_canonname, 1908 LENHOSTNAME); 1909 else 1910 getnameinfo(&num->sa, SOCKLEN(num), 1911 fullhost, LENHOSTNAME, NULL, 1912 0, 0); 1913 } 1914 freeaddrinfo(ai); 1915 return 1; 1916 } 1917 fprintf(stderr, "***Can't find host %s\n", hname); 1918 1919 return 0; 1920 } 1921 1922 1923 /* 1924 * nntohost - convert network number to host name. This routine enforces 1925 * the showhostnames setting. 1926 */ 1927 const char * 1928 nntohost( 1929 sockaddr_u *netnum 1930 ) 1931 { 1932 return nntohost_col(netnum, LIB_BUFLENGTH - 1, FALSE); 1933 } 1934 1935 1936 /* 1937 * nntohost_col - convert network number to host name in fixed width. 1938 * This routine enforces the showhostnames setting. 1939 * When displaying hostnames longer than the width, 1940 * the first part of the hostname is displayed. When 1941 * displaying numeric addresses longer than the width, 1942 * Such as IPv6 addresses, the caller decides whether 1943 * the first or last of the numeric address is used. 1944 */ 1945 const char * 1946 nntohost_col( 1947 sockaddr_u * addr, 1948 size_t width, 1949 int preserve_lowaddrbits 1950 ) 1951 { 1952 const char * out; 1953 1954 if (!showhostnames || SOCK_UNSPEC(addr)) { 1955 if (preserve_lowaddrbits) 1956 out = trunc_left(stoa(addr), width); 1957 else 1958 out = trunc_right(stoa(addr), width); 1959 } else if (ISREFCLOCKADR(addr)) { 1960 out = refnumtoa(addr); 1961 } else { 1962 out = trunc_right(socktohost(addr), width); 1963 } 1964 return out; 1965 } 1966 1967 1968 /* 1969 * nntohostp() is the same as nntohost() plus a :port suffix 1970 */ 1971 const char * 1972 nntohostp( 1973 sockaddr_u *netnum 1974 ) 1975 { 1976 const char * hostn; 1977 char * buf; 1978 1979 if (!showhostnames || SOCK_UNSPEC(netnum)) 1980 return sptoa(netnum); 1981 else if (ISREFCLOCKADR(netnum)) 1982 return refnumtoa(netnum); 1983 1984 hostn = socktohost(netnum); 1985 LIB_GETBUF(buf); 1986 snprintf(buf, LIB_BUFLENGTH, "%s:%u", hostn, SRCPORT(netnum)); 1987 1988 return buf; 1989 } 1990 1991 /* 1992 * rtdatetolfp - decode an RT-11 date into an l_fp 1993 */ 1994 static int 1995 rtdatetolfp( 1996 char *str, 1997 l_fp *lfp 1998 ) 1999 { 2000 register char *cp; 2001 register int i; 2002 struct calendar cal; 2003 char buf[4]; 2004 2005 cal.yearday = 0; 2006 2007 /* 2008 * An RT-11 date looks like: 2009 * 2010 * d[d]-Mth-y[y] hh:mm:ss 2011 * 2012 * (No docs, but assume 4-digit years are also legal...) 2013 * 2014 * d[d]-Mth-y[y[y[y]]] hh:mm:ss 2015 */ 2016 cp = str; 2017 if (!isdigit((int)*cp)) { 2018 if (*cp == '-') { 2019 /* 2020 * Catch special case 2021 */ 2022 L_CLR(lfp); 2023 return 1; 2024 } 2025 return 0; 2026 } 2027 2028 cal.monthday = (u_char) (*cp++ - '0'); /* ascii dependent */ 2029 if (isdigit((int)*cp)) { 2030 cal.monthday = (u_char)((cal.monthday << 3) + (cal.monthday << 1)); 2031 cal.monthday = (u_char)(cal.monthday + *cp++ - '0'); 2032 } 2033 2034 if (*cp++ != '-') 2035 return 0; 2036 2037 for (i = 0; i < 3; i++) 2038 buf[i] = *cp++; 2039 buf[3] = '\0'; 2040 2041 for (i = 0; i < 12; i++) 2042 if (STREQ(buf, months[i])) 2043 break; 2044 if (i == 12) 2045 return 0; 2046 cal.month = (u_char)(i + 1); 2047 2048 if (*cp++ != '-') 2049 return 0; 2050 2051 if (!isdigit((int)*cp)) 2052 return 0; 2053 cal.year = (u_short)(*cp++ - '0'); 2054 if (isdigit((int)*cp)) { 2055 cal.year = (u_short)((cal.year << 3) + (cal.year << 1)); 2056 cal.year = (u_short)(*cp++ - '0'); 2057 } 2058 if (isdigit((int)*cp)) { 2059 cal.year = (u_short)((cal.year << 3) + (cal.year << 1)); 2060 cal.year = (u_short)(cal.year + *cp++ - '0'); 2061 } 2062 if (isdigit((int)*cp)) { 2063 cal.year = (u_short)((cal.year << 3) + (cal.year << 1)); 2064 cal.year = (u_short)(cal.year + *cp++ - '0'); 2065 } 2066 2067 /* 2068 * Catch special case. If cal.year == 0 this is a zero timestamp. 2069 */ 2070 if (cal.year == 0) { 2071 L_CLR(lfp); 2072 return 1; 2073 } 2074 2075 if (*cp++ != ' ' || !isdigit((int)*cp)) 2076 return 0; 2077 cal.hour = (u_char)(*cp++ - '0'); 2078 if (isdigit((int)*cp)) { 2079 cal.hour = (u_char)((cal.hour << 3) + (cal.hour << 1)); 2080 cal.hour = (u_char)(cal.hour + *cp++ - '0'); 2081 } 2082 2083 if (*cp++ != ':' || !isdigit((int)*cp)) 2084 return 0; 2085 cal.minute = (u_char)(*cp++ - '0'); 2086 if (isdigit((int)*cp)) { 2087 cal.minute = (u_char)((cal.minute << 3) + (cal.minute << 1)); 2088 cal.minute = (u_char)(cal.minute + *cp++ - '0'); 2089 } 2090 2091 if (*cp++ != ':' || !isdigit((int)*cp)) 2092 return 0; 2093 cal.second = (u_char)(*cp++ - '0'); 2094 if (isdigit((int)*cp)) { 2095 cal.second = (u_char)((cal.second << 3) + (cal.second << 1)); 2096 cal.second = (u_char)(cal.second + *cp++ - '0'); 2097 } 2098 2099 /* 2100 * For RT-11, 1972 seems to be the pivot year 2101 */ 2102 if (cal.year < 72) 2103 cal.year += 2000; 2104 if (cal.year < 100) 2105 cal.year += 1900; 2106 2107 lfp->l_ui = caltontp(&cal); 2108 lfp->l_uf = 0; 2109 return 1; 2110 } 2111 2112 2113 /* 2114 * decodets - decode a timestamp into an l_fp format number, with 2115 * consideration of fuzzball formats. 2116 */ 2117 int 2118 decodets( 2119 char *str, 2120 l_fp *lfp 2121 ) 2122 { 2123 char *cp; 2124 char buf[30]; 2125 size_t b; 2126 2127 /* 2128 * If it starts with a 0x, decode as hex. 2129 */ 2130 if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X')) 2131 return hextolfp(str+2, lfp); 2132 2133 /* 2134 * If it starts with a '"', try it as an RT-11 date. 2135 */ 2136 if (*str == '"') { 2137 cp = str + 1; 2138 b = 0; 2139 while ('"' != *cp && '\0' != *cp && 2140 b < COUNTOF(buf) - 1) 2141 buf[b++] = *cp++; 2142 buf[b] = '\0'; 2143 return rtdatetolfp(buf, lfp); 2144 } 2145 2146 /* 2147 * Might still be hex. Check out the first character. Talk 2148 * about heuristics! 2149 */ 2150 if ((*str >= 'A' && *str <= 'F') || (*str >= 'a' && *str <= 'f')) 2151 return hextolfp(str, lfp); 2152 2153 /* 2154 * Try it as a decimal. If this fails, try as an unquoted 2155 * RT-11 date. This code should go away eventually. 2156 */ 2157 if (atolfp(str, lfp)) 2158 return 1; 2159 2160 return rtdatetolfp(str, lfp); 2161 } 2162 2163 2164 /* 2165 * decodetime - decode a time value. It should be in milliseconds 2166 */ 2167 int 2168 decodetime( 2169 char *str, 2170 l_fp *lfp 2171 ) 2172 { 2173 return mstolfp(str, lfp); 2174 } 2175 2176 2177 /* 2178 * decodeint - decode an integer 2179 */ 2180 int 2181 decodeint( 2182 char *str, 2183 long *val 2184 ) 2185 { 2186 if (*str == '0') { 2187 if (*(str+1) == 'x' || *(str+1) == 'X') 2188 return hextoint(str+2, (u_long *)val); 2189 return octtoint(str, (u_long *)val); 2190 } 2191 return atoint(str, val); 2192 } 2193 2194 2195 /* 2196 * decodeuint - decode an unsigned integer 2197 */ 2198 int 2199 decodeuint( 2200 char *str, 2201 u_long *val 2202 ) 2203 { 2204 if (*str == '0') { 2205 if (*(str + 1) == 'x' || *(str + 1) == 'X') 2206 return (hextoint(str + 2, val)); 2207 return (octtoint(str, val)); 2208 } 2209 return (atouint(str, val)); 2210 } 2211 2212 2213 /* 2214 * decodearr - decode an array of time values 2215 */ 2216 static int 2217 decodearr( 2218 char *str, 2219 int *narr, 2220 l_fp *lfparr 2221 ) 2222 { 2223 register char *cp, *bp; 2224 register l_fp *lfp; 2225 char buf[60]; 2226 2227 lfp = lfparr; 2228 cp = str; 2229 *narr = 0; 2230 2231 while (*narr < 8) { 2232 while (isspace((int)*cp)) 2233 cp++; 2234 if (*cp == '\0') 2235 break; 2236 2237 bp = buf; 2238 while (!isspace((int)*cp) && *cp != '\0') 2239 *bp++ = *cp++; 2240 *bp++ = '\0'; 2241 2242 if (!decodetime(buf, lfp)) 2243 return 0; 2244 (*narr)++; 2245 lfp++; 2246 } 2247 return 1; 2248 } 2249 2250 2251 /* 2252 * Finally, the built in command handlers 2253 */ 2254 2255 /* 2256 * help - tell about commands, or details of a particular command 2257 */ 2258 static void 2259 help( 2260 struct parse *pcmd, 2261 FILE *fp 2262 ) 2263 { 2264 struct xcmd *xcp = NULL; /* quiet warning */ 2265 const char *cmd; 2266 const char *list[100]; 2267 size_t word, words; 2268 size_t row, rows; 2269 size_t col, cols; 2270 size_t length; 2271 2272 if (pcmd->nargs == 0) { 2273 words = 0; 2274 for (xcp = builtins; xcp->keyword != NULL; xcp++) { 2275 if (*(xcp->keyword) != '?' && 2276 words < COUNTOF(list)) 2277 list[words++] = xcp->keyword; 2278 } 2279 for (xcp = opcmds; xcp->keyword != NULL; xcp++) 2280 if (words < COUNTOF(list)) 2281 list[words++] = xcp->keyword; 2282 2283 qsort((void *)list, words, sizeof(list[0]), helpsort); 2284 col = 0; 2285 for (word = 0; word < words; word++) { 2286 length = strlen(list[word]); 2287 col = max(col, length); 2288 } 2289 2290 cols = SCREENWIDTH / ++col; 2291 rows = (words + cols - 1) / cols; 2292 2293 fprintf(fp, "ntpq commands:\n"); 2294 2295 for (row = 0; row < rows; row++) { 2296 for (word = row; word < words; word += rows) 2297 fprintf(fp, "%-*.*s", (int)col, 2298 (int)col - 1, list[word]); 2299 fprintf(fp, "\n"); 2300 } 2301 } else { 2302 cmd = pcmd->argval[0].string; 2303 words = findcmd(cmd, builtins, opcmds, &xcp); 2304 if (words == 0) { 2305 fprintf(stderr, 2306 "Command `%s' is unknown\n", cmd); 2307 return; 2308 } else if (words >= 2) { 2309 fprintf(stderr, 2310 "Command `%s' is ambiguous\n", cmd); 2311 return; 2312 } 2313 fprintf(fp, "function: %s\n", xcp->comment); 2314 printusage(xcp, fp); 2315 } 2316 } 2317 2318 2319 /* 2320 * helpsort - do hostname qsort comparisons 2321 */ 2322 static int 2323 helpsort( 2324 const void *t1, 2325 const void *t2 2326 ) 2327 { 2328 const char * const * name1 = t1; 2329 const char * const * name2 = t2; 2330 2331 return strcmp(*name1, *name2); 2332 } 2333 2334 2335 /* 2336 * printusage - print usage information for a command 2337 */ 2338 static void 2339 printusage( 2340 struct xcmd *xcp, 2341 FILE *fp 2342 ) 2343 { 2344 register int i; 2345 2346 /* XXX: Do we need to warn about extra args here too? */ 2347 2348 (void) fprintf(fp, "usage: %s", xcp->keyword); 2349 for (i = 0; i < MAXARGS && xcp->arg[i] != NO; i++) { 2350 if (xcp->arg[i] & OPT) 2351 (void) fprintf(fp, " [ %s ]", xcp->desc[i]); 2352 else 2353 (void) fprintf(fp, " %s", xcp->desc[i]); 2354 } 2355 (void) fprintf(fp, "\n"); 2356 } 2357 2358 2359 /* 2360 * timeout - set time out time 2361 */ 2362 static void 2363 timeout( 2364 struct parse *pcmd, 2365 FILE *fp 2366 ) 2367 { 2368 int val; 2369 2370 if (pcmd->nargs == 0) { 2371 val = (int)tvout.tv_sec * 1000 + tvout.tv_usec / 1000; 2372 (void) fprintf(fp, "primary timeout %d ms\n", val); 2373 } else { 2374 tvout.tv_sec = pcmd->argval[0].uval / 1000; 2375 tvout.tv_usec = (pcmd->argval[0].uval - ((long)tvout.tv_sec * 1000)) 2376 * 1000; 2377 } 2378 } 2379 2380 2381 /* 2382 * auth_delay - set delay for auth requests 2383 */ 2384 static void 2385 auth_delay( 2386 struct parse *pcmd, 2387 FILE *fp 2388 ) 2389 { 2390 int isneg; 2391 u_long val; 2392 2393 if (pcmd->nargs == 0) { 2394 val = delay_time.l_ui * 1000 + delay_time.l_uf / 4294967; 2395 (void) fprintf(fp, "delay %lu ms\n", val); 2396 } else { 2397 if (pcmd->argval[0].ival < 0) { 2398 isneg = 1; 2399 val = (u_long)(-pcmd->argval[0].ival); 2400 } else { 2401 isneg = 0; 2402 val = (u_long)pcmd->argval[0].ival; 2403 } 2404 2405 delay_time.l_ui = val / 1000; 2406 val %= 1000; 2407 delay_time.l_uf = val * 4294967; /* 2**32/1000 */ 2408 2409 if (isneg) 2410 L_NEG(&delay_time); 2411 } 2412 } 2413 2414 2415 /* 2416 * host - set the host we are dealing with. 2417 */ 2418 static void 2419 host( 2420 struct parse *pcmd, 2421 FILE *fp 2422 ) 2423 { 2424 int i; 2425 2426 if (pcmd->nargs == 0) { 2427 if (havehost) 2428 (void) fprintf(fp, "current host is %s\n", 2429 currenthost); 2430 else 2431 (void) fprintf(fp, "no current host\n"); 2432 return; 2433 } 2434 2435 i = 0; 2436 ai_fam_templ = ai_fam_default; 2437 if (pcmd->nargs == 2) { 2438 if (!strcmp("-4", pcmd->argval[i].string)) 2439 ai_fam_templ = AF_INET; 2440 else if (!strcmp("-6", pcmd->argval[i].string)) 2441 ai_fam_templ = AF_INET6; 2442 else 2443 goto no_change; 2444 i = 1; 2445 } 2446 if (openhost(pcmd->argval[i].string, ai_fam_templ)) { 2447 fprintf(fp, "current host set to %s\n", currenthost); 2448 } else { 2449 no_change: 2450 if (havehost) 2451 fprintf(fp, "current host remains %s\n", 2452 currenthost); 2453 else 2454 fprintf(fp, "still no current host\n"); 2455 } 2456 } 2457 2458 2459 /* 2460 * poll - do one (or more) polls of the host via NTP 2461 */ 2462 /*ARGSUSED*/ 2463 static void 2464 ntp_poll( 2465 struct parse *pcmd, 2466 FILE *fp 2467 ) 2468 { 2469 (void) fprintf(fp, "poll not implemented yet\n"); 2470 } 2471 2472 2473 /* 2474 * showdrefid2str - return a string explanation of the value of drefid 2475 */ 2476 static char * 2477 showdrefid2str(void) 2478 { 2479 switch (drefid) { 2480 case REFID_HASH: 2481 return "hash"; 2482 case REFID_IPV4: 2483 return "ipv4"; 2484 default: 2485 return "Unknown"; 2486 } 2487 } 2488 2489 2490 /* 2491 * drefid - display/change "display hash" 2492 */ 2493 static void 2494 showdrefid( 2495 struct parse *pcmd, 2496 FILE *fp 2497 ) 2498 { 2499 if (pcmd->nargs == 0) { 2500 (void) fprintf(fp, "drefid value is %s\n", showdrefid2str()); 2501 return; 2502 } else if (STREQ(pcmd->argval[0].string, "hash")) { 2503 drefid = REFID_HASH; 2504 } else if (STREQ(pcmd->argval[0].string, "ipv4")) { 2505 drefid = REFID_IPV4; 2506 } else { 2507 (void) fprintf(fp, "What?\n"); 2508 return; 2509 } 2510 (void) fprintf(fp, "drefid value set to %s\n", showdrefid2str()); 2511 } 2512 2513 2514 /* 2515 * keyid - get a keyid to use for authenticating requests 2516 */ 2517 static void 2518 keyid( 2519 struct parse *pcmd, 2520 FILE *fp 2521 ) 2522 { 2523 if (pcmd->nargs == 0) { 2524 if (info_auth_keyid == 0) 2525 (void) fprintf(fp, "no keyid defined\n"); 2526 else 2527 (void) fprintf(fp, "keyid is %lu\n", (u_long)info_auth_keyid); 2528 } else { 2529 /* allow zero so that keyid can be cleared. */ 2530 if(pcmd->argval[0].uval > NTP_MAXKEY) 2531 (void) fprintf(fp, "Invalid key identifier\n"); 2532 info_auth_keyid = pcmd->argval[0].uval; 2533 } 2534 } 2535 2536 /* 2537 * keytype - get type of key to use for authenticating requests 2538 */ 2539 static void 2540 keytype( 2541 struct parse *pcmd, 2542 FILE *fp 2543 ) 2544 { 2545 const char * digest_name; 2546 size_t digest_len; 2547 int key_type; 2548 2549 if (!pcmd->nargs) { 2550 fprintf(fp, "keytype is %s with %lu octet digests\n", 2551 keytype_name(info_auth_keytype), 2552 (u_long)info_auth_hashlen); 2553 return; 2554 } 2555 2556 digest_name = pcmd->argval[0].string; 2557 digest_len = 0; 2558 key_type = keytype_from_text(digest_name, &digest_len); 2559 2560 if (!key_type) { 2561 fprintf(fp, "keytype is not valid. " 2562 #ifdef OPENSSL 2563 "Type \"help keytype\" for the available digest types.\n"); 2564 #else 2565 "Only \"md5\" is available.\n"); 2566 #endif 2567 return; 2568 } 2569 2570 info_auth_keytype = key_type; 2571 info_auth_hashlen = digest_len; 2572 } 2573 2574 2575 /* 2576 * passwd - get an authentication key 2577 */ 2578 /*ARGSUSED*/ 2579 static void 2580 passwd( 2581 struct parse *pcmd, 2582 FILE *fp 2583 ) 2584 { 2585 const char *pass; 2586 2587 if (info_auth_keyid == 0) { 2588 info_auth_keyid = getkeyid("Keyid: "); 2589 if (info_auth_keyid == 0) { 2590 (void)fprintf(fp, "Keyid must be defined\n"); 2591 return; 2592 } 2593 } 2594 if (pcmd->nargs >= 1) 2595 pass = pcmd->argval[0].string; 2596 else { 2597 pass = getpass_keytype(info_auth_keytype); 2598 if ('\0' == pass[0]) { 2599 fprintf(fp, "Password unchanged\n"); 2600 return; 2601 } 2602 } 2603 authusekey(info_auth_keyid, info_auth_keytype, 2604 (const u_char *)pass); 2605 authtrust(info_auth_keyid, 1); 2606 } 2607 2608 2609 /* 2610 * hostnames - set the showhostnames flag 2611 */ 2612 static void 2613 hostnames( 2614 struct parse *pcmd, 2615 FILE *fp 2616 ) 2617 { 2618 if (pcmd->nargs == 0) { 2619 if (showhostnames) 2620 (void) fprintf(fp, "hostnames being shown\n"); 2621 else 2622 (void) fprintf(fp, "hostnames not being shown\n"); 2623 } else { 2624 if (STREQ(pcmd->argval[0].string, "yes")) 2625 showhostnames = 1; 2626 else if (STREQ(pcmd->argval[0].string, "no")) 2627 showhostnames = 0; 2628 else 2629 (void)fprintf(stderr, "What?\n"); 2630 } 2631 } 2632 2633 2634 2635 /* 2636 * setdebug - set/change debugging level 2637 */ 2638 static void 2639 setdebug( 2640 struct parse *pcmd, 2641 FILE *fp 2642 ) 2643 { 2644 if (pcmd->nargs == 0) { 2645 (void) fprintf(fp, "debug level is %d\n", debug); 2646 return; 2647 } else if (STREQ(pcmd->argval[0].string, "no")) { 2648 debug = 0; 2649 } else if (STREQ(pcmd->argval[0].string, "more")) { 2650 debug++; 2651 } else if (STREQ(pcmd->argval[0].string, "less")) { 2652 debug--; 2653 } else { 2654 (void) fprintf(fp, "What?\n"); 2655 return; 2656 } 2657 (void) fprintf(fp, "debug level set to %d\n", debug); 2658 } 2659 2660 2661 /* 2662 * quit - stop this nonsense 2663 */ 2664 /*ARGSUSED*/ 2665 static void 2666 quit( 2667 struct parse *pcmd, 2668 FILE *fp 2669 ) 2670 { 2671 if (havehost) 2672 closesocket(sockfd); /* cleanliness next to godliness */ 2673 exit(0); 2674 } 2675 2676 2677 /* 2678 * version - print the current version number 2679 */ 2680 /*ARGSUSED*/ 2681 static void 2682 version( 2683 struct parse *pcmd, 2684 FILE *fp 2685 ) 2686 { 2687 2688 (void) fprintf(fp, "%s\n", Version); 2689 return; 2690 } 2691 2692 2693 /* 2694 * raw - set raw mode output 2695 */ 2696 /*ARGSUSED*/ 2697 static void 2698 raw( 2699 struct parse *pcmd, 2700 FILE *fp 2701 ) 2702 { 2703 rawmode = 1; 2704 (void) fprintf(fp, "Output set to raw\n"); 2705 } 2706 2707 2708 /* 2709 * cooked - set cooked mode output 2710 */ 2711 /*ARGSUSED*/ 2712 static void 2713 cooked( 2714 struct parse *pcmd, 2715 FILE *fp 2716 ) 2717 { 2718 rawmode = 0; 2719 (void) fprintf(fp, "Output set to cooked\n"); 2720 return; 2721 } 2722 2723 2724 /* 2725 * authenticate - always authenticate requests to this host 2726 */ 2727 static void 2728 authenticate( 2729 struct parse *pcmd, 2730 FILE *fp 2731 ) 2732 { 2733 if (pcmd->nargs == 0) { 2734 if (always_auth) { 2735 (void) fprintf(fp, 2736 "authenticated requests being sent\n"); 2737 } else 2738 (void) fprintf(fp, 2739 "unauthenticated requests being sent\n"); 2740 } else { 2741 if (STREQ(pcmd->argval[0].string, "yes")) { 2742 always_auth = 1; 2743 } else if (STREQ(pcmd->argval[0].string, "no")) { 2744 always_auth = 0; 2745 } else 2746 (void)fprintf(stderr, "What?\n"); 2747 } 2748 } 2749 2750 2751 /* 2752 * ntpversion - choose the NTP version to use 2753 */ 2754 static void 2755 ntpversion( 2756 struct parse *pcmd, 2757 FILE *fp 2758 ) 2759 { 2760 if (pcmd->nargs == 0) { 2761 (void) fprintf(fp, 2762 "NTP version being claimed is %d\n", pktversion); 2763 } else { 2764 if (pcmd->argval[0].uval < NTP_OLDVERSION 2765 || pcmd->argval[0].uval > NTP_VERSION) { 2766 (void) fprintf(stderr, "versions %d to %d, please\n", 2767 NTP_OLDVERSION, NTP_VERSION); 2768 } else { 2769 pktversion = (u_char) pcmd->argval[0].uval; 2770 } 2771 } 2772 } 2773 2774 2775 static void __attribute__((__format__(__printf__, 1, 0))) 2776 vwarning(const char *fmt, va_list ap) 2777 { 2778 int serrno = errno; 2779 (void) fprintf(stderr, "%s: ", progname); 2780 vfprintf(stderr, fmt, ap); 2781 (void) fprintf(stderr, ": %s\n", strerror(serrno)); 2782 } 2783 2784 /* 2785 * warning - print a warning message 2786 */ 2787 static void __attribute__((__format__(__printf__, 1, 2))) 2788 warning( 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 } 2798 2799 2800 /* 2801 * error - print a message and exit 2802 */ 2803 static void __attribute__((__format__(__printf__, 1, 2))) 2804 error( 2805 const char *fmt, 2806 ... 2807 ) 2808 { 2809 va_list ap; 2810 va_start(ap, fmt); 2811 vwarning(fmt, ap); 2812 va_end(ap); 2813 exit(1); 2814 } 2815 /* 2816 * getkeyid - prompt the user for a keyid to use 2817 */ 2818 static u_long 2819 getkeyid( 2820 const char *keyprompt 2821 ) 2822 { 2823 int c; 2824 FILE *fi; 2825 char pbuf[20]; 2826 size_t i; 2827 size_t ilim; 2828 2829 #ifndef SYS_WINNT 2830 if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL) 2831 #else 2832 if ((fi = _fdopen(open("CONIN$", _O_TEXT), "r")) == NULL) 2833 #endif /* SYS_WINNT */ 2834 fi = stdin; 2835 else 2836 setbuf(fi, (char *)NULL); 2837 fprintf(stderr, "%s", keyprompt); fflush(stderr); 2838 for (i = 0, ilim = COUNTOF(pbuf) - 1; 2839 i < ilim && (c = getc(fi)) != '\n' && c != EOF; 2840 ) 2841 pbuf[i++] = (char)c; 2842 pbuf[i] = '\0'; 2843 if (fi != stdin) 2844 fclose(fi); 2845 2846 return (u_long) atoi(pbuf); 2847 } 2848 2849 2850 /* 2851 * atoascii - printable-ize possibly ascii data using the character 2852 * transformations cat -v uses. 2853 */ 2854 static void 2855 atoascii( 2856 const char *in, 2857 size_t in_octets, 2858 char *out, 2859 size_t out_octets 2860 ) 2861 { 2862 const u_char * pchIn; 2863 const u_char * pchInLimit; 2864 u_char * pchOut; 2865 u_char c; 2866 2867 pchIn = (const u_char *)in; 2868 pchInLimit = pchIn + in_octets; 2869 pchOut = (u_char *)out; 2870 2871 if (NULL == pchIn) { 2872 if (0 < out_octets) 2873 *pchOut = '\0'; 2874 return; 2875 } 2876 2877 #define ONEOUT(c) \ 2878 do { \ 2879 if (0 == --out_octets) { \ 2880 *pchOut = '\0'; \ 2881 return; \ 2882 } \ 2883 *pchOut++ = (c); \ 2884 } while (0) 2885 2886 for ( ; pchIn < pchInLimit; pchIn++) { 2887 c = *pchIn; 2888 if ('\0' == c) 2889 break; 2890 if (c & 0x80) { 2891 ONEOUT('M'); 2892 ONEOUT('-'); 2893 c &= 0x7f; 2894 } 2895 if (c < ' ') { 2896 ONEOUT('^'); 2897 ONEOUT((u_char)(c + '@')); 2898 } else if (0x7f == c) { 2899 ONEOUT('^'); 2900 ONEOUT('?'); 2901 } else 2902 ONEOUT(c); 2903 } 2904 ONEOUT('\0'); 2905 2906 #undef ONEOUT 2907 } 2908 2909 2910 /* 2911 * makeascii - print possibly ascii data using the character 2912 * transformations that cat -v uses. 2913 */ 2914 void 2915 makeascii( 2916 size_t length, 2917 const char *data, 2918 FILE *fp 2919 ) 2920 { 2921 const u_char *data_u_char; 2922 const u_char *cp; 2923 int c; 2924 2925 data_u_char = (const u_char *)data; 2926 2927 for (cp = data_u_char; cp < data_u_char + length; cp++) { 2928 c = (int)*cp; 2929 if (c & 0x80) { 2930 putc('M', fp); 2931 putc('-', fp); 2932 c &= 0x7f; 2933 } 2934 2935 if (c < ' ') { 2936 putc('^', fp); 2937 putc(c + '@', fp); 2938 } else if (0x7f == c) { 2939 putc('^', fp); 2940 putc('?', fp); 2941 } else 2942 putc(c, fp); 2943 } 2944 } 2945 2946 2947 /* 2948 * asciize - same thing as makeascii except add a newline 2949 */ 2950 void 2951 asciize( 2952 int length, 2953 char *data, 2954 FILE *fp 2955 ) 2956 { 2957 makeascii(length, data, fp); 2958 putc('\n', fp); 2959 } 2960 2961 2962 /* 2963 * truncate string to fit clipping excess at end. 2964 * "too long" -> "too l" 2965 * Used for hostnames. 2966 */ 2967 const char * 2968 trunc_right( 2969 const char * src, 2970 size_t width 2971 ) 2972 { 2973 size_t sl; 2974 char * out; 2975 2976 2977 sl = strlen(src); 2978 if (sl > width && LIB_BUFLENGTH - 1 > width && width > 0) { 2979 LIB_GETBUF(out); 2980 memcpy(out, src, width); 2981 out[width] = '\0'; 2982 2983 return out; 2984 } 2985 2986 return src; 2987 } 2988 2989 2990 /* 2991 * truncate string to fit by preserving right side and using '_' to hint 2992 * "too long" -> "_long" 2993 * Used for local IPv6 addresses, where low bits differentiate. 2994 */ 2995 const char * 2996 trunc_left( 2997 const char * src, 2998 size_t width 2999 ) 3000 { 3001 size_t sl; 3002 char * out; 3003 3004 3005 sl = strlen(src); 3006 if (sl > width && LIB_BUFLENGTH - 1 > width && width > 1) { 3007 LIB_GETBUF(out); 3008 out[0] = '_'; 3009 memcpy(&out[1], &src[sl + 1 - width], width); 3010 3011 return out; 3012 } 3013 3014 return src; 3015 } 3016 3017 3018 /* 3019 * Some circular buffer space 3020 */ 3021 #define CBLEN 80 3022 #define NUMCB 6 3023 3024 char circ_buf[NUMCB][CBLEN]; 3025 int nextcb = 0; 3026 3027 /* 3028 * nextvar - find the next variable in the buffer 3029 */ 3030 int 3031 nextvar( 3032 size_t *datalen, 3033 const char **datap, 3034 char **vname, 3035 char **vvalue 3036 ) 3037 { 3038 const char *cp; 3039 const char *np; 3040 const char *cpend; 3041 size_t srclen; 3042 size_t len; 3043 static char name[MAXVARLEN]; 3044 static char value[MAXVALLEN]; 3045 3046 cp = *datap; 3047 cpend = cp + *datalen; 3048 3049 /* 3050 * Space past commas and white space 3051 */ 3052 while (cp < cpend && (*cp == ',' || isspace((int)*cp))) 3053 cp++; 3054 if (cp >= cpend) 3055 return 0; 3056 3057 /* 3058 * Copy name until we hit a ',', an '=', a '\r' or a '\n'. Backspace 3059 * over any white space and terminate it. 3060 */ 3061 srclen = strcspn(cp, ",=\r\n"); 3062 srclen = min(srclen, (size_t)(cpend - cp)); 3063 len = srclen; 3064 while (len > 0 && isspace((unsigned char)cp[len - 1])) 3065 len--; 3066 if (len >= sizeof(name)) 3067 return 0; 3068 if (len > 0) 3069 memcpy(name, cp, len); 3070 name[len] = '\0'; 3071 *vname = name; 3072 cp += srclen; 3073 3074 /* 3075 * Check if we hit the end of the buffer or a ','. If so we are done. 3076 */ 3077 if (cp >= cpend || *cp == ',' || *cp == '\r' || *cp == '\n') { 3078 if (cp < cpend) 3079 cp++; 3080 *datap = cp; 3081 *datalen = size2int_sat(cpend - cp); 3082 *vvalue = NULL; 3083 return 1; 3084 } 3085 3086 /* 3087 * So far, so good. Copy out the value 3088 */ 3089 cp++; /* past '=' */ 3090 while (cp < cpend && (isspace((unsigned char)*cp) && *cp != '\r' && *cp != '\n')) 3091 cp++; 3092 np = cp; 3093 if ('"' == *np) { 3094 do { 3095 np++; 3096 } while (np < cpend && '"' != *np); 3097 if (np < cpend && '"' == *np) 3098 np++; 3099 } else { 3100 while (np < cpend && ',' != *np && '\r' != *np) 3101 np++; 3102 } 3103 len = np - cp; 3104 if (np > cpend || len >= sizeof(value) || 3105 (np < cpend && ',' != *np && '\r' != *np)) 3106 return 0; 3107 memcpy(value, cp, len); 3108 /* 3109 * Trim off any trailing whitespace 3110 */ 3111 while (len > 0 && isspace((unsigned char)value[len - 1])) 3112 len--; 3113 value[len] = '\0'; 3114 3115 /* 3116 * Return this. All done. 3117 */ 3118 if (np < cpend && ',' == *np) 3119 np++; 3120 *datap = np; 3121 *datalen = size2int_sat(cpend - np); 3122 *vvalue = value; 3123 return 1; 3124 } 3125 3126 3127 u_short 3128 varfmt(const char * varname) 3129 { 3130 u_int n; 3131 3132 for (n = 0; n < COUNTOF(cookedvars); n++) 3133 if (!strcmp(varname, cookedvars[n].varname)) 3134 return cookedvars[n].fmt; 3135 3136 return PADDING; 3137 } 3138 3139 3140 /* 3141 * printvars - print variables returned in response packet 3142 */ 3143 void 3144 printvars( 3145 size_t length, 3146 const char *data, 3147 int status, 3148 int sttype, 3149 int quiet, 3150 FILE *fp 3151 ) 3152 { 3153 if (rawmode) 3154 rawprint(sttype, length, data, status, quiet, fp); 3155 else 3156 cookedprint(sttype, length, data, status, quiet, fp); 3157 } 3158 3159 3160 /* 3161 * rawprint - do a printout of the data in raw mode 3162 */ 3163 static void 3164 rawprint( 3165 int datatype, 3166 size_t length, 3167 const char *data, 3168 int status, 3169 int quiet, 3170 FILE *fp 3171 ) 3172 { 3173 const char *cp; 3174 const char *cpend; 3175 3176 /* 3177 * Essentially print the data as is. We reformat unprintables, though. 3178 */ 3179 cp = data; 3180 cpend = data + length; 3181 3182 if (!quiet) 3183 (void) fprintf(fp, "status=0x%04x,\n", status); 3184 3185 while (cp < cpend) { 3186 if (*cp == '\r') { 3187 /* 3188 * If this is a \r and the next character is a 3189 * \n, supress this, else pretty print it. Otherwise 3190 * just output the character. 3191 */ 3192 if (cp == (cpend - 1) || *(cp + 1) != '\n') 3193 makeascii(1, cp, fp); 3194 } else if (isspace((unsigned char)*cp) || isprint((unsigned char)*cp)) 3195 putc(*cp, fp); 3196 else 3197 makeascii(1, cp, fp); 3198 cp++; 3199 } 3200 } 3201 3202 3203 /* 3204 * Global data used by the cooked output routines 3205 */ 3206 int out_chars; /* number of characters output */ 3207 int out_linecount; /* number of characters output on this line */ 3208 3209 3210 /* 3211 * startoutput - get ready to do cooked output 3212 */ 3213 static void 3214 startoutput(void) 3215 { 3216 out_chars = 0; 3217 out_linecount = 0; 3218 } 3219 3220 3221 /* 3222 * output - output a variable=value combination 3223 */ 3224 static void 3225 output( 3226 FILE *fp, 3227 const char *name, 3228 const char *value 3229 ) 3230 { 3231 int len; 3232 3233 /* strlen of "name=value" */ 3234 len = size2int_sat(strlen(name) + 1 + strlen(value)); 3235 3236 if (out_chars != 0) { 3237 out_chars += 2; 3238 if ((out_linecount + len + 2) > MAXOUTLINE) { 3239 fputs(",\n", fp); 3240 out_linecount = 0; 3241 } else { 3242 fputs(", ", fp); 3243 out_linecount += 2; 3244 } 3245 } 3246 3247 fputs(name, fp); 3248 putc('=', fp); 3249 fputs(value, fp); 3250 out_chars += len; 3251 out_linecount += len; 3252 } 3253 3254 3255 /* 3256 * endoutput - terminate a block of cooked output 3257 */ 3258 static void 3259 endoutput( 3260 FILE *fp 3261 ) 3262 { 3263 if (out_chars != 0) 3264 putc('\n', fp); 3265 } 3266 3267 3268 /* 3269 * outputarr - output an array of values 3270 */ 3271 static void 3272 outputarr( 3273 FILE *fp, 3274 char *name, 3275 int narr, 3276 l_fp *lfp 3277 ) 3278 { 3279 char *bp; 3280 char *cp; 3281 size_t i; 3282 size_t len; 3283 char buf[256]; 3284 3285 bp = buf; 3286 /* 3287 * Hack to align delay and offset values 3288 */ 3289 for (i = (int)strlen(name); i < 11; i++) 3290 *bp++ = ' '; 3291 3292 for (i = narr; i > 0; i--) { 3293 if (i != narr) 3294 *bp++ = ' '; 3295 cp = lfptoms(lfp, 2); 3296 len = strlen(cp); 3297 if (len > 7) { 3298 cp[7] = '\0'; 3299 len = 7; 3300 } 3301 while (len < 7) { 3302 *bp++ = ' '; 3303 len++; 3304 } 3305 while (*cp != '\0') 3306 *bp++ = *cp++; 3307 lfp++; 3308 } 3309 *bp = '\0'; 3310 output(fp, name, buf); 3311 } 3312 3313 static char * 3314 tstflags( 3315 u_long val 3316 ) 3317 { 3318 register char *cp, *s; 3319 size_t cb; 3320 register int i; 3321 register const char *sep; 3322 3323 sep = ""; 3324 s = cp = circ_buf[nextcb]; 3325 if (++nextcb >= NUMCB) 3326 nextcb = 0; 3327 cb = sizeof(circ_buf[0]); 3328 3329 snprintf(cp, cb, "%02lx", val); 3330 cp += strlen(cp); 3331 cb -= strlen(cp); 3332 if (!val) { 3333 strlcat(cp, " ok", cb); 3334 cp += strlen(cp); 3335 cb -= strlen(cp); 3336 } else { 3337 if (cb) { 3338 *cp++ = ' '; 3339 cb--; 3340 } 3341 for (i = 0; i < (int)COUNTOF(tstflagnames); i++) { 3342 if (val & 0x1) { 3343 snprintf(cp, cb, "%s%s", sep, 3344 tstflagnames[i]); 3345 sep = ", "; 3346 cp += strlen(cp); 3347 cb -= strlen(cp); 3348 } 3349 val >>= 1; 3350 } 3351 } 3352 if (cb) 3353 *cp = '\0'; 3354 3355 return s; 3356 } 3357 3358 /* 3359 * cookedprint - output variables in cooked mode 3360 */ 3361 static void 3362 cookedprint( 3363 int datatype, 3364 size_t length, 3365 const char *data, 3366 int status, 3367 int quiet, 3368 FILE *fp 3369 ) 3370 { 3371 char *name; 3372 char *value; 3373 char output_raw; 3374 int fmt; 3375 l_fp lfp; 3376 sockaddr_u hval; 3377 u_long uval; 3378 int narr; 3379 size_t len; 3380 l_fp lfparr[8]; 3381 char b[12]; 3382 char bn[2 * MAXVARLEN]; 3383 char bv[2 * MAXVALLEN]; 3384 3385 UNUSED_ARG(datatype); 3386 3387 if (!quiet) 3388 fprintf(fp, "status=%04x %s,\n", status, 3389 statustoa(datatype, status)); 3390 3391 startoutput(); 3392 while (nextvar(&length, &data, &name, &value)) { 3393 fmt = varfmt(name); 3394 output_raw = 0; 3395 switch (fmt) { 3396 3397 case PADDING: 3398 output_raw = '*'; 3399 break; 3400 3401 case TS: 3402 if (!decodets(value, &lfp)) 3403 output_raw = '?'; 3404 else 3405 output(fp, name, prettydate(&lfp)); 3406 break; 3407 3408 case HA: /* fallthru */ 3409 case NA: 3410 if (!decodenetnum(value, &hval)) { 3411 output_raw = '?'; 3412 } else if (fmt == HA){ 3413 output(fp, name, nntohost(&hval)); 3414 } else { 3415 output(fp, name, stoa(&hval)); 3416 } 3417 break; 3418 3419 case RF: 3420 if (decodenetnum(value, &hval)) { 3421 if (ISREFCLOCKADR(&hval)) 3422 output(fp, name, 3423 refnumtoa(&hval)); 3424 else 3425 output(fp, name, stoa(&hval)); 3426 } else if (strlen(value) <= 4) { 3427 output(fp, name, value); 3428 } else { 3429 output_raw = '?'; 3430 } 3431 break; 3432 3433 case LP: 3434 if (!decodeuint(value, &uval) || uval > 3) { 3435 output_raw = '?'; 3436 } else { 3437 b[0] = (0x2 & uval) 3438 ? '1' 3439 : '0'; 3440 b[1] = (0x1 & uval) 3441 ? '1' 3442 : '0'; 3443 b[2] = '\0'; 3444 output(fp, name, b); 3445 } 3446 break; 3447 3448 case OC: 3449 if (!decodeuint(value, &uval)) { 3450 output_raw = '?'; 3451 } else { 3452 snprintf(b, sizeof(b), "%03lo", uval); 3453 output(fp, name, b); 3454 } 3455 break; 3456 3457 case AR: 3458 if (!decodearr(value, &narr, lfparr)) 3459 output_raw = '?'; 3460 else 3461 outputarr(fp, name, narr, lfparr); 3462 break; 3463 3464 case FX: 3465 if (!decodeuint(value, &uval)) 3466 output_raw = '?'; 3467 else 3468 output(fp, name, tstflags(uval)); 3469 break; 3470 3471 default: 3472 fprintf(stderr, "Internal error in cookedprint, %s=%s, fmt %d\n", 3473 name, value, fmt); 3474 output_raw = '?'; 3475 break; 3476 } 3477 3478 if (output_raw != 0) { 3479 /* TALOS-CAN-0063: avoid buffer overrun */ 3480 atoascii(name, MAXVARLEN, bn, sizeof(bn)); 3481 if (output_raw != '*') { 3482 atoascii(value, MAXVALLEN, 3483 bv, sizeof(bv) - 1); 3484 len = strlen(bv); 3485 bv[len] = output_raw; 3486 bv[len+1] = '\0'; 3487 } else { 3488 atoascii(value, MAXVALLEN, 3489 bv, sizeof(bv)); 3490 } 3491 output(fp, bn, bv); 3492 } 3493 } 3494 endoutput(fp); 3495 } 3496 3497 3498 /* 3499 * sortassoc - sort associations in the cache into ascending order 3500 */ 3501 void 3502 sortassoc(void) 3503 { 3504 if (numassoc > 1) 3505 qsort(assoc_cache, (size_t)numassoc, 3506 sizeof(assoc_cache[0]), &assoccmp); 3507 } 3508 3509 3510 /* 3511 * assoccmp - compare two associations 3512 */ 3513 static int 3514 assoccmp( 3515 const void *t1, 3516 const void *t2 3517 ) 3518 { 3519 const struct association *ass1 = t1; 3520 const struct association *ass2 = t2; 3521 3522 if (ass1->assid < ass2->assid) 3523 return -1; 3524 if (ass1->assid > ass2->assid) 3525 return 1; 3526 return 0; 3527 } 3528 3529 3530 /* 3531 * grow_assoc_cache() - enlarge dynamic assoc_cache array 3532 * 3533 * The strategy is to add an assumed 4k page size at a time, leaving 3534 * room for malloc() bookkeeping overhead equivalent to 4 pointers. 3535 */ 3536 void 3537 grow_assoc_cache(void) 3538 { 3539 static size_t prior_sz; 3540 size_t new_sz; 3541 3542 new_sz = prior_sz + 4 * 1024; 3543 if (0 == prior_sz) { 3544 new_sz -= 4 * sizeof(void *); 3545 } 3546 assoc_cache = erealloc_zero(assoc_cache, new_sz, prior_sz); 3547 prior_sz = new_sz; 3548 assoc_cache_slots = (u_int)(new_sz / sizeof(assoc_cache[0])); 3549 } 3550 3551 3552 /* 3553 * ntpq_custom_opt_handler - autoopts handler for -c and -p 3554 * 3555 * By default, autoopts loses the relative order of -c and -p options 3556 * on the command line. This routine replaces the default handler for 3557 * those routines and builds a list of commands to execute preserving 3558 * the order. 3559 */ 3560 void 3561 ntpq_custom_opt_handler( 3562 tOptions *pOptions, 3563 tOptDesc *pOptDesc 3564 ) 3565 { 3566 switch (pOptDesc->optValue) { 3567 3568 default: 3569 fprintf(stderr, 3570 "ntpq_custom_opt_handler unexpected option '%c' (%d)\n", 3571 pOptDesc->optValue, pOptDesc->optValue); 3572 exit(1); 3573 3574 case 'c': 3575 ADDCMD(pOptDesc->pzLastArg); 3576 break; 3577 3578 case 'p': 3579 ADDCMD("peers"); 3580 break; 3581 } 3582 } 3583 /* 3584 * Obtain list of digest names 3585 */ 3586 3587 #ifdef OPENSSL 3588 # ifdef HAVE_EVP_MD_DO_ALL_SORTED 3589 struct hstate { 3590 char *list; 3591 const char **seen; 3592 int idx; 3593 }; 3594 #define K_PER_LINE 8 3595 #define K_NL_PFX_STR "\n " 3596 #define K_DELIM_STR ", " 3597 static void list_md_fn(const EVP_MD *m, const char *from, const char *to, void *arg ) 3598 { 3599 size_t len, n; 3600 const char *name, *cp, **seen; 3601 struct hstate *hstate = arg; 3602 EVP_MD_CTX *ctx; 3603 u_int digest_len; 3604 u_char digest[EVP_MAX_MD_SIZE]; 3605 3606 if (!m) 3607 return; /* Ignore aliases */ 3608 3609 name = EVP_MD_name(m); 3610 3611 /* Lowercase names aren't accepted by keytype_from_text in ssl_init.c */ 3612 3613 for( cp = name; *cp; cp++ ) { 3614 if( islower((unsigned char)*cp) ) 3615 return; 3616 } 3617 len = (cp - name) + 1; 3618 3619 /* There are duplicates. Discard if name has been seen. */ 3620 3621 for (seen = hstate->seen; *seen; seen++) 3622 if (!strcmp(*seen, name)) 3623 return; 3624 n = (seen - hstate->seen) + 2; 3625 hstate->seen = erealloc(hstate->seen, n * sizeof(*seen)); 3626 hstate->seen[n-2] = name; 3627 hstate->seen[n-1] = NULL; 3628 3629 /* Discard MACs that NTP won't accept. 3630 * Keep this consistent with keytype_from_text() in ssl_init.c. 3631 */ 3632 3633 ctx = EVP_MD_CTX_new(); 3634 EVP_DigestInit(ctx, EVP_get_digestbyname(name)); 3635 EVP_DigestFinal(ctx, digest, &digest_len); 3636 EVP_MD_CTX_free(ctx); 3637 if (digest_len > (MAX_MAC_LEN - sizeof(keyid_t))) 3638 return; 3639 3640 if (hstate->list != NULL) 3641 len += strlen(hstate->list); 3642 len += (hstate->idx >= K_PER_LINE)? strlen(K_NL_PFX_STR): strlen(K_DELIM_STR); 3643 3644 if (hstate->list == NULL) { 3645 hstate->list = (char *)emalloc(len); 3646 hstate->list[0] = '\0'; 3647 } else 3648 hstate->list = (char *)erealloc(hstate->list, len); 3649 3650 sprintf(hstate->list + strlen(hstate->list), "%s%s", 3651 ((hstate->idx >= K_PER_LINE)? K_NL_PFX_STR : K_DELIM_STR), 3652 name); 3653 if (hstate->idx >= K_PER_LINE) 3654 hstate->idx = 1; 3655 else 3656 hstate->idx++; 3657 } 3658 # endif 3659 #endif 3660 3661 static char *list_digest_names(void) 3662 { 3663 char *list = NULL; 3664 3665 #ifdef OPENSSL 3666 # ifdef HAVE_EVP_MD_DO_ALL_SORTED 3667 struct hstate hstate = { NULL, NULL, K_PER_LINE+1 }; 3668 3669 hstate.seen = (const char **) emalloc_zero(1*sizeof( const char * )); // replaces -> calloc(1, sizeof( const char * )); 3670 3671 INIT_SSL(); 3672 EVP_MD_do_all_sorted(list_md_fn, &hstate); 3673 list = hstate.list; 3674 free(hstate.seen); 3675 # else 3676 list = (char *)emalloc(sizeof("md5, others (upgrade to OpenSSL-1.0 for full list)")); 3677 strcpy(list, "md5, others (upgrade to OpenSSL-1.0 for full list)"); 3678 # endif 3679 #else 3680 list = (char *)emalloc(sizeof("md5")); 3681 strcpy(list, "md5"); 3682 #endif 3683 3684 return list; 3685 } 3686 3687 #define CTRLC_STACK_MAX 4 3688 static volatile size_t ctrlc_stack_len = 0; 3689 static volatile Ctrl_C_Handler ctrlc_stack[CTRLC_STACK_MAX]; 3690 3691 3692 3693 int/*BOOL*/ 3694 push_ctrl_c_handler( 3695 Ctrl_C_Handler func 3696 ) 3697 { 3698 size_t size = ctrlc_stack_len; 3699 if (func && (size < CTRLC_STACK_MAX)) { 3700 ctrlc_stack[size] = func; 3701 ctrlc_stack_len = size + 1; 3702 return TRUE; 3703 } 3704 return FALSE; 3705 } 3706 3707 int/*BOOL*/ 3708 pop_ctrl_c_handler( 3709 Ctrl_C_Handler func 3710 ) 3711 { 3712 size_t size = ctrlc_stack_len; 3713 if (size) { 3714 --size; 3715 if (func == NULL || func == ctrlc_stack[size]) { 3716 ctrlc_stack_len = size; 3717 return TRUE; 3718 } 3719 } 3720 return FALSE; 3721 } 3722 3723 static void 3724 on_ctrlc(void) 3725 { 3726 size_t size = ctrlc_stack_len; 3727 while (size) 3728 if ((*ctrlc_stack[--size])()) 3729 break; 3730 } 3731 3732 static int 3733 my_easprintf( 3734 char ** ppinto, 3735 const char * fmt , 3736 ... 3737 ) 3738 { 3739 va_list va; 3740 int prc; 3741 size_t len = 128; 3742 char * buf = emalloc(len); 3743 3744 again: 3745 /* Note: we expect the memory allocation to fail long before the 3746 * increment in buffer size actually overflows. 3747 */ 3748 buf = (buf) ? erealloc(buf, len) : emalloc(len); 3749 3750 va_start(va, fmt); 3751 prc = vsnprintf(buf, len, fmt, va); 3752 va_end(va); 3753 3754 if (prc < 0) { 3755 /* might be very old vsnprintf. Or actually MSVC... */ 3756 len += len >> 1; 3757 goto again; 3758 } 3759 if ((size_t)prc >= len) { 3760 /* at least we have the proper size now... */ 3761 len = (size_t)prc + 1; 3762 goto again; 3763 } 3764 if ((size_t)prc < (len - 32)) 3765 buf = erealloc(buf, (size_t)prc + 1); 3766 *ppinto = buf; 3767 return prc; 3768 } 3769