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