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