1 /* 2 * ntpdc_ops.c - subroutines which are called to perform operations by 3 * ntpdc 4 */ 5 6 #ifdef HAVE_CONFIG_H 7 # include <config.h> 8 #endif 9 10 #include <stdio.h> 11 #include <stddef.h> 12 13 #include "ntpdc.h" 14 #include "ntp_net.h" 15 #include "ntp_control.h" 16 #include "ntp_refclock.h" 17 #include "ntp_stdlib.h" 18 19 #include <ctype.h> 20 #ifdef HAVE_SYS_TIMEX_H 21 # include <sys/timex.h> 22 #endif 23 #if !defined(__bsdi__) && !defined(apollo) 24 #ifdef HAVE_NETINET_IN_H 25 #include <netinet/in.h> 26 #endif 27 #endif 28 29 #include <arpa/inet.h> 30 31 /* 32 * utility functions 33 */ 34 static int checkitems (size_t, FILE *); 35 static int checkitemsize (size_t, size_t); 36 static int check1item (size_t, FILE *); 37 38 /* 39 * Declarations for command handlers in here 40 */ 41 static void peerlist (struct parse *, FILE *); 42 static void peers (struct parse *, FILE *); 43 static void doconfig (struct parse *pcmd, FILE *fp, int mode, int refc); 44 static void dmpeers (struct parse *, FILE *); 45 static void dopeers (struct parse *, FILE *, int); 46 static void printpeer (struct info_peer *, FILE *); 47 static void showpeer (struct parse *, FILE *); 48 static void peerstats (struct parse *, FILE *); 49 static void loopinfo (struct parse *, FILE *); 50 static void sysinfo (struct parse *, FILE *); 51 static void sysstats (struct parse *, FILE *); 52 static void iostats (struct parse *, FILE *); 53 static void memstats (struct parse *, FILE *); 54 static void timerstats (struct parse *, FILE *); 55 static void addpeer (struct parse *, FILE *); 56 static void addserver (struct parse *, FILE *); 57 static void addrefclock (struct parse *, FILE *); 58 static void broadcast (struct parse *, FILE *); 59 static void doconfig (struct parse *, FILE *, int, int); 60 static void unconfig (struct parse *, FILE *); 61 static void set (struct parse *, FILE *); 62 static void sys_clear (struct parse *, FILE *); 63 static void doset (struct parse *, FILE *, int); 64 static void reslist (struct parse *, FILE *); 65 static void new_restrict (struct parse *, FILE *); 66 static void unrestrict (struct parse *, FILE *); 67 static void delrestrict (struct parse *, FILE *); 68 static void do_restrict (struct parse *, FILE *, int); 69 static void monlist (struct parse *, FILE *); 70 static void reset (struct parse *, FILE *); 71 static void preset (struct parse *, FILE *); 72 static void readkeys (struct parse *, FILE *); 73 static void trustkey (struct parse *, FILE *); 74 static void untrustkey (struct parse *, FILE *); 75 static void do_trustkey (struct parse *, FILE *, int); 76 static void authinfo (struct parse *, FILE *); 77 static void traps (struct parse *, FILE *); 78 static void addtrap (struct parse *, FILE *); 79 static void clrtrap (struct parse *, FILE *); 80 static void do_addclr_trap (struct parse *, FILE *, int); 81 static void requestkey (struct parse *, FILE *); 82 static void controlkey (struct parse *, FILE *); 83 static void do_changekey (struct parse *, FILE *, int); 84 static void ctlstats (struct parse *, FILE *); 85 static void clockstat (struct parse *, FILE *); 86 static void fudge (struct parse *, FILE *); 87 static void clkbug (struct parse *, FILE *); 88 static void kerninfo (struct parse *, FILE *); 89 static void get_if_stats (struct parse *, FILE *); 90 static void do_if_reload (struct parse *, FILE *); 91 92 /* 93 * Commands we understand. Ntpdc imports this. 94 */ 95 struct xcmd opcmds[] = { 96 { "listpeers", peerlist, { OPT|IP_VERSION, NO, NO, NO }, 97 { "-4|-6", "", "", "" }, 98 "display list of peers the server knows about [IP Version]" }, 99 { "peers", peers, { OPT|IP_VERSION, NO, NO, NO }, 100 { "-4|-6", "", "", "" }, 101 "display peer summary information [IP Version]" }, 102 { "dmpeers", dmpeers, { OPT|IP_VERSION, NO, NO, NO }, 103 { "-4|-6", "", "", "" }, 104 "display peer summary info the way Dave Mills likes it (IP Version)" }, 105 { "showpeer", showpeer, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD}, 106 { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 107 "display detailed information for one or more peers" }, 108 { "pstats", peerstats, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 109 { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 110 "display statistical information for one or more peers" }, 111 { "loopinfo", loopinfo, { OPT|NTP_STR, NO, NO, NO }, 112 { "oneline|multiline", "", "", "" }, 113 "display loop filter information" }, 114 { "sysinfo", sysinfo, { NO, NO, NO, NO }, 115 { "", "", "", "" }, 116 "display local server information" }, 117 { "sysstats", sysstats, { NO, NO, NO, NO }, 118 { "", "", "", "" }, 119 "display local server statistics" }, 120 { "memstats", memstats, { NO, NO, NO, NO }, 121 { "", "", "", "" }, 122 "display peer memory usage statistics" }, 123 { "iostats", iostats, { NO, NO, NO, NO }, 124 { "", "", "", "" }, 125 "display I/O subsystem statistics" }, 126 { "timerstats", timerstats, { NO, NO, NO, NO }, 127 { "", "", "", "" }, 128 "display event timer subsystem statistics" }, 129 { "addpeer", addpeer, { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 130 { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." }, 131 "configure a new peer association" }, 132 { "addserver", addserver, { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 133 { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." }, 134 "configure a new server" }, 135 { "addrefclock",addrefclock, { NTP_ADD, OPT|NTP_UINT, OPT|NTP_STR, OPT|NTP_STR }, 136 { "addr", "mode", "minpoll|prefer", "minpoll|prefer" }, 137 "configure a new server" }, 138 { "broadcast", broadcast, { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 139 { "addr", "keyid", "version", "minpoll" }, 140 "configure broadcasting time service" }, 141 { "unconfig", unconfig, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 142 { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 143 "unconfigure existing peer assocations" }, 144 { "enable", set, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 145 { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." }, 146 "set a system flag (auth, bclient, monitor, pll, kernel, stats)" }, 147 { "disable", sys_clear, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 148 { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." }, 149 "clear a system flag (auth, bclient, monitor, pll, kernel, stats)" }, 150 { "reslist", reslist, {OPT|IP_VERSION, NO, NO, NO }, 151 { "-4|-6", "", "", "" }, 152 "display the server's restrict list" }, 153 { "restrict", new_restrict, { NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR }, 154 { "address", "mask", 155 "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod", 156 "..." }, 157 "create restrict entry/add flags to entry" }, 158 { "unrestrict", unrestrict, { NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR }, 159 { "address", "mask", 160 "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod", 161 "..." }, 162 "remove flags from a restrict entry" }, 163 { "delrestrict", delrestrict, { NTP_ADD, NTP_ADD, OPT|NTP_STR, NO }, 164 { "address", "mask", "ntpport", "" }, 165 "delete a restrict entry" }, 166 { "monlist", monlist, { OPT|NTP_INT, NO, NO, NO }, 167 { "version", "", "", "" }, 168 "display data the server's monitor routines have collected" }, 169 { "reset", reset, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 170 { "io|sys|mem|timer|auth|ctl|allpeers", "...", "...", "..." }, 171 "reset various subsystem statistics counters" }, 172 { "preset", preset, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 173 { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 174 "reset stat counters associated with particular peer(s)" }, 175 { "readkeys", readkeys, { NO, NO, NO, NO }, 176 { "", "", "", "" }, 177 "request a reread of the keys file and re-init of system keys" }, 178 { "trustedkey", trustkey, { NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT }, 179 { "keyid", "keyid", "keyid", "keyid" }, 180 "add one or more key ID's to the trusted list" }, 181 { "untrustedkey", untrustkey, { NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT }, 182 { "keyid", "keyid", "keyid", "keyid" }, 183 "remove one or more key ID's from the trusted list" }, 184 { "authinfo", authinfo, { NO, NO, NO, NO }, 185 { "", "", "", "" }, 186 "display the state of the authentication code" }, 187 { "traps", traps, { NO, NO, NO, NO }, 188 { "", "", "", "" }, 189 "display the traps set in the server" }, 190 { "addtrap", addtrap, { NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO }, 191 { "address", "port", "interface", "" }, 192 "configure a trap in the server" }, 193 { "clrtrap", clrtrap, { NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO }, 194 { "address", "port", "interface", "" }, 195 "remove a trap (configured or otherwise) from the server" }, 196 { "requestkey", requestkey, { NTP_UINT, NO, NO, NO }, 197 { "keyid", "", "", "" }, 198 "change the keyid the server uses to authenticate requests" }, 199 { "controlkey", controlkey, { NTP_UINT, NO, NO, NO }, 200 { "keyid", "", "", "" }, 201 "change the keyid the server uses to authenticate control messages" }, 202 { "ctlstats", ctlstats, { NO, NO, NO, NO }, 203 { "", "", "", "" }, 204 "display packet count statistics from the control module" }, 205 { "clockstat", clockstat, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 206 { "address", "address", "address", "address" }, 207 "display clock status information" }, 208 { "fudge", fudge, { NTP_ADD, NTP_STR, NTP_STR, NO }, 209 { "address", "time1|time2|val1|val2|flags", "value", "" }, 210 "set/change one of a clock's fudge factors" }, 211 { "clkbug", clkbug, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 212 { "address", "address", "address", "address" }, 213 "display clock debugging information" }, 214 { "kerninfo", kerninfo, { NO, NO, NO, NO }, 215 { "", "", "", "" }, 216 "display the kernel pll/pps variables" }, 217 { "ifstats", get_if_stats, { NO, NO, NO, NO }, 218 { "", "", "", "" }, 219 "list interface statistics" }, 220 { "ifreload", do_if_reload, { NO, NO, NO, NO }, 221 { "", "", "", "" }, 222 "reload interface configuration" }, 223 { 0, 0, { NO, NO, NO, NO }, 224 { "", "", "", "" }, "" } 225 }; 226 227 /* 228 * For quick string comparisons 229 */ 230 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) 231 232 /* 233 * SET_SS_LEN_IF_PRESENT - used by SET_ADDR, SET_ADDRS macros 234 */ 235 236 #ifdef ISC_PLATFORM_HAVESALEN 237 #define SET_SS_LEN_IF_PRESENT(psau) \ 238 do { \ 239 (psau)->sa.sa_len = SOCKLEN(psau); \ 240 } while (0) 241 #else 242 #define SET_SS_LEN_IF_PRESENT(psau) do { } while (0) 243 #endif 244 245 /* 246 * SET_ADDR - setup address for v4/v6 as needed 247 */ 248 #define SET_ADDR(address, v6flag, v4addr, v6addr) \ 249 do { \ 250 ZERO(address); \ 251 if (v6flag) { \ 252 AF(&(address)) = AF_INET6; \ 253 SOCK_ADDR6(&(address)) = (v6addr); \ 254 } else { \ 255 AF(&(address)) = AF_INET; \ 256 NSRCADR(&(address)) = (v4addr); \ 257 } \ 258 SET_SS_LEN_IF_PRESENT(&(address)); \ 259 } while (0) 260 261 262 /* 263 * SET_ADDRS - setup source and destination addresses for 264 * v4/v6 as needed 265 */ 266 #define SET_ADDRS(a1, a2, info, a1prefix, a2prefix) \ 267 do { \ 268 ZERO(a1); \ 269 ZERO(a2); \ 270 if ((info)->v6_flag) { \ 271 AF(&(a1)) = AF_INET6; \ 272 AF(&(a2)) = AF_INET6; \ 273 SOCK_ADDR6(&(a1)) = (info)->a1prefix##6; \ 274 SOCK_ADDR6(&(a2)) = (info)->a2prefix##6; \ 275 } else { \ 276 AF(&(a1)) = AF_INET; \ 277 AF(&(a2)) = AF_INET; \ 278 NSRCADR(&(a1)) = (info)->a1prefix; \ 279 NSRCADR(&(a2)) = (info)->a2prefix; \ 280 } \ 281 SET_SS_LEN_IF_PRESENT(&(a1)); \ 282 SET_SS_LEN_IF_PRESENT(&(a2)); \ 283 } while (0) 284 285 286 /* 287 * checkitems - utility to print a message if no items were returned 288 */ 289 static int 290 checkitems( 291 size_t items, 292 FILE *fp 293 ) 294 { 295 if (items == 0) { 296 (void) fprintf(fp, "No data returned in response to query\n"); 297 return 0; 298 } 299 return 1; 300 } 301 302 303 /* 304 * checkitemsize - utility to print a message if the item size is wrong 305 */ 306 static int 307 checkitemsize( 308 size_t itemsize, 309 size_t expected 310 ) 311 { 312 if (itemsize != expected) { 313 (void) fprintf(stderr, 314 "***Incorrect item size returned by remote host (%lu should be %lu)\n", 315 (u_long)itemsize, (u_long)expected); 316 return 0; 317 } 318 return 1; 319 } 320 321 322 /* 323 * check1item - check to make sure we have exactly one item 324 */ 325 static int 326 check1item( 327 size_t items, 328 FILE *fp 329 ) 330 { 331 if (items == 0) { 332 (void) fprintf(fp, "No data returned in response to query\n"); 333 return 0; 334 } 335 if (items > 1) { 336 (void) fprintf(fp, "Expected one item in response, got %lu\n", 337 (u_long)items); 338 return 0; 339 } 340 return 1; 341 } 342 343 344 /* 345 * peerlist - get a short list of peers 346 */ 347 /*ARGSUSED*/ 348 static void 349 peerlist( 350 struct parse *pcmd, 351 FILE *fp 352 ) 353 { 354 struct info_peer_list *plist; 355 sockaddr_u paddr; 356 size_t items; 357 size_t itemsize; 358 int res; 359 360 again: 361 res = doquery(impl_ver, REQ_PEER_LIST, 0, 0, 0, (char *)NULL, &items, 362 &itemsize, (void *)&plist, 0, 363 sizeof(struct info_peer_list)); 364 365 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 366 impl_ver = IMPL_XNTPD_OLD; 367 goto again; 368 } 369 370 if (res != 0) 371 return; 372 373 if (!checkitems(items, fp)) 374 return; 375 376 if (!checkitemsize(itemsize, sizeof(struct info_peer_list)) && 377 !checkitemsize(itemsize, v4sizeof(struct info_peer_list))) 378 return; 379 380 while (items > 0) { 381 SET_ADDR(paddr, plist->v6_flag, plist->addr, plist->addr6); 382 if ((pcmd->nargs == 0) || 383 ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) || 384 ((pcmd->argval->ival == 4) && (plist->v6_flag == 0))) 385 { 386 const char *strhost = nntohost(&paddr); 387 const char *straddr = stoa(&paddr); 388 (void) fprintf(fp, "%-12s %s", 389 modetoa(plist->hmode), strhost); 390 if (strcmp(strhost,straddr)) 391 (void) fprintf(fp, " (%s)\n", straddr); 392 else 393 (void) fprintf(fp, "\n"); 394 } 395 plist++; 396 items--; 397 } 398 } 399 400 401 /* 402 * peers - show peer summary 403 */ 404 static void 405 peers( 406 struct parse *pcmd, 407 FILE *fp 408 ) 409 { 410 dopeers(pcmd, fp, 0); 411 } 412 413 /* 414 * dmpeers - show peer summary, Dave Mills style 415 */ 416 static void 417 dmpeers( 418 struct parse *pcmd, 419 FILE *fp 420 ) 421 { 422 dopeers(pcmd, fp, 1); 423 } 424 425 426 /* 427 * peers - show peer summary 428 */ 429 /*ARGSUSED*/ 430 static void 431 dopeers( 432 struct parse *pcmd, 433 FILE *fp, 434 int dmstyle 435 ) 436 { 437 struct info_peer_summary *plist; 438 sockaddr_u dstadr; 439 sockaddr_u srcadr; 440 size_t items; 441 size_t itemsize; 442 int ntp_poll; 443 int res; 444 int c; 445 l_fp tempts; 446 447 again: 448 res = doquery(impl_ver, REQ_PEER_LIST_SUM, 0, 0, 0, (char *)NULL, 449 &items, &itemsize, (void *)&plist, 0, 450 sizeof(struct info_peer_summary)); 451 452 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 453 impl_ver = IMPL_XNTPD_OLD; 454 goto again; 455 } 456 457 if (res != 0) 458 return; 459 460 if (!checkitems(items, fp)) 461 return; 462 463 if (!checkitemsize(itemsize, sizeof(struct info_peer_summary)) && 464 !checkitemsize(itemsize, v4sizeof(struct info_peer_summary))) 465 return; 466 467 (void) fprintf(fp, 468 " remote local st poll reach delay offset disp\n"); 469 (void) fprintf(fp, 470 "=======================================================================\n"); 471 while (items > 0) { 472 if (!dmstyle) { 473 if (plist->flags & INFO_FLAG_SYSPEER) 474 c = '*'; 475 else if (plist->hmode == MODE_ACTIVE) 476 c = '+'; 477 else if (plist->hmode == MODE_PASSIVE) 478 c = '-'; 479 else if (plist->hmode == MODE_CLIENT) 480 c = '='; 481 else if (plist->hmode == MODE_BROADCAST) 482 c = '^'; 483 else if (plist->hmode == MODE_BCLIENT) 484 c = '~'; 485 else 486 c = ' '; 487 } else { 488 if (plist->flags & INFO_FLAG_SYSPEER) 489 c = '*'; 490 else if (plist->flags & INFO_FLAG_SHORTLIST) 491 c = '+'; 492 else if (plist->flags & INFO_FLAG_SEL_CANDIDATE) 493 c = '.'; 494 else 495 c = ' '; 496 } 497 NTOHL_FP(&(plist->offset), &tempts); 498 ntp_poll = 1<<max(min3(plist->ppoll, plist->hpoll, NTP_MAXPOLL), 499 NTP_MINPOLL); 500 SET_ADDRS(dstadr, srcadr, plist, dstadr, srcadr); 501 if ((pcmd->nargs == 0) || 502 ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) || 503 ((pcmd->argval->ival == 4) && (plist->v6_flag == 0))) 504 (void) fprintf(fp, 505 "%c%-15.15s %-15.15s %2u %4d %3o %7.7s %9.9s %7.7s\n", 506 c, nntohost(&srcadr), stoa(&dstadr), 507 plist->stratum, ntp_poll, plist->reach, 508 fptoa(NTOHS_FP(plist->delay), 5), 509 lfptoa(&tempts, 6), 510 ufptoa(NTOHS_FP(plist->dispersion), 5)); 511 plist++; 512 items--; 513 } 514 } 515 516 /* Convert a refid & stratum (in host order) to a string */ 517 static char * 518 refid_string( 519 u_int32 refid, 520 int stratum 521 ) 522 { 523 if (stratum <= 1) { 524 static char junk[5]; 525 junk[4] = 0; 526 memcpy(junk, &refid, 4); 527 return junk; 528 } 529 530 return numtoa(refid); 531 } 532 533 static void 534 print_pflag( 535 FILE * fp, 536 u_int32 flags 537 ) 538 { 539 static const char none[] = ""; 540 static const char comma[] = ","; 541 const char *dlim; 542 543 if (0 == flags) { 544 fprintf(fp, " none\n"); 545 return; 546 } 547 dlim = none; 548 if (flags & INFO_FLAG_SYSPEER) { 549 fprintf(fp, " system_peer"); 550 dlim = comma; 551 } 552 if (flags & INFO_FLAG_CONFIG) { 553 fprintf(fp, "%s config", dlim); 554 dlim = comma; 555 } 556 if (flags & INFO_FLAG_REFCLOCK) { 557 fprintf(fp, "%s refclock", dlim); 558 dlim = comma; 559 } 560 if (flags & INFO_FLAG_AUTHENABLE) { 561 fprintf(fp, "%s auth", dlim); 562 dlim = comma; 563 } 564 if (flags & INFO_FLAG_PREFER) { 565 fprintf(fp, "%s prefer", dlim); 566 dlim = comma; 567 } 568 if (flags & INFO_FLAG_IBURST) { 569 fprintf(fp, "%s iburst", dlim); 570 dlim = comma; 571 } 572 if (flags & INFO_FLAG_BURST) { 573 fprintf(fp, "%s burst", dlim); 574 dlim = comma; 575 } 576 if (flags & INFO_FLAG_SEL_CANDIDATE) { 577 fprintf(fp, "%s candidate", dlim); 578 dlim = comma; 579 } 580 if (flags & INFO_FLAG_SHORTLIST) { 581 fprintf(fp, "%s shortlist", dlim); 582 dlim = comma; 583 } 584 fprintf(fp, "\n"); 585 } 586 /* 587 * printpeer - print detail information for a peer 588 */ 589 static void 590 printpeer( 591 register struct info_peer *pp, 592 FILE *fp 593 ) 594 { 595 register int i; 596 l_fp tempts; 597 sockaddr_u srcadr, dstadr; 598 599 SET_ADDRS(dstadr, srcadr, pp, dstadr, srcadr); 600 601 (void) fprintf(fp, "remote %s, local %s\n", 602 stoa(&srcadr), stoa(&dstadr)); 603 (void) fprintf(fp, "hmode %s, pmode %s, stratum %d, precision %d\n", 604 modetoa(pp->hmode), modetoa(pp->pmode), 605 pp->stratum, pp->precision); 606 607 (void) fprintf(fp, 608 "leap %c%c, refid [%s], rootdistance %s, rootdispersion %s\n", 609 pp->leap & 0x2 ? '1' : '0', 610 pp->leap & 0x1 ? '1' : '0', 611 refid_string(pp->refid, 612 (pp->flags & INFO_FLAG_REFCLOCK ? 0 : pp->stratum)), 613 fptoa(NTOHS_FP(pp->rootdelay), 5), 614 ufptoa(NTOHS_FP(pp->rootdispersion), 5)); 615 616 (void) fprintf(fp, 617 "ppoll %d, hpoll %d, keyid %lu, version %d, association %u\n", 618 pp->ppoll, pp->hpoll, (u_long)pp->keyid, pp->version, ntohs(pp->associd)); 619 620 (void) fprintf(fp, 621 "reach %03o, unreach %d, flash 0x%04x, ", 622 pp->reach, pp->unreach, pp->flash2); 623 624 (void) fprintf(fp, "boffset %s, ttl/mode %d\n", 625 fptoa(NTOHS_FP(pp->estbdelay), 5), pp->ttl); 626 627 (void) fprintf(fp, "timer %lds, flags", (long)ntohl(pp->timer)); 628 print_pflag(fp, pp->flags); 629 630 NTOHL_FP(&pp->reftime, &tempts); 631 (void) fprintf(fp, "reference time: %s\n", 632 prettydate(&tempts)); 633 NTOHL_FP(&pp->org, &tempts); 634 (void) fprintf(fp, "originate timestamp: %s\n", 635 prettydate(&tempts)); 636 NTOHL_FP(&pp->rec, &tempts); 637 (void) fprintf(fp, "receive timestamp: %s\n", 638 prettydate(&tempts)); 639 NTOHL_FP(&pp->xmt, &tempts); 640 (void) fprintf(fp, "transmit timestamp: %s\n", 641 prettydate(&tempts)); 642 643 (void) fprintf(fp, "filter delay: "); 644 for (i = 0; i < NTP_SHIFT; i++) { 645 (void) fprintf(fp, " %-8.8s", 646 fptoa(NTOHS_FP(pp->filtdelay[i]), 5)); 647 if (i == (NTP_SHIFT>>1)-1) 648 (void) fprintf(fp, "\n "); 649 } 650 (void) fprintf(fp, "\n"); 651 652 (void) fprintf(fp, "filter offset:"); 653 for (i = 0; i < NTP_SHIFT; i++) { 654 NTOHL_FP(&pp->filtoffset[i], &tempts); 655 (void) fprintf(fp, " %-8.8s", lfptoa(&tempts, 6)); 656 if (i == (NTP_SHIFT>>1)-1) 657 (void) fprintf(fp, "\n "); 658 } 659 (void) fprintf(fp, "\n"); 660 661 (void) fprintf(fp, "filter order: "); 662 for (i = 0; i < NTP_SHIFT; i++) { 663 (void) fprintf(fp, " %-8d", pp->order[i]); 664 if (i == (NTP_SHIFT>>1)-1) 665 (void) fprintf(fp, "\n "); 666 } 667 (void) fprintf(fp, "\n"); 668 669 670 NTOHL_FP(&pp->offset, &tempts); 671 (void) fprintf(fp, 672 "offset %s, delay %s, error bound %s, filter error %s\n", 673 lfptoa(&tempts, 6), fptoa(NTOHS_FP(pp->delay), 5), 674 ufptoa(NTOHS_FP(pp->dispersion), 5), 675 ufptoa(NTOHS_FP(pp->selectdisp), 5)); 676 } 677 678 679 /* 680 * showpeer - show detailed information for a peer 681 */ 682 static void 683 showpeer( 684 struct parse *pcmd, 685 FILE *fp 686 ) 687 { 688 struct info_peer *pp; 689 /* 4 is the maximum number of peers which will fit in a packet */ 690 struct info_peer_list *pl, plist[min(MAXARGS, 4)]; 691 size_t qitemlim; 692 size_t qitems; 693 size_t items; 694 size_t itemsize; 695 int res; 696 int sendsize; 697 698 again: 699 if (impl_ver == IMPL_XNTPD) 700 sendsize = sizeof(struct info_peer_list); 701 else 702 sendsize = v4sizeof(struct info_peer_list); 703 704 qitemlim = min(pcmd->nargs, COUNTOF(plist)); 705 for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) { 706 if (IS_IPV4(&pcmd->argval[qitems].netnum)) { 707 pl->addr = NSRCADR(&pcmd->argval[qitems].netnum); 708 if (impl_ver == IMPL_XNTPD) 709 pl->v6_flag = 0; 710 } else { 711 if (impl_ver == IMPL_XNTPD_OLD) { 712 fprintf(stderr, 713 "***Server doesn't understand IPv6 addresses\n"); 714 return; 715 } 716 pl->addr6 = SOCK_ADDR6(&pcmd->argval[qitems].netnum); 717 pl->v6_flag = 1; 718 } 719 pl->port = (u_short)s_port; 720 pl->hmode = pl->flags = 0; 721 pl = (void *)((char *)pl + sendsize); 722 } 723 724 res = doquery(impl_ver, REQ_PEER_INFO, 0, qitems, 725 sendsize, (char *)plist, &items, 726 &itemsize, (void *)&pp, 0, sizeof(struct info_peer)); 727 728 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 729 impl_ver = IMPL_XNTPD_OLD; 730 goto again; 731 } 732 733 if (res != 0) 734 return; 735 736 if (!checkitems(items, fp)) 737 return; 738 739 if (!checkitemsize(itemsize, sizeof(struct info_peer)) && 740 !checkitemsize(itemsize, v4sizeof(struct info_peer))) 741 return; 742 743 while (items-- > 0) { 744 printpeer(pp, fp); 745 if (items > 0) 746 fprintf(fp, "\n"); 747 pp++; 748 } 749 } 750 751 752 /* 753 * peerstats - return statistics for a peer 754 */ 755 static void 756 peerstats( 757 struct parse *pcmd, 758 FILE *fp 759 ) 760 { 761 struct info_peer_stats *pp; 762 /* 4 is the maximum number of peers which will fit in a packet */ 763 struct info_peer_list *pl, plist[min(MAXARGS, 4)]; 764 sockaddr_u src, dst; 765 size_t qitemlim; 766 size_t qitems; 767 size_t items; 768 size_t itemsize; 769 int res; 770 size_t sendsize; 771 772 again: 773 if (impl_ver == IMPL_XNTPD) 774 sendsize = sizeof(struct info_peer_list); 775 else 776 sendsize = v4sizeof(struct info_peer_list); 777 778 ZERO(plist); 779 780 qitemlim = min(pcmd->nargs, COUNTOF(plist)); 781 for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) { 782 if (IS_IPV4(&pcmd->argval[qitems].netnum)) { 783 pl->addr = NSRCADR(&pcmd->argval[qitems].netnum); 784 if (impl_ver == IMPL_XNTPD) 785 pl->v6_flag = 0; 786 } else { 787 if (impl_ver == IMPL_XNTPD_OLD) { 788 fprintf(stderr, 789 "***Server doesn't understand IPv6 addresses\n"); 790 return; 791 } 792 pl->addr6 = SOCK_ADDR6(&pcmd->argval[qitems].netnum); 793 pl->v6_flag = 1; 794 } 795 pl->port = (u_short)s_port; 796 pl->hmode = plist[qitems].flags = 0; 797 pl = (void *)((char *)pl + sendsize); 798 } 799 800 res = doquery(impl_ver, REQ_PEER_STATS, 0, qitems, 801 sendsize, (char *)plist, &items, 802 &itemsize, (void *)&pp, 0, 803 sizeof(struct info_peer_stats)); 804 805 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 806 impl_ver = IMPL_XNTPD_OLD; 807 goto again; 808 } 809 810 if (res != 0) 811 return; 812 813 if (!checkitems(items, fp)) 814 return; 815 816 if (!checkitemsize(itemsize, sizeof(struct info_peer_stats)) && 817 !checkitemsize(itemsize, v4sizeof(struct info_peer_stats))) 818 return; 819 820 while (items-- > 0) { 821 ZERO_SOCK(&dst); 822 ZERO_SOCK(&src); 823 if (pp->v6_flag != 0) { 824 AF(&dst) = AF_INET6; 825 AF(&src) = AF_INET6; 826 SOCK_ADDR6(&dst) = pp->dstadr6; 827 SOCK_ADDR6(&src) = pp->srcadr6; 828 } else { 829 AF(&dst) = AF_INET; 830 AF(&src) = AF_INET; 831 NSRCADR(&dst) = pp->dstadr; 832 NSRCADR(&src) = pp->srcadr; 833 } 834 #ifdef ISC_PLATFORM_HAVESALEN 835 src.sa.sa_len = SOCKLEN(&src); 836 dst.sa.sa_len = SOCKLEN(&dst); 837 #endif 838 fprintf(fp, "remote host: %s\n", 839 nntohost(&src)); 840 fprintf(fp, "local interface: %s\n", 841 stoa(&dst)); 842 fprintf(fp, "time last received: %lus\n", 843 (u_long)ntohl(pp->timereceived)); 844 fprintf(fp, "time until next send: %lus\n", 845 (u_long)ntohl(pp->timetosend)); 846 fprintf(fp, "reachability change: %lus\n", 847 (u_long)ntohl(pp->timereachable)); 848 fprintf(fp, "packets sent: %lu\n", 849 (u_long)ntohl(pp->sent)); 850 fprintf(fp, "packets received: %lu\n", 851 (u_long)ntohl(pp->processed)); 852 fprintf(fp, "bad authentication: %lu\n", 853 (u_long)ntohl(pp->badauth)); 854 fprintf(fp, "bogus origin: %lu\n", 855 (u_long)ntohl(pp->bogusorg)); 856 fprintf(fp, "duplicate: %lu\n", 857 (u_long)ntohl(pp->oldpkt)); 858 fprintf(fp, "bad dispersion: %lu\n", 859 (u_long)ntohl(pp->seldisp)); 860 fprintf(fp, "bad reference time: %lu\n", 861 (u_long)ntohl(pp->selbroken)); 862 fprintf(fp, "candidate order: %u\n", 863 pp->candidate); 864 if (items > 0) 865 fprintf(fp, "\n"); 866 fprintf(fp, "flags: "); 867 print_pflag(fp, ntohs(pp->flags)); 868 pp++; 869 } 870 } 871 872 873 /* 874 * loopinfo - show loop filter information 875 */ 876 static void 877 loopinfo( 878 struct parse *pcmd, 879 FILE *fp 880 ) 881 { 882 struct info_loop *il; 883 size_t items; 884 size_t itemsize; 885 int oneline = 0; 886 int res; 887 l_fp tempts; 888 889 if (pcmd->nargs > 0) { 890 if (STREQ(pcmd->argval[0].string, "oneline")) 891 oneline = 1; 892 else if (STREQ(pcmd->argval[0].string, "multiline")) 893 oneline = 0; 894 else { 895 (void) fprintf(stderr, "How many lines?\n"); 896 return; 897 } 898 } 899 900 again: 901 res = doquery(impl_ver, REQ_LOOP_INFO, 0, 0, 0, (char *)NULL, 902 &items, &itemsize, (void *)&il, 0, 903 sizeof(struct info_loop)); 904 905 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 906 impl_ver = IMPL_XNTPD_OLD; 907 goto again; 908 } 909 910 if (res != 0) 911 return; 912 913 if (!check1item(items, fp)) 914 return; 915 916 if (!checkitemsize(itemsize, sizeof(struct info_loop))) 917 return; 918 919 if (oneline) { 920 l_fp temp2ts; 921 922 NTOHL_FP(&il->last_offset, &tempts); 923 NTOHL_FP(&il->drift_comp, &temp2ts); 924 925 (void) fprintf(fp, 926 "offset %s, frequency %s, time_const %ld, watchdog %ld\n", 927 lfptoa(&tempts, 6), 928 lfptoa(&temp2ts, 3), 929 (long)(int32)ntohl((u_long)il->compliance), 930 (u_long)ntohl((u_long)il->watchdog_timer)); 931 } else { 932 NTOHL_FP(&il->last_offset, &tempts); 933 (void) fprintf(fp, "offset: %s s\n", 934 lfptoa(&tempts, 6)); 935 NTOHL_FP(&il->drift_comp, &tempts); 936 (void) fprintf(fp, "frequency: %s ppm\n", 937 lfptoa(&tempts, 3)); 938 (void) fprintf(fp, "poll adjust: %ld\n", 939 (long)(int32)ntohl(il->compliance)); 940 (void) fprintf(fp, "watchdog timer: %ld s\n", 941 (u_long)ntohl(il->watchdog_timer)); 942 } 943 } 944 945 946 /* 947 * sysinfo - show current system state 948 */ 949 /*ARGSUSED*/ 950 static void 951 sysinfo( 952 struct parse *pcmd, 953 FILE *fp 954 ) 955 { 956 struct info_sys *is; 957 sockaddr_u peeraddr; 958 size_t items; 959 size_t itemsize; 960 int res; 961 l_fp tempts; 962 963 again: 964 res = doquery(impl_ver, REQ_SYS_INFO, 0, 0, 0, (char *)NULL, 965 &items, &itemsize, (void *)&is, 0, 966 sizeof(struct info_sys)); 967 968 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 969 impl_ver = IMPL_XNTPD_OLD; 970 goto again; 971 } 972 973 if (res != 0) 974 return; 975 976 if (!check1item(items, fp)) 977 return; 978 979 if (!checkitemsize(itemsize, sizeof(struct info_sys)) && 980 !checkitemsize(itemsize, v4sizeof(struct info_sys))) 981 return; 982 983 SET_ADDR(peeraddr, is->v6_flag, is->peer, is->peer6); 984 985 (void) fprintf(fp, "system peer: %s\n", nntohost(&peeraddr)); 986 (void) fprintf(fp, "system peer mode: %s\n", modetoa(is->peer_mode)); 987 (void) fprintf(fp, "leap indicator: %c%c\n", 988 is->leap & 0x2 ? '1' : '0', 989 is->leap & 0x1 ? '1' : '0'); 990 (void) fprintf(fp, "stratum: %d\n", (int)is->stratum); 991 (void) fprintf(fp, "precision: %d\n", (int)is->precision); 992 (void) fprintf(fp, "root distance: %s s\n", 993 fptoa(NTOHS_FP(is->rootdelay), 5)); 994 (void) fprintf(fp, "root dispersion: %s s\n", 995 ufptoa(NTOHS_FP(is->rootdispersion), 5)); 996 (void) fprintf(fp, "reference ID: [%s]\n", 997 refid_string(is->refid, is->stratum)); 998 NTOHL_FP(&is->reftime, &tempts); 999 (void) fprintf(fp, "reference time: %s\n", prettydate(&tempts)); 1000 1001 (void) fprintf(fp, "system flags: "); 1002 if ((is->flags & (INFO_FLAG_BCLIENT | INFO_FLAG_AUTHENABLE | 1003 INFO_FLAG_NTP | INFO_FLAG_KERNEL| INFO_FLAG_CAL | 1004 INFO_FLAG_PPS_SYNC | INFO_FLAG_MONITOR | INFO_FLAG_FILEGEN)) == 0) { 1005 (void) fprintf(fp, "none\n"); 1006 } else { 1007 if (is->flags & INFO_FLAG_BCLIENT) 1008 (void) fprintf(fp, "bclient "); 1009 if (is->flags & INFO_FLAG_AUTHENTICATE) 1010 (void) fprintf(fp, "auth "); 1011 if (is->flags & INFO_FLAG_MONITOR) 1012 (void) fprintf(fp, "monitor "); 1013 if (is->flags & INFO_FLAG_NTP) 1014 (void) fprintf(fp, "ntp "); 1015 if (is->flags & INFO_FLAG_KERNEL) 1016 (void) fprintf(fp, "kernel "); 1017 if (is->flags & INFO_FLAG_FILEGEN) 1018 (void) fprintf(fp, "stats "); 1019 if (is->flags & INFO_FLAG_CAL) 1020 (void) fprintf(fp, "calibrate "); 1021 if (is->flags & INFO_FLAG_PPS_SYNC) 1022 (void) fprintf(fp, "pps "); 1023 (void) fprintf(fp, "\n"); 1024 } 1025 (void) fprintf(fp, "jitter: %s s\n", 1026 fptoa(ntohl(is->frequency), 6)); 1027 (void) fprintf(fp, "stability: %s ppm\n", 1028 ufptoa(ntohl(is->stability), 3)); 1029 (void) fprintf(fp, "broadcastdelay: %s s\n", 1030 fptoa(NTOHS_FP(is->bdelay), 6)); 1031 NTOHL_FP(&is->authdelay, &tempts); 1032 (void) fprintf(fp, "authdelay: %s s\n", lfptoa(&tempts, 6)); 1033 } 1034 1035 1036 /* 1037 * sysstats - print system statistics 1038 */ 1039 /*ARGSUSED*/ 1040 static void 1041 sysstats( 1042 struct parse *pcmd, 1043 FILE *fp 1044 ) 1045 { 1046 struct info_sys_stats *ss; 1047 size_t items; 1048 size_t itemsize; 1049 int res; 1050 1051 again: 1052 res = doquery(impl_ver, REQ_SYS_STATS, 0, 0, 0, (char *)NULL, 1053 &items, &itemsize, (void *)&ss, 0, 1054 sizeof(struct info_sys_stats)); 1055 1056 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1057 impl_ver = IMPL_XNTPD_OLD; 1058 goto again; 1059 } 1060 1061 if (res != 0) 1062 return; 1063 1064 if (!check1item(items, fp)) 1065 return; 1066 1067 if (itemsize != sizeof(struct info_sys_stats) && 1068 itemsize != sizeof(struct old_info_sys_stats)) { 1069 /* issue warning according to new structure size */ 1070 checkitemsize(itemsize, sizeof(struct info_sys_stats)); 1071 return; 1072 } 1073 fprintf(fp, "time since restart: %lu\n", 1074 (u_long)ntohl(ss->timeup)); 1075 fprintf(fp, "time since reset: %lu\n", 1076 (u_long)ntohl(ss->timereset)); 1077 fprintf(fp, "packets received: %lu\n", 1078 (u_long)ntohl(ss->received)); 1079 fprintf(fp, "packets processed: %lu\n", 1080 (u_long)ntohl(ss->processed)); 1081 fprintf(fp, "current version: %lu\n", 1082 (u_long)ntohl(ss->newversionpkt)); 1083 fprintf(fp, "previous version: %lu\n", 1084 (u_long)ntohl(ss->oldversionpkt)); 1085 fprintf(fp, "declined: %lu\n", 1086 (u_long)ntohl(ss->unknownversion)); 1087 fprintf(fp, "access denied: %lu\n", 1088 (u_long)ntohl(ss->denied)); 1089 fprintf(fp, "bad length or format: %lu\n", 1090 (u_long)ntohl(ss->badlength)); 1091 fprintf(fp, "bad authentication: %lu\n", 1092 (u_long)ntohl(ss->badauth)); 1093 if (itemsize != sizeof(struct info_sys_stats)) 1094 return; 1095 1096 fprintf(fp, "rate exceeded: %lu\n", 1097 (u_long)ntohl(ss->limitrejected)); 1098 } 1099 1100 1101 1102 /* 1103 * iostats - print I/O statistics 1104 */ 1105 /*ARGSUSED*/ 1106 static void 1107 iostats( 1108 struct parse *pcmd, 1109 FILE *fp 1110 ) 1111 { 1112 struct info_io_stats *io; 1113 size_t items; 1114 size_t itemsize; 1115 int res; 1116 1117 again: 1118 res = doquery(impl_ver, REQ_IO_STATS, 0, 0, 0, NULL, &items, 1119 &itemsize, (void *)&io, 0, sizeof(*io)); 1120 1121 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1122 impl_ver = IMPL_XNTPD_OLD; 1123 goto again; 1124 } 1125 1126 if (res != 0) 1127 return; 1128 1129 if (!check1item(items, fp)) 1130 return; 1131 1132 if (!checkitemsize(itemsize, sizeof(*io))) 1133 return; 1134 1135 fprintf(fp, "time since reset: %lu\n", 1136 (u_long)ntohl(io->timereset)); 1137 fprintf(fp, "receive buffers: %u\n", 1138 (u_int)ntohs(io->totalrecvbufs)); 1139 fprintf(fp, "free receive buffers: %u\n", 1140 (u_int)ntohs(io->freerecvbufs)); 1141 fprintf(fp, "used receive buffers: %u\n", 1142 (u_int)ntohs(io->fullrecvbufs)); 1143 fprintf(fp, "low water refills: %u\n", 1144 (u_int)ntohs(io->lowwater)); 1145 fprintf(fp, "dropped packets: %lu\n", 1146 (u_long)ntohl(io->dropped)); 1147 fprintf(fp, "ignored packets: %lu\n", 1148 (u_long)ntohl(io->ignored)); 1149 fprintf(fp, "received packets: %lu\n", 1150 (u_long)ntohl(io->received)); 1151 fprintf(fp, "packets sent: %lu\n", 1152 (u_long)ntohl(io->sent)); 1153 fprintf(fp, "packets not sent: %lu\n", 1154 (u_long)ntohl(io->notsent)); 1155 fprintf(fp, "interrupts handled: %lu\n", 1156 (u_long)ntohl(io->interrupts)); 1157 fprintf(fp, "received by int: %lu\n", 1158 (u_long)ntohl(io->int_received)); 1159 } 1160 1161 1162 /* 1163 * memstats - print peer memory statistics 1164 */ 1165 /*ARGSUSED*/ 1166 static void 1167 memstats( 1168 struct parse *pcmd, 1169 FILE *fp 1170 ) 1171 { 1172 struct info_mem_stats *mem; 1173 int i; 1174 size_t items; 1175 size_t itemsize; 1176 int res; 1177 1178 again: 1179 res = doquery(impl_ver, REQ_MEM_STATS, 0, 0, 0, NULL, &items, 1180 &itemsize, (void *)&mem, 0, sizeof(*mem)); 1181 1182 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1183 impl_ver = IMPL_XNTPD_OLD; 1184 goto again; 1185 } 1186 1187 if (res != 0) 1188 return; 1189 1190 if (!check1item(items, fp)) 1191 return; 1192 1193 if (!checkitemsize(itemsize, sizeof(*mem))) 1194 return; 1195 1196 fprintf(fp, "time since reset: %lu\n", 1197 (u_long)ntohl(mem->timereset)); 1198 fprintf(fp, "total peer memory: %u\n", 1199 (u_int)ntohs(mem->totalpeermem)); 1200 fprintf(fp, "free peer memory: %u\n", 1201 (u_int)ntohs(mem->freepeermem)); 1202 fprintf(fp, "calls to findpeer: %lu\n", 1203 (u_long)ntohl(mem->findpeer_calls)); 1204 fprintf(fp, "new peer allocations: %lu\n", 1205 (u_long)ntohl(mem->allocations)); 1206 fprintf(fp, "peer demobilizations: %lu\n", 1207 (u_long)ntohl(mem->demobilizations)); 1208 1209 fprintf(fp, "hash table counts: "); 1210 for (i = 0; i < NTP_HASH_SIZE; i++) { 1211 fprintf(fp, "%4d", (int)mem->hashcount[i]); 1212 if ((i % 8) == 7 && i != (NTP_HASH_SIZE-1)) 1213 fprintf(fp, "\n "); 1214 } 1215 fprintf(fp, "\n"); 1216 } 1217 1218 1219 1220 /* 1221 * timerstats - print timer statistics 1222 */ 1223 /*ARGSUSED*/ 1224 static void 1225 timerstats( 1226 struct parse *pcmd, 1227 FILE *fp 1228 ) 1229 { 1230 struct info_timer_stats *tim; 1231 size_t items; 1232 size_t itemsize; 1233 int res; 1234 1235 again: 1236 res = doquery(impl_ver, REQ_TIMER_STATS, 0, 0, 0, NULL, &items, 1237 &itemsize, (void *)&tim, 0, sizeof(*tim)); 1238 1239 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1240 impl_ver = IMPL_XNTPD_OLD; 1241 goto again; 1242 } 1243 1244 if (res != 0) 1245 return; 1246 1247 if (!check1item(items, fp)) 1248 return; 1249 1250 if (!checkitemsize(itemsize, sizeof(*tim))) 1251 return; 1252 1253 fprintf(fp, "time since reset: %lu\n", 1254 (u_long)ntohl(tim->timereset)); 1255 fprintf(fp, "alarms handled: %lu\n", 1256 (u_long)ntohl(tim->alarms)); 1257 fprintf(fp, "alarm overruns: %lu\n", 1258 (u_long)ntohl(tim->overflows)); 1259 fprintf(fp, "calls to transmit: %lu\n", 1260 (u_long)ntohl(tim->xmtcalls)); 1261 } 1262 1263 1264 /* 1265 * addpeer - configure an active mode association 1266 */ 1267 static void 1268 addpeer( 1269 struct parse *pcmd, 1270 FILE *fp 1271 ) 1272 { 1273 doconfig(pcmd, fp, MODE_ACTIVE, 0); 1274 } 1275 1276 1277 /* 1278 * addserver - configure a client mode association 1279 */ 1280 static void 1281 addserver( 1282 struct parse *pcmd, 1283 FILE *fp 1284 ) 1285 { 1286 doconfig(pcmd, fp, MODE_CLIENT, 0); 1287 } 1288 1289 /* 1290 * addrefclock - configure a reference clock association 1291 */ 1292 static void 1293 addrefclock( 1294 struct parse *pcmd, 1295 FILE *fp 1296 ) 1297 { 1298 doconfig(pcmd, fp, MODE_CLIENT, 1); 1299 } 1300 1301 /* 1302 * broadcast - configure a broadcast mode association 1303 */ 1304 static void 1305 broadcast( 1306 struct parse *pcmd, 1307 FILE *fp 1308 ) 1309 { 1310 doconfig(pcmd, fp, MODE_BROADCAST, 0); 1311 } 1312 1313 1314 /* 1315 * config - configure a new peer association 1316 */ 1317 static void 1318 doconfig( 1319 struct parse *pcmd, 1320 FILE *fp, 1321 int mode, 1322 int refc 1323 ) 1324 { 1325 struct conf_peer cpeer; 1326 size_t items; 1327 size_t itemsize; 1328 const char *dummy; 1329 u_long keyid; 1330 u_int version; 1331 u_char minpoll; 1332 u_char maxpoll; 1333 u_int flags; 1334 u_char cmode; 1335 int res; 1336 int sendsize; 1337 int numtyp; 1338 long val; 1339 1340 again: 1341 keyid = 0; 1342 version = 3; 1343 flags = 0; 1344 res = FALSE; 1345 cmode = 0; 1346 minpoll = NTP_MINDPOLL; 1347 maxpoll = NTP_MAXDPOLL; 1348 numtyp = 1; 1349 if (refc) 1350 numtyp = 5; 1351 1352 if (impl_ver == IMPL_XNTPD) 1353 sendsize = sizeof(struct conf_peer); 1354 else 1355 sendsize = v4sizeof(struct conf_peer); 1356 1357 items = 1; 1358 while (pcmd->nargs > (size_t)items) { 1359 if (STREQ(pcmd->argval[items].string, "prefer")) 1360 flags |= CONF_FLAG_PREFER; 1361 else if (STREQ(pcmd->argval[items].string, "burst")) 1362 flags |= CONF_FLAG_BURST; 1363 else if (STREQ(pcmd->argval[items].string, "iburst")) 1364 flags |= CONF_FLAG_IBURST; 1365 else if (!refc && STREQ(pcmd->argval[items].string, "keyid")) 1366 numtyp = 1; 1367 else if (!refc && STREQ(pcmd->argval[items].string, "version")) 1368 numtyp = 2; 1369 else if (STREQ(pcmd->argval[items].string, "minpoll")) 1370 numtyp = 3; 1371 else if (STREQ(pcmd->argval[items].string, "maxpoll")) 1372 numtyp = 4; 1373 else { 1374 if (!atoint(pcmd->argval[items].string, &val)) 1375 numtyp = 0; 1376 switch (numtyp) { 1377 case 1: 1378 keyid = val; 1379 numtyp = 2; 1380 break; 1381 1382 case 2: 1383 version = (u_int)val; 1384 numtyp = 0; 1385 break; 1386 1387 case 3: 1388 minpoll = (u_char)val; 1389 numtyp = 0; 1390 break; 1391 1392 case 4: 1393 maxpoll = (u_char)val; 1394 numtyp = 0; 1395 break; 1396 1397 case 5: 1398 cmode = (u_char)val; 1399 numtyp = 0; 1400 break; 1401 1402 default: 1403 fprintf(fp, "*** '%s' not understood\n", 1404 pcmd->argval[items].string); 1405 res = TRUE; 1406 numtyp = 0; 1407 } 1408 if (val < 0) { 1409 fprintf(stderr, 1410 "*** Value '%s' should be unsigned\n", 1411 pcmd->argval[items].string); 1412 res = TRUE; 1413 } 1414 } 1415 items++; 1416 } 1417 if (keyid > 0) 1418 flags |= CONF_FLAG_AUTHENABLE; 1419 if (version > NTP_VERSION || version < NTP_OLDVERSION) { 1420 fprintf(fp, "***invalid version number: %u\n", 1421 version); 1422 res = TRUE; 1423 } 1424 if (minpoll < NTP_MINPOLL || minpoll > NTP_MAXPOLL || 1425 maxpoll < NTP_MINPOLL || maxpoll > NTP_MAXPOLL || 1426 minpoll > maxpoll) { 1427 fprintf(fp, "***min/max-poll must be within %d..%d\n", 1428 NTP_MINPOLL, NTP_MAXPOLL); 1429 res = TRUE; 1430 } 1431 1432 if (res) 1433 return; 1434 1435 ZERO(cpeer); 1436 1437 if (IS_IPV4(&pcmd->argval[0].netnum)) { 1438 cpeer.peeraddr = NSRCADR(&pcmd->argval[0].netnum); 1439 if (impl_ver == IMPL_XNTPD) 1440 cpeer.v6_flag = 0; 1441 } else { 1442 if (impl_ver == IMPL_XNTPD_OLD) { 1443 fprintf(stderr, 1444 "***Server doesn't understand IPv6 addresses\n"); 1445 return; 1446 } 1447 cpeer.peeraddr6 = SOCK_ADDR6(&pcmd->argval[0].netnum); 1448 cpeer.v6_flag = 1; 1449 } 1450 cpeer.hmode = (u_char) mode; 1451 cpeer.keyid = keyid; 1452 cpeer.version = (u_char) version; 1453 cpeer.minpoll = minpoll; 1454 cpeer.maxpoll = maxpoll; 1455 cpeer.flags = (u_char)flags; 1456 cpeer.ttl = cmode; 1457 1458 res = doquery(impl_ver, REQ_CONFIG, 1, 1, 1459 sendsize, (char *)&cpeer, &items, 1460 &itemsize, &dummy, 0, sizeof(struct conf_peer)); 1461 1462 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1463 impl_ver = IMPL_XNTPD_OLD; 1464 goto again; 1465 } 1466 1467 if (res == INFO_ERR_FMT) { 1468 (void) fprintf(fp, 1469 "***Retrying command with old conf_peer size\n"); 1470 res = doquery(impl_ver, REQ_CONFIG, 1, 1, 1471 sizeof(struct old_conf_peer), (char *)&cpeer, 1472 &items, &itemsize, &dummy, 0, 1473 sizeof(struct conf_peer)); 1474 } 1475 if (res == 0) 1476 (void) fprintf(fp, "done!\n"); 1477 return; 1478 } 1479 1480 1481 /* 1482 * unconfig - unconfigure some associations 1483 */ 1484 static void 1485 unconfig( 1486 struct parse *pcmd, 1487 FILE *fp 1488 ) 1489 { 1490 /* 8 is the maximum number of peers which will fit in a packet */ 1491 struct conf_unpeer *pl, plist[min(MAXARGS, 8)]; 1492 size_t qitemlim; 1493 size_t qitems; 1494 size_t items; 1495 size_t itemsize; 1496 const char *dummy; 1497 int res; 1498 size_t sendsize; 1499 1500 again: 1501 if (impl_ver == IMPL_XNTPD) 1502 sendsize = sizeof(struct conf_unpeer); 1503 else 1504 sendsize = v4sizeof(struct conf_unpeer); 1505 1506 qitemlim = min(pcmd->nargs, COUNTOF(plist)); 1507 for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) { 1508 if (IS_IPV4(&pcmd->argval[0].netnum)) { 1509 pl->peeraddr = NSRCADR(&pcmd->argval[qitems].netnum); 1510 if (impl_ver == IMPL_XNTPD) 1511 pl->v6_flag = 0; 1512 } else { 1513 if (impl_ver == IMPL_XNTPD_OLD) { 1514 fprintf(stderr, 1515 "***Server doesn't understand IPv6 addresses\n"); 1516 return; 1517 } 1518 pl->peeraddr6 = 1519 SOCK_ADDR6(&pcmd->argval[qitems].netnum); 1520 pl->v6_flag = 1; 1521 } 1522 pl = (void *)((char *)pl + sendsize); 1523 } 1524 1525 res = doquery(impl_ver, REQ_UNCONFIG, 1, qitems, 1526 sendsize, (char *)plist, &items, 1527 &itemsize, &dummy, 0, sizeof(struct conf_unpeer)); 1528 1529 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1530 impl_ver = IMPL_XNTPD_OLD; 1531 goto again; 1532 } 1533 1534 if (res == 0) 1535 (void) fprintf(fp, "done!\n"); 1536 } 1537 1538 1539 /* 1540 * set - set some system flags 1541 */ 1542 static void 1543 set( 1544 struct parse *pcmd, 1545 FILE *fp 1546 ) 1547 { 1548 doset(pcmd, fp, REQ_SET_SYS_FLAG); 1549 } 1550 1551 1552 /* 1553 * clear - clear some system flags 1554 */ 1555 static void 1556 sys_clear( 1557 struct parse *pcmd, 1558 FILE *fp 1559 ) 1560 { 1561 doset(pcmd, fp, REQ_CLR_SYS_FLAG); 1562 } 1563 1564 1565 /* 1566 * doset - set/clear system flags 1567 */ 1568 static void 1569 doset( 1570 struct parse *pcmd, 1571 FILE *fp, 1572 int req 1573 ) 1574 { 1575 struct conf_sys_flags sys; 1576 size_t items; 1577 size_t itemsize; 1578 const char *dummy; 1579 int res; 1580 1581 sys.flags = 0; 1582 res = 0; 1583 for (items = 0; (size_t)items < pcmd->nargs; items++) { 1584 if (STREQ(pcmd->argval[items].string, "auth")) 1585 sys.flags |= SYS_FLAG_AUTH; 1586 else if (STREQ(pcmd->argval[items].string, "bclient")) 1587 sys.flags |= SYS_FLAG_BCLIENT; 1588 else if (STREQ(pcmd->argval[items].string, "calibrate")) 1589 sys.flags |= SYS_FLAG_CAL; 1590 else if (STREQ(pcmd->argval[items].string, "kernel")) 1591 sys.flags |= SYS_FLAG_KERNEL; 1592 else if (STREQ(pcmd->argval[items].string, "monitor")) 1593 sys.flags |= SYS_FLAG_MONITOR; 1594 else if (STREQ(pcmd->argval[items].string, "ntp")) 1595 sys.flags |= SYS_FLAG_NTP; 1596 else if (STREQ(pcmd->argval[items].string, "pps")) 1597 sys.flags |= SYS_FLAG_PPS; 1598 else if (STREQ(pcmd->argval[items].string, "stats")) 1599 sys.flags |= SYS_FLAG_FILEGEN; 1600 else { 1601 (void) fprintf(fp, "Unknown flag %s\n", 1602 pcmd->argval[items].string); 1603 res = 1; 1604 } 1605 } 1606 1607 sys.flags = htonl(sys.flags); 1608 if (res || sys.flags == 0) 1609 return; 1610 1611 again: 1612 res = doquery(impl_ver, req, 1, 1, 1613 sizeof(struct conf_sys_flags), (char *)&sys, &items, 1614 &itemsize, &dummy, 0, sizeof(struct conf_sys_flags)); 1615 1616 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1617 impl_ver = IMPL_XNTPD_OLD; 1618 goto again; 1619 } 1620 1621 if (res == 0) 1622 (void) fprintf(fp, "done!\n"); 1623 } 1624 1625 1626 /* 1627 * data for printing/interrpreting the restrict flags 1628 */ 1629 struct resflags { 1630 const char *str; 1631 int bit; 1632 }; 1633 1634 /* XXX: HMS: we apparently don't report set bits we do not recognize. */ 1635 1636 static struct resflags resflagsV2[] = { 1637 { "ignore", 0x001 }, 1638 { "noserve", 0x002 }, 1639 { "notrust", 0x004 }, 1640 { "noquery", 0x008 }, 1641 { "nomodify", 0x010 }, 1642 { "nopeer", 0x020 }, 1643 { "notrap", 0x040 }, 1644 { "lptrap", 0x080 }, 1645 { "limited", 0x100 }, 1646 { "", 0 } 1647 }; 1648 1649 static struct resflags resflagsV3[] = { 1650 { "ignore", RES_IGNORE }, 1651 { "noserve", RES_DONTSERVE }, 1652 { "notrust", RES_DONTTRUST }, 1653 { "noquery", RES_NOQUERY }, 1654 { "nomodify", RES_NOMODIFY }, 1655 { "nopeer", RES_NOPEER }, 1656 { "notrap", RES_NOTRAP }, 1657 { "lptrap", RES_LPTRAP }, 1658 { "limited", RES_LIMITED }, 1659 { "version", RES_VERSION }, 1660 { "kod", RES_KOD }, 1661 { "flake", RES_FLAKE }, 1662 1663 { "", 0 } 1664 }; 1665 1666 static struct resflags resmflags[] = { 1667 { "ntpport", RESM_NTPONLY }, 1668 { "interface", RESM_INTERFACE }, 1669 { "source", RESM_SOURCE }, 1670 { "", 0 } 1671 }; 1672 1673 1674 /* 1675 * reslist - obtain and print the server's restrict list 1676 */ 1677 /*ARGSUSED*/ 1678 static void 1679 reslist( 1680 struct parse *pcmd, 1681 FILE *fp 1682 ) 1683 { 1684 struct info_restrict *rl; 1685 sockaddr_u resaddr; 1686 sockaddr_u maskaddr; 1687 size_t items; 1688 size_t itemsize; 1689 int res; 1690 int skip; 1691 const char *addr; 1692 const char *mask; 1693 struct resflags *rf; 1694 u_int32 count; 1695 u_short rflags; 1696 u_short mflags; 1697 char flagstr[300]; 1698 static const char *comma = ", "; 1699 1700 again: 1701 res = doquery(impl_ver, REQ_GET_RESTRICT, 0, 0, 0, (char *)NULL, 1702 &items, &itemsize, (void *)&rl, 0, 1703 sizeof(struct info_restrict)); 1704 1705 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1706 impl_ver = IMPL_XNTPD_OLD; 1707 goto again; 1708 } 1709 1710 if (res != 0) 1711 return; 1712 1713 if (!checkitems(items, fp)) 1714 return; 1715 1716 if (!checkitemsize(itemsize, sizeof(struct info_restrict)) && 1717 !checkitemsize(itemsize, v4sizeof(struct info_restrict))) 1718 return; 1719 1720 fprintf(fp, 1721 " address mask count flags\n"); 1722 fprintf(fp, 1723 "=====================================================================\n"); 1724 1725 while (items > 0) { 1726 SET_ADDRS(resaddr, maskaddr, rl, addr, mask); 1727 if (rl->v6_flag != 0) { 1728 addr = nntohost(&resaddr); 1729 } else { 1730 if (rl->mask == (u_int32)0xffffffff) 1731 addr = nntohost(&resaddr); 1732 else 1733 addr = stoa(&resaddr); 1734 } 1735 mask = stoa(&maskaddr); 1736 skip = 1; 1737 if ((pcmd->nargs == 0) || 1738 ((pcmd->argval->ival == 6) && (rl->v6_flag != 0)) || 1739 ((pcmd->argval->ival == 4) && (rl->v6_flag == 0))) 1740 skip = 0; 1741 count = ntohl(rl->count); 1742 rflags = ntohs(rl->rflags); 1743 mflags = ntohs(rl->mflags); 1744 flagstr[0] = '\0'; 1745 1746 res = 1; 1747 rf = &resmflags[0]; 1748 while (rf->bit != 0) { 1749 if (mflags & rf->bit) { 1750 if (!res) 1751 strlcat(flagstr, comma, 1752 sizeof(flagstr)); 1753 res = 0; 1754 strlcat(flagstr, rf->str, 1755 sizeof(flagstr)); 1756 } 1757 rf++; 1758 } 1759 1760 rf = (impl_ver == IMPL_XNTPD_OLD) 1761 ? &resflagsV2[0] 1762 : &resflagsV3[0]; 1763 1764 while (rf->bit != 0) { 1765 if (rflags & rf->bit) { 1766 if (!res) 1767 strlcat(flagstr, comma, 1768 sizeof(flagstr)); 1769 res = 0; 1770 strlcat(flagstr, rf->str, 1771 sizeof(flagstr)); 1772 } 1773 rf++; 1774 } 1775 1776 if (flagstr[0] == '\0') 1777 strlcpy(flagstr, "none", sizeof(flagstr)); 1778 1779 if (!skip) 1780 fprintf(fp, "%-15.15s %-15.15s %9lu %s\n", 1781 addr, mask, (u_long)count, flagstr); 1782 rl++; 1783 items--; 1784 } 1785 } 1786 1787 1788 1789 /* 1790 * new_restrict - create/add a set of restrictions 1791 */ 1792 static void 1793 new_restrict( 1794 struct parse *pcmd, 1795 FILE *fp 1796 ) 1797 { 1798 do_restrict(pcmd, fp, REQ_RESADDFLAGS); 1799 } 1800 1801 1802 /* 1803 * unrestrict - remove restriction flags from existing entry 1804 */ 1805 static void 1806 unrestrict( 1807 struct parse *pcmd, 1808 FILE *fp 1809 ) 1810 { 1811 do_restrict(pcmd, fp, REQ_RESSUBFLAGS); 1812 } 1813 1814 1815 /* 1816 * delrestrict - delete an existing restriction 1817 */ 1818 static void 1819 delrestrict( 1820 struct parse *pcmd, 1821 FILE *fp 1822 ) 1823 { 1824 do_restrict(pcmd, fp, REQ_UNRESTRICT); 1825 } 1826 1827 1828 /* 1829 * do_restrict - decode commandline restrictions and make the request 1830 */ 1831 static void 1832 do_restrict( 1833 struct parse *pcmd, 1834 FILE *fp, 1835 int req_code 1836 ) 1837 { 1838 struct conf_restrict cres; 1839 size_t items; 1840 size_t itemsize; 1841 const char *dummy; 1842 u_int32 num; 1843 u_long bit; 1844 int i; 1845 size_t res; 1846 int err; 1847 int sendsize; 1848 1849 /* Initialize cres */ 1850 cres.addr = 0; 1851 cres.mask = 0; 1852 cres.flags = 0; 1853 cres.mflags = 0; 1854 cres.v6_flag = 0; 1855 1856 again: 1857 if (impl_ver == IMPL_XNTPD) 1858 sendsize = sizeof(struct conf_restrict); 1859 else 1860 sendsize = v4sizeof(struct conf_restrict); 1861 1862 if (IS_IPV4(&pcmd->argval[0].netnum)) { 1863 cres.addr = NSRCADR(&pcmd->argval[0].netnum); 1864 cres.mask = NSRCADR(&pcmd->argval[1].netnum); 1865 if (impl_ver == IMPL_XNTPD) 1866 cres.v6_flag = 0; 1867 } else { 1868 if (impl_ver == IMPL_XNTPD_OLD) { 1869 fprintf(stderr, 1870 "***Server doesn't understand IPv6 addresses\n"); 1871 return; 1872 } 1873 cres.addr6 = SOCK_ADDR6(&pcmd->argval[0].netnum); 1874 cres.v6_flag = 1; 1875 } 1876 cres.flags = 0; 1877 cres.mflags = 0; 1878 err = FALSE; 1879 for (res = 2; res < pcmd->nargs; res++) { 1880 if (STREQ(pcmd->argval[res].string, "ntpport")) { 1881 cres.mflags |= RESM_NTPONLY; 1882 } else { 1883 for (i = 0; resflagsV3[i].bit != 0; i++) { 1884 if (STREQ(pcmd->argval[res].string, 1885 resflagsV3[i].str)) 1886 break; 1887 } 1888 if (resflagsV3[i].bit != 0) { 1889 cres.flags |= resflagsV3[i].bit; 1890 if (req_code == REQ_UNRESTRICT) { 1891 fprintf(fp, 1892 "Flag %s inappropriate\n", 1893 resflagsV3[i].str); 1894 err = TRUE; 1895 } 1896 } else { 1897 fprintf(fp, "Unknown flag %s\n", 1898 pcmd->argval[res].string); 1899 err = TRUE; 1900 } 1901 } 1902 } 1903 cres.flags = htons(cres.flags); 1904 cres.mflags = htons(cres.mflags); 1905 1906 /* 1907 * Make sure mask for default address is zero. Otherwise, 1908 * make sure mask bits are contiguous. 1909 */ 1910 if (IS_IPV4(&pcmd->argval[0].netnum)) { 1911 if (cres.addr == 0) { 1912 cres.mask = 0; 1913 } else { 1914 num = ntohl(cres.mask); 1915 for (bit = 0x80000000; bit != 0; bit >>= 1) 1916 if ((num & bit) == 0) 1917 break; 1918 for ( ; bit != 0; bit >>= 1) 1919 if ((num & bit) != 0) 1920 break; 1921 if (bit != 0) { 1922 fprintf(fp, "Invalid mask %s\n", 1923 numtoa(cres.mask)); 1924 err = TRUE; 1925 } 1926 } 1927 } else { 1928 /* XXX IPv6 sanity checking stuff */ 1929 } 1930 1931 if (err) 1932 return; 1933 1934 res = doquery(impl_ver, req_code, 1, 1, sendsize, (char *)&cres, 1935 &items, &itemsize, &dummy, 0, sizeof(cres)); 1936 1937 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1938 impl_ver = IMPL_XNTPD_OLD; 1939 goto again; 1940 } 1941 1942 if (res == 0) 1943 (void) fprintf(fp, "done!\n"); 1944 return; 1945 } 1946 1947 1948 /* 1949 * monlist - obtain and print the server's monitor data 1950 */ 1951 /*ARGSUSED*/ 1952 static void 1953 monlist( 1954 struct parse *pcmd, 1955 FILE *fp 1956 ) 1957 { 1958 const char *struct_star; 1959 const struct info_monitor *ml; 1960 const struct info_monitor_1 *m1; 1961 const struct old_info_monitor *oml; 1962 sockaddr_u addr; 1963 sockaddr_u dstadr; 1964 size_t items; 1965 size_t itemsize; 1966 int res; 1967 int version = -1; 1968 1969 if (pcmd->nargs > 0) 1970 version = pcmd->argval[0].ival; 1971 1972 again: 1973 res = doquery(impl_ver, 1974 (version == 1 || version == -1) ? REQ_MON_GETLIST_1 : 1975 REQ_MON_GETLIST, 0, 0, 0, NULL, 1976 &items, &itemsize, &struct_star, 1977 (version < 0) ? (1 << INFO_ERR_REQ) : 0, 1978 sizeof(struct info_monitor_1)); 1979 1980 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1981 impl_ver = IMPL_XNTPD_OLD; 1982 goto again; 1983 } 1984 1985 if (res == INFO_ERR_REQ && version < 0) 1986 res = doquery(impl_ver, REQ_MON_GETLIST, 0, 0, 0, NULL, 1987 &items, &itemsize, &struct_star, 0, 1988 sizeof(struct info_monitor)); 1989 1990 if (res != 0) 1991 return; 1992 1993 if (!checkitems(items, fp)) 1994 return; 1995 1996 if (itemsize == sizeof(struct info_monitor_1) || 1997 itemsize == v4sizeof(struct info_monitor_1)) { 1998 1999 m1 = (const void*)struct_star; 2000 fprintf(fp, 2001 "remote address port local address count m ver rstr avgint lstint\n"); 2002 fprintf(fp, 2003 "===============================================================================\n"); 2004 while (items > 0) { 2005 SET_ADDRS(dstadr, addr, m1, daddr, addr); 2006 if ((pcmd->nargs == 0) || 2007 ((pcmd->argval->ival == 6) && (m1->v6_flag != 0)) || 2008 ((pcmd->argval->ival == 4) && (m1->v6_flag == 0))) 2009 fprintf(fp, 2010 "%-22.22s %5d %-15s %8lu %1u %1u %6lx %6lu %7lu\n", 2011 nntohost(&addr), 2012 ntohs(m1->port), 2013 stoa(&dstadr), 2014 (u_long)ntohl(m1->count), 2015 m1->mode, 2016 m1->version, 2017 (u_long)ntohl(m1->restr), 2018 (u_long)ntohl(m1->avg_int), 2019 (u_long)ntohl(m1->last_int)); 2020 m1++; 2021 items--; 2022 } 2023 } else if (itemsize == sizeof(struct info_monitor) || 2024 itemsize == v4sizeof(struct info_monitor)) { 2025 2026 ml = (const void *)struct_star; 2027 fprintf(fp, 2028 " address port count mode ver rstr avgint lstint\n"); 2029 fprintf(fp, 2030 "===============================================================================\n"); 2031 while (items > 0) { 2032 SET_ADDR(dstadr, ml->v6_flag, ml->addr, ml->addr6); 2033 if ((pcmd->nargs == 0) || 2034 ((pcmd->argval->ival == 6) && (ml->v6_flag != 0)) || 2035 ((pcmd->argval->ival == 4) && (ml->v6_flag == 0))) 2036 fprintf(fp, 2037 "%-25.25s %5u %9lu %4u %2u %9lx %9lu %9lu\n", 2038 nntohost(&dstadr), 2039 ntohs(ml->port), 2040 (u_long)ntohl(ml->count), 2041 ml->mode, 2042 ml->version, 2043 (u_long)ntohl(ml->restr), 2044 (u_long)ntohl(ml->avg_int), 2045 (u_long)ntohl(ml->last_int)); 2046 ml++; 2047 items--; 2048 } 2049 } else if (itemsize == sizeof(struct old_info_monitor)) { 2050 2051 oml = (const void *)struct_star; 2052 fprintf(fp, 2053 " address port count mode version lasttime firsttime\n"); 2054 fprintf(fp, 2055 "======================================================================\n"); 2056 while (items > 0) { 2057 SET_ADDR(dstadr, oml->v6_flag, oml->addr, oml->addr6); 2058 fprintf(fp, "%-20.20s %5u %9lu %4u %3u %9lu %9lu\n", 2059 nntohost(&dstadr), 2060 ntohs(oml->port), 2061 (u_long)ntohl(oml->count), 2062 oml->mode, 2063 oml->version, 2064 (u_long)ntohl(oml->lasttime), 2065 (u_long)ntohl(oml->firsttime)); 2066 oml++; 2067 items--; 2068 } 2069 } else { 2070 /* issue warning according to new info_monitor size */ 2071 checkitemsize(itemsize, sizeof(struct info_monitor)); 2072 } 2073 } 2074 2075 2076 /* 2077 * Mapping between command line strings and stat reset flags 2078 */ 2079 struct statreset { 2080 const char * const str; 2081 const int flag; 2082 } sreset[] = { 2083 { "allpeers", RESET_FLAG_ALLPEERS }, 2084 { "io", RESET_FLAG_IO }, 2085 { "sys", RESET_FLAG_SYS }, 2086 { "mem", RESET_FLAG_MEM }, 2087 { "timer", RESET_FLAG_TIMER }, 2088 { "auth", RESET_FLAG_AUTH }, 2089 { "ctl", RESET_FLAG_CTL }, 2090 { "", 0 } 2091 }; 2092 2093 /* 2094 * reset - reset statistic counters 2095 */ 2096 static void 2097 reset( 2098 struct parse *pcmd, 2099 FILE *fp 2100 ) 2101 { 2102 struct reset_flags rflags; 2103 size_t items; 2104 size_t itemsize; 2105 const char *dummy; 2106 int i; 2107 size_t res; 2108 int err; 2109 2110 err = 0; 2111 rflags.flags = 0; 2112 for (res = 0; res < pcmd->nargs; res++) { 2113 for (i = 0; sreset[i].flag != 0; i++) { 2114 if (STREQ(pcmd->argval[res].string, sreset[i].str)) 2115 break; 2116 } 2117 if (sreset[i].flag == 0) { 2118 fprintf(fp, "Flag %s unknown\n", 2119 pcmd->argval[res].string); 2120 err = 1; 2121 } else { 2122 rflags.flags |= sreset[i].flag; 2123 } 2124 } 2125 rflags.flags = htonl(rflags.flags); 2126 2127 if (err) { 2128 (void) fprintf(fp, "Not done due to errors\n"); 2129 return; 2130 } 2131 2132 again: 2133 res = doquery(impl_ver, REQ_RESET_STATS, 1, 1, 2134 sizeof(struct reset_flags), (char *)&rflags, &items, 2135 &itemsize, &dummy, 0, sizeof(struct reset_flags)); 2136 2137 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2138 impl_ver = IMPL_XNTPD_OLD; 2139 goto again; 2140 } 2141 2142 if (res == 0) 2143 (void) fprintf(fp, "done!\n"); 2144 return; 2145 } 2146 2147 2148 2149 /* 2150 * preset - reset stat counters for particular peers 2151 */ 2152 static void 2153 preset( 2154 struct parse *pcmd, 2155 FILE *fp 2156 ) 2157 { 2158 /* 8 is the maximum number of peers which will fit in a packet */ 2159 struct conf_unpeer *pl, plist[min(MAXARGS, 8)]; 2160 size_t qitemlim; 2161 size_t qitems; 2162 size_t items; 2163 size_t itemsize; 2164 const char *dummy; 2165 int res; 2166 size_t sendsize; 2167 2168 again: 2169 if (impl_ver == IMPL_XNTPD) 2170 sendsize = sizeof(struct conf_unpeer); 2171 else 2172 sendsize = v4sizeof(struct conf_unpeer); 2173 2174 qitemlim = min(pcmd->nargs, COUNTOF(plist)); 2175 for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) { 2176 if (IS_IPV4(&pcmd->argval[qitems].netnum)) { 2177 pl->peeraddr = NSRCADR(&pcmd->argval[qitems].netnum); 2178 if (impl_ver == IMPL_XNTPD) 2179 pl->v6_flag = 0; 2180 } else { 2181 if (impl_ver == IMPL_XNTPD_OLD) { 2182 fprintf(stderr, 2183 "***Server doesn't understand IPv6 addresses\n"); 2184 return; 2185 } 2186 pl->peeraddr6 = 2187 SOCK_ADDR6(&pcmd->argval[qitems].netnum); 2188 pl->v6_flag = 1; 2189 } 2190 pl = (void *)((char *)pl + sendsize); 2191 } 2192 2193 res = doquery(impl_ver, REQ_RESET_PEER, 1, qitems, 2194 sendsize, (char *)plist, &items, 2195 &itemsize, &dummy, 0, sizeof(struct conf_unpeer)); 2196 2197 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2198 impl_ver = IMPL_XNTPD_OLD; 2199 goto again; 2200 } 2201 2202 if (res == 0) 2203 (void) fprintf(fp, "done!\n"); 2204 } 2205 2206 2207 /* 2208 * readkeys - request the server to reread the keys file 2209 */ 2210 /*ARGSUSED*/ 2211 static void 2212 readkeys( 2213 struct parse *pcmd, 2214 FILE *fp 2215 ) 2216 { 2217 size_t items; 2218 size_t itemsize; 2219 const char *dummy; 2220 int res; 2221 2222 again: 2223 res = doquery(impl_ver, REQ_REREAD_KEYS, 1, 0, 0, (char *)0, 2224 &items, &itemsize, &dummy, 0, sizeof(dummy)); 2225 2226 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2227 impl_ver = IMPL_XNTPD_OLD; 2228 goto again; 2229 } 2230 2231 if (res == 0) 2232 (void) fprintf(fp, "done!\n"); 2233 return; 2234 } 2235 2236 2237 /* 2238 * trustkey - add some keys to the trusted key list 2239 */ 2240 static void 2241 trustkey( 2242 struct parse *pcmd, 2243 FILE *fp 2244 ) 2245 { 2246 do_trustkey(pcmd, fp, REQ_TRUSTKEY); 2247 } 2248 2249 2250 /* 2251 * untrustkey - remove some keys from the trusted key list 2252 */ 2253 static void 2254 untrustkey( 2255 struct parse *pcmd, 2256 FILE *fp 2257 ) 2258 { 2259 do_trustkey(pcmd, fp, REQ_UNTRUSTKEY); 2260 } 2261 2262 2263 /* 2264 * do_trustkey - do grunge work of adding/deleting keys 2265 */ 2266 static void 2267 do_trustkey( 2268 struct parse *pcmd, 2269 FILE *fp, 2270 int req 2271 ) 2272 { 2273 u_long keyids[MAXARGS]; 2274 size_t i; 2275 size_t items; 2276 size_t itemsize; 2277 const char *dummy; 2278 int ritems; 2279 int res; 2280 2281 ritems = 0; 2282 for (i = 0; i < pcmd->nargs; i++) { 2283 keyids[ritems++] = pcmd->argval[i].uval; 2284 } 2285 2286 again: 2287 res = doquery(impl_ver, req, 1, ritems, sizeof(u_long), 2288 (char *)keyids, &items, &itemsize, &dummy, 0, 2289 sizeof(dummy)); 2290 2291 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2292 impl_ver = IMPL_XNTPD_OLD; 2293 goto again; 2294 } 2295 2296 if (res == 0) 2297 (void) fprintf(fp, "done!\n"); 2298 return; 2299 } 2300 2301 2302 2303 /* 2304 * authinfo - obtain and print info about authentication 2305 */ 2306 /*ARGSUSED*/ 2307 static void 2308 authinfo( 2309 struct parse *pcmd, 2310 FILE *fp 2311 ) 2312 { 2313 struct info_auth *ia; 2314 size_t items; 2315 size_t itemsize; 2316 int res; 2317 2318 again: 2319 res = doquery(impl_ver, REQ_AUTHINFO, 0, 0, 0, NULL, &items, 2320 &itemsize, (void *)&ia, 0, sizeof(*ia)); 2321 2322 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2323 impl_ver = IMPL_XNTPD_OLD; 2324 goto again; 2325 } 2326 2327 if (res != 0) 2328 return; 2329 2330 if (!check1item(items, fp)) 2331 return; 2332 2333 if (!checkitemsize(itemsize, sizeof(*ia))) 2334 return; 2335 2336 fprintf(fp, "time since reset: %lu\n", 2337 (u_long)ntohl(ia->timereset)); 2338 fprintf(fp, "stored keys: %lu\n", 2339 (u_long)ntohl(ia->numkeys)); 2340 fprintf(fp, "free keys: %lu\n", 2341 (u_long)ntohl(ia->numfreekeys)); 2342 fprintf(fp, "key lookups: %lu\n", 2343 (u_long)ntohl(ia->keylookups)); 2344 fprintf(fp, "keys not found: %lu\n", 2345 (u_long)ntohl(ia->keynotfound)); 2346 fprintf(fp, "uncached keys: %lu\n", 2347 (u_long)ntohl(ia->keyuncached)); 2348 fprintf(fp, "encryptions: %lu\n", 2349 (u_long)ntohl(ia->encryptions)); 2350 fprintf(fp, "decryptions: %lu\n", 2351 (u_long)ntohl(ia->decryptions)); 2352 fprintf(fp, "expired keys: %lu\n", 2353 (u_long)ntohl(ia->expired)); 2354 } 2355 2356 2357 2358 /* 2359 * traps - obtain and print a list of traps 2360 */ 2361 /*ARGSUSED*/ 2362 static void 2363 traps( 2364 struct parse *pcmd, 2365 FILE *fp 2366 ) 2367 { 2368 size_t i; 2369 struct info_trap *it; 2370 sockaddr_u trap_addr, local_addr; 2371 size_t items; 2372 size_t itemsize; 2373 int res; 2374 2375 again: 2376 res = doquery(impl_ver, REQ_TRAPS, 0, 0, 0, NULL, &items, 2377 &itemsize, (void *)&it, 0, sizeof(*it)); 2378 2379 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2380 impl_ver = IMPL_XNTPD_OLD; 2381 goto again; 2382 } 2383 2384 if (res != 0) 2385 return; 2386 2387 if (!checkitems(items, fp)) 2388 return; 2389 2390 if (!checkitemsize(itemsize, sizeof(struct info_trap)) && 2391 !checkitemsize(itemsize, v4sizeof(struct info_trap))) 2392 return; 2393 2394 for (i = 0; i < items; i++ ) { 2395 SET_ADDRS(trap_addr, local_addr, it, trap_address, local_address); 2396 fprintf(fp, "%saddress %s, port %d\n", 2397 (0 == i) 2398 ? "" 2399 : "\n", 2400 stoa(&trap_addr), ntohs(it->trap_port)); 2401 fprintf(fp, "interface: %s, ", 2402 (0 == it->local_address) 2403 ? "wildcard" 2404 : stoa(&local_addr)); 2405 if (ntohl(it->flags) & TRAP_CONFIGURED) 2406 fprintf(fp, "configured\n"); 2407 else if (ntohl(it->flags) & TRAP_NONPRIO) 2408 fprintf(fp, "low priority\n"); 2409 else 2410 fprintf(fp, "normal priority\n"); 2411 2412 fprintf(fp, "set for %ld secs, last set %ld secs ago\n", 2413 (long)ntohl(it->origtime), 2414 (long)ntohl(it->settime)); 2415 fprintf(fp, "sequence %d, number of resets %ld\n", 2416 ntohs(it->sequence), (long)ntohl(it->resets)); 2417 } 2418 } 2419 2420 2421 /* 2422 * addtrap - configure a trap 2423 */ 2424 static void 2425 addtrap( 2426 struct parse *pcmd, 2427 FILE *fp 2428 ) 2429 { 2430 do_addclr_trap(pcmd, fp, REQ_ADD_TRAP); 2431 } 2432 2433 2434 /* 2435 * clrtrap - clear a trap from the server 2436 */ 2437 static void 2438 clrtrap( 2439 struct parse *pcmd, 2440 FILE *fp 2441 ) 2442 { 2443 do_addclr_trap(pcmd, fp, REQ_CLR_TRAP); 2444 } 2445 2446 2447 /* 2448 * do_addclr_trap - do grunge work of adding/deleting traps 2449 */ 2450 static void 2451 do_addclr_trap( 2452 struct parse *pcmd, 2453 FILE *fp, 2454 int req 2455 ) 2456 { 2457 struct conf_trap ctrap; 2458 size_t items; 2459 size_t itemsize; 2460 const char *dummy; 2461 int res; 2462 int sendsize; 2463 2464 again: 2465 if (impl_ver == IMPL_XNTPD) 2466 sendsize = sizeof(struct conf_trap); 2467 else 2468 sendsize = v4sizeof(struct conf_trap); 2469 2470 if (IS_IPV4(&pcmd->argval[0].netnum)) { 2471 ctrap.trap_address = NSRCADR(&pcmd->argval[0].netnum); 2472 if (impl_ver == IMPL_XNTPD) 2473 ctrap.v6_flag = 0; 2474 } else { 2475 if (impl_ver == IMPL_XNTPD_OLD) { 2476 fprintf(stderr, 2477 "***Server doesn't understand IPv6 addresses\n"); 2478 return; 2479 } 2480 ctrap.trap_address6 = SOCK_ADDR6(&pcmd->argval[0].netnum); 2481 ctrap.v6_flag = 1; 2482 } 2483 ctrap.local_address = 0; 2484 ctrap.trap_port = htons(TRAPPORT); 2485 ctrap.unused = 0; 2486 2487 if (pcmd->nargs > 1) { 2488 ctrap.trap_port = htons((u_short)pcmd->argval[1].uval); 2489 if (pcmd->nargs > 2) { 2490 if (AF(&pcmd->argval[2].netnum) != 2491 AF(&pcmd->argval[0].netnum)) { 2492 fprintf(stderr, 2493 "***Cannot mix IPv4 and IPv6 addresses\n"); 2494 return; 2495 } 2496 if (IS_IPV4(&pcmd->argval[2].netnum)) 2497 ctrap.local_address = NSRCADR(&pcmd->argval[2].netnum); 2498 else 2499 ctrap.local_address6 = SOCK_ADDR6(&pcmd->argval[2].netnum); 2500 } 2501 } 2502 2503 res = doquery(impl_ver, req, 1, 1, sendsize, 2504 (char *)&ctrap, &items, &itemsize, &dummy, 0, 2505 sizeof(struct conf_trap)); 2506 2507 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2508 impl_ver = IMPL_XNTPD_OLD; 2509 goto again; 2510 } 2511 2512 if (res == 0) 2513 (void) fprintf(fp, "done!\n"); 2514 return; 2515 } 2516 2517 2518 2519 /* 2520 * requestkey - change the server's request key (a dangerous request) 2521 */ 2522 static void 2523 requestkey( 2524 struct parse *pcmd, 2525 FILE *fp 2526 ) 2527 { 2528 do_changekey(pcmd, fp, REQ_REQUEST_KEY); 2529 } 2530 2531 2532 /* 2533 * controlkey - change the server's control key 2534 */ 2535 static void 2536 controlkey( 2537 struct parse *pcmd, 2538 FILE *fp 2539 ) 2540 { 2541 do_changekey(pcmd, fp, REQ_CONTROL_KEY); 2542 } 2543 2544 2545 2546 /* 2547 * do_changekey - do grunge work of changing keys 2548 */ 2549 static void 2550 do_changekey( 2551 struct parse *pcmd, 2552 FILE *fp, 2553 int req 2554 ) 2555 { 2556 u_long key; 2557 size_t items; 2558 size_t itemsize; 2559 const char *dummy; 2560 int res; 2561 2562 2563 key = htonl((u_int32)pcmd->argval[0].uval); 2564 2565 again: 2566 res = doquery(impl_ver, req, 1, 1, sizeof(u_int32), 2567 (char *)&key, &items, &itemsize, &dummy, 0, 2568 sizeof(dummy)); 2569 2570 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2571 impl_ver = IMPL_XNTPD_OLD; 2572 goto again; 2573 } 2574 2575 if (res == 0) 2576 (void) fprintf(fp, "done!\n"); 2577 return; 2578 } 2579 2580 2581 2582 /* 2583 * ctlstats - obtain and print info about authentication 2584 */ 2585 /*ARGSUSED*/ 2586 static void 2587 ctlstats( 2588 struct parse *pcmd, 2589 FILE *fp 2590 ) 2591 { 2592 struct info_control *ic; 2593 size_t items; 2594 size_t itemsize; 2595 int res; 2596 2597 again: 2598 res = doquery(impl_ver, REQ_GET_CTLSTATS, 0, 0, 0, NULL, &items, 2599 &itemsize, (void *)&ic, 0, sizeof(*ic)); 2600 2601 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2602 impl_ver = IMPL_XNTPD_OLD; 2603 goto again; 2604 } 2605 2606 if (res != 0) 2607 return; 2608 2609 if (!check1item(items, fp)) 2610 return; 2611 2612 if (!checkitemsize(itemsize, sizeof(*ic))) 2613 return; 2614 2615 fprintf(fp, "time since reset: %lu\n", 2616 (u_long)ntohl(ic->ctltimereset)); 2617 fprintf(fp, "requests received: %lu\n", 2618 (u_long)ntohl(ic->numctlreq)); 2619 fprintf(fp, "responses sent: %lu\n", 2620 (u_long)ntohl(ic->numctlresponses)); 2621 fprintf(fp, "fragments sent: %lu\n", 2622 (u_long)ntohl(ic->numctlfrags)); 2623 fprintf(fp, "async messages sent: %lu\n", 2624 (u_long)ntohl(ic->numasyncmsgs)); 2625 fprintf(fp, "error msgs sent: %lu\n", 2626 (u_long)ntohl(ic->numctlerrors)); 2627 fprintf(fp, "total bad pkts: %lu\n", 2628 (u_long)ntohl(ic->numctlbadpkts)); 2629 fprintf(fp, "packet too short: %lu\n", 2630 (u_long)ntohl(ic->numctltooshort)); 2631 fprintf(fp, "response on input: %lu\n", 2632 (u_long)ntohl(ic->numctlinputresp)); 2633 fprintf(fp, "fragment on input: %lu\n", 2634 (u_long)ntohl(ic->numctlinputfrag)); 2635 fprintf(fp, "error set on input: %lu\n", 2636 (u_long)ntohl(ic->numctlinputerr)); 2637 fprintf(fp, "bad offset on input: %lu\n", 2638 (u_long)ntohl(ic->numctlbadoffset)); 2639 fprintf(fp, "bad version packets: %lu\n", 2640 (u_long)ntohl(ic->numctlbadversion)); 2641 fprintf(fp, "data in pkt too short: %lu\n", 2642 (u_long)ntohl(ic->numctldatatooshort)); 2643 fprintf(fp, "unknown op codes: %lu\n", 2644 (u_long)ntohl(ic->numctlbadop)); 2645 } 2646 2647 2648 /* 2649 * clockstat - get and print clock status information 2650 */ 2651 static void 2652 clockstat( 2653 struct parse *pcmd, 2654 FILE *fp 2655 ) 2656 { 2657 struct info_clock *cl; 2658 /* 8 is the maximum number of clocks which will fit in a packet */ 2659 u_long clist[min(MAXARGS, 8)]; 2660 size_t qitemlim; 2661 size_t qitems; 2662 size_t items; 2663 size_t itemsize; 2664 int res; 2665 l_fp ts; 2666 struct clktype *clk; 2667 2668 qitemlim = min(pcmd->nargs, COUNTOF(clist)); 2669 for (qitems = 0; qitems < qitemlim; qitems++) 2670 clist[qitems] = NSRCADR(&pcmd->argval[qitems].netnum); 2671 2672 again: 2673 res = doquery(impl_ver, REQ_GET_CLOCKINFO, 0, qitems, 2674 sizeof(u_int32), (char *)clist, &items, 2675 &itemsize, (void *)&cl, 0, sizeof(struct info_clock)); 2676 2677 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2678 impl_ver = IMPL_XNTPD_OLD; 2679 goto again; 2680 } 2681 2682 if (res != 0) 2683 return; 2684 2685 if (!checkitems(items, fp)) 2686 return; 2687 2688 if (!checkitemsize(itemsize, sizeof(struct info_clock))) 2689 return; 2690 2691 while (items-- > 0) { 2692 (void) fprintf(fp, "clock address: %s\n", 2693 numtoa(cl->clockadr)); 2694 for (clk = clktypes; clk->code >= 0; clk++) 2695 if (clk->code == cl->type) 2696 break; 2697 if (clk->code >= 0) 2698 (void) fprintf(fp, "clock type: %s\n", 2699 clk->clocktype); 2700 else 2701 (void) fprintf(fp, "clock type: unknown type (%d)\n", 2702 cl->type); 2703 (void) fprintf(fp, "last event: %d\n", 2704 cl->lastevent); 2705 (void) fprintf(fp, "current status: %d\n", 2706 cl->currentstatus); 2707 (void) fprintf(fp, "number of polls: %lu\n", 2708 (u_long)ntohl(cl->polls)); 2709 (void) fprintf(fp, "no response to poll: %lu\n", 2710 (u_long)ntohl(cl->noresponse)); 2711 (void) fprintf(fp, "bad format responses: %lu\n", 2712 (u_long)ntohl(cl->badformat)); 2713 (void) fprintf(fp, "bad data responses: %lu\n", 2714 (u_long)ntohl(cl->baddata)); 2715 (void) fprintf(fp, "running time: %lu\n", 2716 (u_long)ntohl(cl->timestarted)); 2717 NTOHL_FP(&cl->fudgetime1, &ts); 2718 (void) fprintf(fp, "fudge time 1: %s\n", 2719 lfptoa(&ts, 6)); 2720 NTOHL_FP(&cl->fudgetime2, &ts); 2721 (void) fprintf(fp, "fudge time 2: %s\n", 2722 lfptoa(&ts, 6)); 2723 (void) fprintf(fp, "stratum: %ld\n", 2724 (u_long)ntohl(cl->fudgeval1)); 2725 /* [Bug3527] Backward Incompatible: cl->fudgeval2 is 2726 * a string, instantiated via memcpy() so there is no 2727 * endian issue to correct. 2728 */ 2729 #ifdef DISABLE_BUG3527_FIX 2730 (void) fprintf(fp, "reference ID: %s\n", 2731 refid_string(ntohl(cl->fudgeval2), 0)); 2732 #else 2733 (void) fprintf(fp, "reference ID: %s\n", 2734 refid_string(cl->fudgeval2, 0)); 2735 #endif 2736 (void) fprintf(fp, "fudge flags: 0x%x\n", 2737 cl->flags); 2738 2739 if (items > 0) 2740 (void) fprintf(fp, "\n"); 2741 cl++; 2742 } 2743 } 2744 2745 2746 /* 2747 * fudge - set clock fudge factors 2748 */ 2749 static void 2750 fudge( 2751 struct parse *pcmd, 2752 FILE *fp 2753 ) 2754 { 2755 struct conf_fudge fudgedata; 2756 size_t items; 2757 size_t itemsize; 2758 const char *dummy; 2759 l_fp ts; 2760 int res; 2761 long val; 2762 u_long u_val; 2763 int err; 2764 2765 2766 err = 0; 2767 ZERO(fudgedata); 2768 fudgedata.clockadr = NSRCADR(&pcmd->argval[0].netnum); 2769 2770 if (STREQ(pcmd->argval[1].string, "time1")) { 2771 fudgedata.which = htonl(FUDGE_TIME1); 2772 if (!atolfp(pcmd->argval[2].string, &ts)) 2773 err = 1; 2774 else 2775 NTOHL_FP(&ts, &fudgedata.fudgetime); 2776 } else if (STREQ(pcmd->argval[1].string, "time2")) { 2777 fudgedata.which = htonl(FUDGE_TIME2); 2778 if (!atolfp(pcmd->argval[2].string, &ts)) 2779 err = 1; 2780 else 2781 NTOHL_FP(&ts, &fudgedata.fudgetime); 2782 } else if (STREQ(pcmd->argval[1].string, "val1")) { 2783 fudgedata.which = htonl(FUDGE_VAL1); 2784 if (!atoint(pcmd->argval[2].string, &val)) 2785 err = 1; 2786 else 2787 fudgedata.fudgeval_flags = htonl(val); 2788 } else if (STREQ(pcmd->argval[1].string, "val2")) { 2789 fudgedata.which = htonl(FUDGE_VAL2); 2790 if (!atoint(pcmd->argval[2].string, &val)) 2791 err = 1; 2792 else 2793 fudgedata.fudgeval_flags = htonl((u_int32)val); 2794 } else if (STREQ(pcmd->argval[1].string, "flags")) { 2795 fudgedata.which = htonl(FUDGE_FLAGS); 2796 if (!hextoint(pcmd->argval[2].string, &u_val)) 2797 err = 1; 2798 else 2799 fudgedata.fudgeval_flags = htonl((u_int32)(u_val & 0xf)); 2800 } else { 2801 (void) fprintf(stderr, "What fudge is %s?\n", 2802 pcmd->argval[1].string); 2803 return; 2804 } 2805 2806 if (err) { 2807 (void) fprintf(stderr, "Unknown fudge parameter %s\n", 2808 pcmd->argval[2].string); 2809 return; 2810 } 2811 2812 again: 2813 res = doquery(impl_ver, REQ_SET_CLKFUDGE, 1, 1, 2814 sizeof(struct conf_fudge), (char *)&fudgedata, &items, 2815 &itemsize, &dummy, 0, sizeof(dummy)); 2816 2817 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2818 impl_ver = IMPL_XNTPD_OLD; 2819 goto again; 2820 } 2821 2822 if (res == 0) 2823 (void) fprintf(fp, "done!\n"); 2824 return; 2825 } 2826 2827 /* 2828 * clkbug - get and print clock debugging information 2829 */ 2830 static void 2831 clkbug( 2832 struct parse *pcmd, 2833 FILE *fp 2834 ) 2835 { 2836 register int i; 2837 register int n; 2838 register u_int32 s; 2839 struct info_clkbug *cl; 2840 /* 8 is the maximum number of clocks which will fit in a packet */ 2841 u_long clist[min(MAXARGS, 8)]; 2842 u_int32 ltemp; 2843 size_t qitemlim; 2844 size_t qitems; 2845 size_t items; 2846 size_t itemsize; 2847 int res; 2848 int needsp; 2849 l_fp ts; 2850 2851 qitemlim = min(pcmd->nargs, COUNTOF(clist)); 2852 for (qitems = 0; qitems < qitemlim; qitems++) 2853 clist[qitems] = NSRCADR(&pcmd->argval[qitems].netnum); 2854 2855 again: 2856 res = doquery(impl_ver, REQ_GET_CLKBUGINFO, 0, qitems, 2857 sizeof(u_int32), (char *)clist, &items, 2858 &itemsize, (void *)&cl, 0, sizeof(struct info_clkbug)); 2859 2860 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2861 impl_ver = IMPL_XNTPD_OLD; 2862 goto again; 2863 } 2864 2865 if (res != 0) 2866 return; 2867 2868 if (!checkitems(items, fp)) 2869 return; 2870 2871 if (!checkitemsize(itemsize, sizeof(struct info_clkbug))) 2872 return; 2873 2874 while (items-- > 0) { 2875 (void) fprintf(fp, "clock address: %s\n", 2876 numtoa(cl->clockadr)); 2877 n = (int)cl->nvalues; 2878 (void) fprintf(fp, "values: %d", n); 2879 s = ntohs(cl->svalues); 2880 if (n > NUMCBUGVALUES) 2881 n = NUMCBUGVALUES; 2882 for (i = 0; i < n; i++) { 2883 ltemp = ntohl(cl->values[i]); 2884 ltemp &= 0xffffffff; /* HMS: This does nothing now */ 2885 if ((i & 0x3) == 0) 2886 (void) fprintf(fp, "\n"); 2887 if (s & (1 << i)) 2888 (void) fprintf(fp, "%12ld", (u_long)ltemp); 2889 else 2890 (void) fprintf(fp, "%12lu", (u_long)ltemp); 2891 } 2892 (void) fprintf(fp, "\n"); 2893 2894 n = (int)cl->ntimes; 2895 (void) fprintf(fp, "times: %d", n); 2896 s = ntohl(cl->stimes); 2897 if (n > NUMCBUGTIMES) 2898 n = NUMCBUGTIMES; 2899 needsp = 0; 2900 for (i = 0; i < n; i++) { 2901 if ((i & 0x1) == 0) { 2902 (void) fprintf(fp, "\n"); 2903 } else { 2904 for (;needsp > 0; needsp--) 2905 putc(' ', fp); 2906 } 2907 NTOHL_FP(&cl->times[i], &ts); 2908 if (s & (1 << i)) { 2909 (void) fprintf(fp, "%17s", 2910 lfptoa(&ts, 6)); 2911 needsp = 22; 2912 } else { 2913 (void) fprintf(fp, "%37s", 2914 uglydate(&ts)); 2915 needsp = 2; 2916 } 2917 } 2918 (void) fprintf(fp, "\n"); 2919 if (items > 0) { 2920 cl++; 2921 (void) fprintf(fp, "\n"); 2922 } 2923 } 2924 } 2925 2926 2927 /* 2928 * kerninfo - display the kernel pll/pps variables 2929 */ 2930 static void 2931 kerninfo( 2932 struct parse *pcmd, 2933 FILE *fp 2934 ) 2935 { 2936 struct info_kernel *ik; 2937 size_t items; 2938 size_t itemsize; 2939 int res; 2940 unsigned status; 2941 double tscale_usec = 1e-6, tscale_unano = 1e-6; 2942 2943 again: 2944 res = doquery(impl_ver, REQ_GET_KERNEL, 0, 0, 0, (char *)NULL, 2945 &items, &itemsize, (void *)&ik, 0, 2946 sizeof(struct info_kernel)); 2947 2948 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2949 impl_ver = IMPL_XNTPD_OLD; 2950 goto again; 2951 } 2952 2953 if (res != 0) 2954 return; 2955 if (!check1item(items, fp)) 2956 return; 2957 if (!checkitemsize(itemsize, sizeof(struct info_kernel))) 2958 return; 2959 2960 status = ntohs(ik->status) & 0xffff; 2961 /* 2962 * pll variables. We know more than we should about the NANO bit. 2963 */ 2964 #ifdef STA_NANO 2965 if (status & STA_NANO) 2966 tscale_unano = 1e-9; 2967 #endif 2968 (void)fprintf(fp, "pll offset: %g s\n", 2969 (int32)ntohl(ik->offset) * tscale_unano); 2970 (void)fprintf(fp, "pll frequency: %s ppm\n", 2971 fptoa((s_fp)ntohl(ik->freq), 3)); 2972 (void)fprintf(fp, "maximum error: %g s\n", 2973 (u_long)ntohl(ik->maxerror) * tscale_usec); 2974 (void)fprintf(fp, "estimated error: %g s\n", 2975 (u_long)ntohl(ik->esterror) * tscale_usec); 2976 (void)fprintf(fp, "status: %04x ", status); 2977 #ifdef STA_PLL 2978 if (status & STA_PLL) (void)fprintf(fp, " pll"); 2979 #endif 2980 #ifdef STA_PPSFREQ 2981 if (status & STA_PPSFREQ) (void)fprintf(fp, " ppsfreq"); 2982 #endif 2983 #ifdef STA_PPSTIME 2984 if (status & STA_PPSTIME) (void)fprintf(fp, " ppstime"); 2985 #endif 2986 #ifdef STA_FLL 2987 if (status & STA_FLL) (void)fprintf(fp, " fll"); 2988 #endif 2989 #ifdef STA_INS 2990 if (status & STA_INS) (void)fprintf(fp, " ins"); 2991 #endif 2992 #ifdef STA_DEL 2993 if (status & STA_DEL) (void)fprintf(fp, " del"); 2994 #endif 2995 #ifdef STA_UNSYNC 2996 if (status & STA_UNSYNC) (void)fprintf(fp, " unsync"); 2997 #endif 2998 #ifdef STA_FREQHOLD 2999 if (status & STA_FREQHOLD) (void)fprintf(fp, " freqhold"); 3000 #endif 3001 #ifdef STA_PPSSIGNAL 3002 if (status & STA_PPSSIGNAL) (void)fprintf(fp, " ppssignal"); 3003 #endif 3004 #ifdef STA_PPSJITTER 3005 if (status & STA_PPSJITTER) (void)fprintf(fp, " ppsjitter"); 3006 #endif 3007 #ifdef STA_PPSWANDER 3008 if (status & STA_PPSWANDER) (void)fprintf(fp, " ppswander"); 3009 #endif 3010 #ifdef STA_PPSERROR 3011 if (status & STA_PPSERROR) (void)fprintf(fp, " ppserror"); 3012 #endif 3013 #ifdef STA_CLOCKERR 3014 if (status & STA_CLOCKERR) (void)fprintf(fp, " clockerr"); 3015 #endif 3016 #ifdef STA_NANO 3017 if (status & STA_NANO) (void)fprintf(fp, " nano"); 3018 #endif 3019 #ifdef STA_MODE 3020 if (status & STA_MODE) (void)fprintf(fp, " mode=fll"); 3021 #endif 3022 #ifdef STA_CLK 3023 if (status & STA_CLK) (void)fprintf(fp, " src=B"); 3024 #endif 3025 (void)fprintf(fp, "\n"); 3026 (void)fprintf(fp, "pll time constant: %ld\n", 3027 (u_long)ntohl(ik->constant)); 3028 (void)fprintf(fp, "precision: %g s\n", 3029 (u_long)ntohl(ik->precision) * tscale_usec); 3030 (void)fprintf(fp, "frequency tolerance: %s ppm\n", 3031 fptoa((s_fp)ntohl(ik->tolerance), 0)); 3032 3033 /* 3034 * For backwards compatibility (ugh), we find the pps variables 3035 * only if the shift member is nonzero. 3036 */ 3037 if (!ik->shift) 3038 return; 3039 3040 /* 3041 * pps variables 3042 */ 3043 (void)fprintf(fp, "pps frequency: %s ppm\n", 3044 fptoa((s_fp)ntohl(ik->ppsfreq), 3)); 3045 (void)fprintf(fp, "pps stability: %s ppm\n", 3046 fptoa((s_fp)ntohl(ik->stabil), 3)); 3047 (void)fprintf(fp, "pps jitter: %g s\n", 3048 (u_long)ntohl(ik->jitter) * tscale_unano); 3049 (void)fprintf(fp, "calibration interval: %d s\n", 3050 1 << ntohs(ik->shift)); 3051 (void)fprintf(fp, "calibration cycles: %ld\n", 3052 (u_long)ntohl(ik->calcnt)); 3053 (void)fprintf(fp, "jitter exceeded: %ld\n", 3054 (u_long)ntohl(ik->jitcnt)); 3055 (void)fprintf(fp, "stability exceeded: %ld\n", 3056 (u_long)ntohl(ik->stbcnt)); 3057 (void)fprintf(fp, "calibration errors: %ld\n", 3058 (u_long)ntohl(ik->errcnt)); 3059 } 3060 3061 #define IF_LIST_FMT "%2d %c %48s %c %c %12.12s %03lx %3lu %2lu %5lu %5lu %5lu %2lu %3lu %7lu\n" 3062 #define IF_LIST_FMT_STR "%2s %c %48s %c %c %12.12s %3s %3s %2s %5s %5s %5s %2s %3s %7s\n" 3063 #define IF_LIST_AFMT_STR " %48s %c\n" 3064 #define IF_LIST_LABELS "#", 'A', "Address/Mask/Broadcast", 'T', 'E', "IF name", "Flg", "TL", "#M", "recv", "sent", "drop", "S", "PC", "uptime" 3065 #define IF_LIST_LINE "==================================================================================================================\n" 3066 3067 static void 3068 iflist( 3069 FILE *fp, 3070 struct info_if_stats *ifs, 3071 size_t items, 3072 size_t itemsize, 3073 int res 3074 ) 3075 { 3076 static const char *actions = "?.+-"; 3077 sockaddr_u saddr; 3078 3079 if (res != 0) 3080 return; 3081 3082 if (!checkitems(items, fp)) 3083 return; 3084 3085 if (!checkitemsize(itemsize, sizeof(struct info_if_stats))) 3086 return; 3087 3088 fprintf(fp, IF_LIST_FMT_STR, IF_LIST_LABELS); 3089 fprintf(fp, IF_LIST_LINE); 3090 3091 while (items > 0) { 3092 SET_ADDR(saddr, ntohl(ifs->v6_flag), 3093 ifs->unaddr.addr.s_addr, ifs->unaddr.addr6); 3094 fprintf(fp, IF_LIST_FMT, 3095 ntohl(ifs->ifnum), 3096 actions[(ifs->action >= 1 && ifs->action < 4) ? ifs->action : 0], 3097 stoa((&saddr)), 'A', 3098 ifs->ignore_packets ? 'D' : 'E', 3099 ifs->name, 3100 (u_long)ntohl(ifs->flags), 3101 (u_long)ntohl(ifs->last_ttl), 3102 (u_long)ntohl(ifs->num_mcast), 3103 (u_long)ntohl(ifs->received), 3104 (u_long)ntohl(ifs->sent), 3105 (u_long)ntohl(ifs->notsent), 3106 (u_long)ntohl(ifs->scopeid), 3107 (u_long)ntohl(ifs->peercnt), 3108 (u_long)ntohl(ifs->uptime)); 3109 3110 SET_ADDR(saddr, ntohl(ifs->v6_flag), 3111 ifs->unmask.addr.s_addr, ifs->unmask.addr6); 3112 fprintf(fp, IF_LIST_AFMT_STR, stoa(&saddr), 'M'); 3113 3114 if (!ntohl(ifs->v6_flag) && ntohl(ifs->flags) & (INT_BCASTOPEN)) { 3115 SET_ADDR(saddr, ntohl(ifs->v6_flag), 3116 ifs->unbcast.addr.s_addr, ifs->unbcast.addr6); 3117 fprintf(fp, IF_LIST_AFMT_STR, stoa(&saddr), 'B'); 3118 3119 } 3120 3121 ifs++; 3122 items--; 3123 } 3124 } 3125 3126 /*ARGSUSED*/ 3127 static void 3128 get_if_stats( 3129 struct parse *pcmd, 3130 FILE *fp 3131 ) 3132 { 3133 struct info_if_stats *ifs; 3134 size_t items; 3135 size_t itemsize; 3136 int res; 3137 3138 res = doquery(impl_ver, REQ_IF_STATS, 1, 0, 0, (char *)NULL, &items, 3139 &itemsize, (void *)&ifs, 0, 3140 sizeof(struct info_if_stats)); 3141 iflist(fp, ifs, items, itemsize, res); 3142 } 3143 3144 /*ARGSUSED*/ 3145 static void 3146 do_if_reload( 3147 struct parse *pcmd, 3148 FILE *fp 3149 ) 3150 { 3151 struct info_if_stats *ifs; 3152 size_t items; 3153 size_t itemsize; 3154 int res; 3155 3156 res = doquery(impl_ver, REQ_IF_RELOAD, 1, 0, 0, (char *)NULL, &items, 3157 &itemsize, (void *)&ifs, 0, 3158 sizeof(struct info_if_stats)); 3159 iflist(fp, ifs, items, itemsize, res); 3160 } 3161