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