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