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