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