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