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