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