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