1 /* 2 * ntpdc_ops.c - subroutines which are called to perform operations by ntpdc 3 */ 4 5 #ifdef HAVE_CONFIG_H 6 # include <config.h> 7 #endif 8 9 #include <stdio.h> 10 #include <ctype.h> 11 #include <sys/types.h> 12 #include <sys/time.h> 13 #ifdef HAVE_SYS_TIMEX_H 14 # include <sys/timex.h> 15 #endif 16 #include <netdb.h> 17 #if !defined(__bsdi__) && !defined(apollo) 18 #include <netinet/in.h> 19 #endif 20 21 #include "ntpdc.h" 22 #include "ntp_control.h" 23 #include "ntp_refclock.h" 24 #include "ntp_stdlib.h" 25 26 #include <arpa/inet.h> 27 28 /* 29 * Declarations for command handlers in here 30 */ 31 static int checkitems P((int, FILE *)); 32 static int checkitemsize P((int, int)); 33 static int check1item P((int, FILE *)); 34 static void peerlist P((struct parse *, FILE *)); 35 static void peers P((struct parse *, FILE *)); 36 static void doconfig P((struct parse *pcmd, FILE *fp, int mode, int refc)); 37 static void dmpeers P((struct parse *, FILE *)); 38 static void dopeers P((struct parse *, FILE *, int)); 39 static void printpeer P((struct info_peer *, FILE *)); 40 static void showpeer P((struct parse *, FILE *)); 41 static void peerstats P((struct parse *, FILE *)); 42 static void loopinfo P((struct parse *, FILE *)); 43 static void sysinfo P((struct parse *, FILE *)); 44 static void sysstats P((struct parse *, FILE *)); 45 static void iostats P((struct parse *, FILE *)); 46 static void memstats P((struct parse *, FILE *)); 47 static void timerstats P((struct parse *, FILE *)); 48 static void addpeer P((struct parse *, FILE *)); 49 static void addserver P((struct parse *, FILE *)); 50 static void addrefclock P((struct parse *, FILE *)); 51 static void broadcast P((struct parse *, FILE *)); 52 static void doconfig P((struct parse *, FILE *, int, int)); 53 static void unconfig P((struct parse *, FILE *)); 54 static void set P((struct parse *, FILE *)); 55 static void sys_clear P((struct parse *, FILE *)); 56 static void doset P((struct parse *, FILE *, int)); 57 static void reslist P((struct parse *, FILE *)); 58 static void new_restrict P((struct parse *, FILE *)); 59 static void unrestrict P((struct parse *, FILE *)); 60 static void delrestrict P((struct parse *, FILE *)); 61 static void do_restrict P((struct parse *, FILE *, int)); 62 static void monlist P((struct parse *, FILE *)); 63 static void reset P((struct parse *, FILE *)); 64 static void preset P((struct parse *, FILE *)); 65 static void readkeys P((struct parse *, FILE *)); 66 static void trustkey P((struct parse *, FILE *)); 67 static void untrustkey P((struct parse *, FILE *)); 68 static void do_trustkey P((struct parse *, FILE *, int)); 69 static void authinfo P((struct parse *, FILE *)); 70 static void traps P((struct parse *, FILE *)); 71 static void addtrap P((struct parse *, FILE *)); 72 static void clrtrap P((struct parse *, FILE *)); 73 static void do_addclr_trap P((struct parse *, FILE *, int)); 74 static void requestkey P((struct parse *, FILE *)); 75 static void controlkey P((struct parse *, FILE *)); 76 static void do_changekey P((struct parse *, FILE *, int)); 77 static void ctlstats P((struct parse *, FILE *)); 78 static void clockstat P((struct parse *, FILE *)); 79 static void fudge P((struct parse *, FILE *)); 80 static void clkbug P((struct parse *, FILE *)); 81 static void kerninfo P((struct parse *, FILE *)); 82 83 /* 84 * Commands we understand. Ntpdc imports this. 85 */ 86 struct xcmd opcmds[] = { 87 { "listpeers", peerlist, { NO, NO, NO, NO }, 88 { "", "", "", "" }, 89 "display list of peers the server knows about" }, 90 { "peers", peers, { NO, NO, NO, NO }, 91 { "", "", "", "" }, 92 "display peer summary information" }, 93 { "dmpeers", dmpeers, { NO, NO, NO, NO }, 94 { "", "", "", "" }, 95 "display peer summary info the way Dave Mills likes it" }, 96 { "showpeer", showpeer, { ADD, OPT|ADD, OPT|ADD, OPT|ADD }, 97 { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 98 "display detailed information for one or more peers" }, 99 { "pstats", peerstats, { ADD, OPT|ADD, OPT|ADD, OPT|ADD }, 100 { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 101 "display statistical information for one or more peers" }, 102 { "loopinfo", loopinfo, { OPT|NTP_STR, NO, NO, NO }, 103 { "oneline|multiline", "", "", "" }, 104 "display loop filter information" }, 105 { "sysinfo", sysinfo, { NO, NO, NO, NO }, 106 { "", "", "", "" }, 107 "display local server information" }, 108 { "sysstats", sysstats, { NO, NO, NO, NO }, 109 { "", "", "", "" }, 110 "display local server statistics" }, 111 { "memstats", memstats, { NO, NO, NO, NO }, 112 { "", "", "", "" }, 113 "display peer memory usage statistics" }, 114 { "iostats", iostats, { NO, NO, NO, NO }, 115 { "", "", "", "" }, 116 "display I/O subsystem statistics" }, 117 { "timerstats", timerstats, { NO, NO, NO, NO }, 118 { "", "", "", "" }, 119 "display event timer subsystem statistics" }, 120 { "addpeer", addpeer, { ADD, OPT|UINT, OPT|UINT, OPT|NTP_STR }, 121 { "addr", "keyid", "version", "minpoll|prefer" }, 122 "configure a new peer association" }, 123 { "addserver", addserver, { ADD, OPT|UINT, OPT|UINT, OPT|NTP_STR }, 124 { "addr", "keyid", "version", "minpoll|prefer" }, 125 "configure a new server" }, 126 { "addrefclock",addrefclock, { ADD, OPT|UINT, OPT|NTP_STR, OPT|NTP_STR }, 127 { "addr", "mode", "minpoll|prefer", "minpoll|prefer" }, 128 "configure a new server" }, 129 { "broadcast", broadcast, { ADD, OPT|UINT, OPT|UINT, OPT|NTP_STR }, 130 { "addr", "keyid", "version", "minpoll" }, 131 "configure broadcasting time service" }, 132 { "unconfig", unconfig, { ADD, OPT|ADD, OPT|ADD, OPT|ADD }, 133 { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 134 "unconfigure existing peer assocations" }, 135 { "enable", set, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 136 { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." }, 137 "set a system flag (auth, bclient, monitor, pll, kernel, stats)" }, 138 { "disable", sys_clear, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 139 { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." }, 140 "clear a system flag (auth, bclient, monitor, pll, kernel, stats)" }, 141 { "reslist", reslist, { NO, NO, NO, NO }, 142 { "", "", "", "" }, 143 "display the server's restrict list" }, 144 { "restrict", new_restrict, { ADD, ADD, NTP_STR, OPT|NTP_STR }, 145 { "address", "mask", 146 "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer", 147 "..." }, 148 "create restrict entry/add flags to entry" }, 149 { "unrestrict", unrestrict, { ADD, ADD, NTP_STR, OPT|NTP_STR }, 150 { "address", "mask", 151 "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer", 152 "..." }, 153 "remove flags from a restrict entry" }, 154 { "delrestrict", delrestrict, { ADD, ADD, OPT|NTP_STR, NO }, 155 { "address", "mask", "ntpport", "" }, 156 "delete a restrict entry" }, 157 { "monlist", monlist, { OPT|INT, NO, NO, NO }, 158 { "version", "", "", "" }, 159 "display data the server's monitor routines have collected" }, 160 { "reset", reset, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 161 { "io|sys|mem|timer|auth|allpeers", "...", "...", "..." }, 162 "reset various subsystem statistics counters" }, 163 { "preset", preset, { ADD, OPT|ADD, OPT|ADD, OPT|ADD }, 164 { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 165 "reset stat counters associated with particular peer(s)" }, 166 { "readkeys", readkeys, { NO, NO, NO, NO }, 167 { "", "", "", "" }, 168 "request a reread of the keys file and re-init of system keys" }, 169 { "trustedkey", trustkey, { UINT, OPT|UINT, OPT|UINT, OPT|UINT }, 170 { "keyid", "keyid", "keyid", "keyid" }, 171 "add one or more key ID's to the trusted list" }, 172 { "untrustedkey", untrustkey, { UINT, OPT|UINT, OPT|UINT, OPT|UINT }, 173 { "keyid", "keyid", "keyid", "keyid" }, 174 "remove one or more key ID's from the trusted list" }, 175 { "authinfo", authinfo, { NO, NO, NO, NO }, 176 { "", "", "", "" }, 177 "display the state of the authentication code" }, 178 { "traps", traps, { NO, NO, NO, NO }, 179 { "", "", "", "" }, 180 "display the traps set in the server" }, 181 { "addtrap", addtrap, { ADD, OPT|UINT, OPT|ADD, NO }, 182 { "address", "port", "interface", "" }, 183 "configure a trap in the server" }, 184 { "clrtrap", clrtrap, { ADD, OPT|UINT, OPT|ADD, NO }, 185 { "address", "port", "interface", "" }, 186 "remove a trap (configured or otherwise) from the server" }, 187 { "requestkey", requestkey, { UINT, NO, NO, NO }, 188 { "keyid", "", "", "" }, 189 "change the keyid the server uses to authenticate requests" }, 190 { "controlkey", controlkey, { UINT, NO, NO, NO }, 191 { "keyid", "", "", "" }, 192 "change the keyid the server uses to authenticate control messages" }, 193 { "ctlstats", ctlstats, { NO, NO, NO, NO }, 194 { "", "", "", "" }, 195 "display packet count statistics from the control module" }, 196 { "clockstat", clockstat, { ADD, OPT|ADD, OPT|ADD, OPT|ADD }, 197 { "address", "address", "address", "address" }, 198 "display clock status information" }, 199 { "fudge", fudge, { ADD, NTP_STR, NTP_STR, NO }, 200 { "address", "time1|time2|val1|val2|flags", "value", "" }, 201 "set/change one of a clock's fudge factors" }, 202 { "clkbug", clkbug, { ADD, OPT|ADD, OPT|ADD, OPT|ADD }, 203 { "address", "address", "address", "address" }, 204 "display clock debugging information" }, 205 { "kerninfo", kerninfo, { NO, NO, NO, NO }, 206 { "", "", "", "" }, 207 "display the kernel pll/pps variables" }, 208 209 { 0, 0, { NO, NO, NO, NO }, 210 { "", "", "", "" }, "" } 211 }; 212 213 214 /* 215 * Imported from ntpdc.c 216 */ 217 extern int showhostnames; 218 extern struct servent *server_entry; 219 220 /* 221 * For quick string comparisons 222 */ 223 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) 224 225 226 /* 227 * checkitems - utility to print a message if no items were returned 228 */ 229 static int 230 checkitems( 231 int items, 232 FILE *fp 233 ) 234 { 235 if (items == 0) { 236 (void) fprintf(fp, "No data returned in response to query\n"); 237 return 0; 238 } 239 return 1; 240 } 241 242 243 /* 244 * checkitemsize - utility to print a message if the item size is wrong 245 */ 246 static int 247 checkitemsize( 248 int itemsize, 249 int expected 250 ) 251 { 252 if (itemsize != expected) { 253 (void) fprintf(stderr, 254 "***Incorrect item size returned by remote host (%d should be %d)\n", 255 itemsize, expected); 256 return 0; 257 } 258 return 1; 259 } 260 261 262 /* 263 * check1item - check to make sure we have exactly one item 264 */ 265 static int 266 check1item( 267 int items, 268 FILE *fp 269 ) 270 { 271 if (items == 0) { 272 (void) fprintf(fp, "No data returned in response to query\n"); 273 return 0; 274 } 275 if (items > 1) { 276 (void) fprintf(fp, "Expected one item in response, got %d\n", 277 items); 278 return 0; 279 } 280 return 1; 281 } 282 283 284 285 /* 286 * peerlist - get a short list of peers 287 */ 288 /*ARGSUSED*/ 289 static void 290 peerlist( 291 struct parse *pcmd, 292 FILE *fp 293 ) 294 { 295 struct info_peer_list *plist; 296 int items; 297 int itemsize; 298 int res; 299 300 res = doquery(IMPL_XNTPD, REQ_PEER_LIST, 0, 0, 0, (char *)NULL, &items, 301 &itemsize, (char **)&plist, 0); 302 303 if (res != 0 && items == 0) 304 return; 305 306 if (!checkitems(items, fp)) 307 return; 308 309 if (!checkitemsize(itemsize, sizeof(struct info_peer_list))) 310 return; 311 312 while (items > 0) { 313 (void) fprintf(fp, "%-9s %s\n", modetoa(plist->hmode), 314 nntohost(plist->address)); 315 plist++; 316 items--; 317 } 318 } 319 320 321 /* 322 * peers - show peer summary 323 */ 324 static void 325 peers( 326 struct parse *pcmd, 327 FILE *fp 328 ) 329 { 330 dopeers(pcmd, fp, 0); 331 } 332 333 /* 334 * dmpeers - show peer summary, Dave Mills style 335 */ 336 static void 337 dmpeers( 338 struct parse *pcmd, 339 FILE *fp 340 ) 341 { 342 dopeers(pcmd, fp, 1); 343 } 344 345 346 /* 347 * peers - show peer summary 348 */ 349 /*ARGSUSED*/ 350 static void 351 dopeers( 352 struct parse *pcmd, 353 FILE *fp, 354 int dmstyle 355 ) 356 { 357 struct info_peer_summary *plist; 358 int items; 359 int itemsize; 360 int ntp_poll; 361 int res; 362 int c; 363 l_fp tempts; 364 365 res = doquery(IMPL_XNTPD, REQ_PEER_LIST_SUM, 0, 0, 0, (char *)NULL, 366 &items, &itemsize, (char **)&plist, 0); 367 368 if (res != 0 && items == 0) 369 return; 370 371 if (!checkitems(items, fp)) 372 return; 373 374 if (!checkitemsize(itemsize, sizeof(struct info_peer_summary))) 375 return; 376 377 (void) fprintf(fp, 378 " remote local st poll reach delay offset disp\n"); 379 (void) fprintf(fp, 380 "=======================================================================\n"); 381 while (items > 0) { 382 if (!dmstyle) { 383 if (plist->flags & INFO_FLAG_SYSPEER) 384 c = '*'; 385 else if (plist->hmode == MODE_ACTIVE) 386 c = '+'; 387 else if (plist->hmode == MODE_PASSIVE) 388 c = '-'; 389 else if (plist->hmode == MODE_CLIENT) 390 c = '='; 391 else if (plist->hmode == MODE_BROADCAST) 392 c = '^'; 393 else if (plist->hmode == MODE_BCLIENT) 394 c = '~'; 395 else 396 c = ' '; 397 } else { 398 if (plist->flags & INFO_FLAG_SYSPEER) 399 c = '*'; 400 else if (plist->flags & INFO_FLAG_SHORTLIST) 401 c = '+'; 402 else if (plist->flags & INFO_FLAG_SEL_CANDIDATE) 403 c = '.'; 404 else 405 c = ' '; 406 } 407 NTOHL_FP(&(plist->offset), &tempts); 408 ntp_poll = 1<<max(min3(plist->ppoll, plist->hpoll, NTP_MAXPOLL), 409 NTP_MINPOLL); 410 (void) fprintf(fp, 411 "%c%-15.15s %-15.15s %2d %4d %3o %7.7s %9.9s %7.7s\n", 412 c, nntohost(plist->srcadr), 413 numtoa(plist->dstadr), 414 plist->stratum, ntp_poll, plist->reach, 415 fptoa(NTOHS_FP(plist->delay), 5), 416 lfptoa(&tempts, 6), 417 ufptoa(NTOHS_FP(plist->dispersion), 5)); 418 419 plist++; 420 items--; 421 } 422 } 423 424 /* Convert a refid & stratum (in host order) to a string */ 425 static char* 426 refid_string( 427 u_int32 refid, 428 int stratum 429 ) 430 { 431 if (stratum <= 1) { 432 static char junk[5]; 433 junk[4] = 0; 434 memmove(junk, (char *)&refid, 4); 435 return junk; 436 } 437 438 return numtoa(refid); 439 } 440 441 /* 442 * printpeer - print detail information for a peer 443 */ 444 static void 445 printpeer( 446 register struct info_peer *pp, 447 FILE *fp 448 ) 449 { 450 register int i; 451 const char *str; 452 l_fp tempts; 453 454 (void) fprintf(fp, "remote %s, local %s\n", 455 numtoa(pp->srcadr), numtoa(pp->dstadr)); 456 457 (void) fprintf(fp, "hmode %s, pmode %s, stratum %d, precision %d\n", 458 modetoa(pp->hmode), modetoa(pp->pmode), 459 pp->stratum, pp->precision); 460 461 (void) fprintf(fp, 462 "leap %c%c, refid [%s], rootdistance %s, rootdispersion %s\n", 463 pp->leap & 0x2 ? '1' : '0', 464 pp->leap & 0x1 ? '1' : '0', 465 refid_string(pp->refid, pp->stratum), fptoa(NTOHS_FP(pp->rootdelay), 5), 466 ufptoa(NTOHS_FP(pp->rootdispersion), 5)); 467 468 (void) fprintf(fp, 469 "ppoll %d, hpoll %d, keyid %lu, version %d, association %u\n", 470 pp->ppoll, pp->hpoll, (u_long)pp->keyid, pp->version, ntohs(pp->associd)); 471 472 (void) fprintf(fp, 473 "valid %d, reach %03o, unreach %d, flash 0x%04x, ", 474 pp->valid, pp->reach, pp->unreach, pp->flash2); 475 476 (void) fprintf(fp, "boffset %s, ttl/mode %d\n", 477 fptoa(NTOHS_FP(pp->estbdelay), 5), pp->ttl); 478 479 (void) fprintf(fp, "timer %lds, flags", (long)ntohl(pp->timer)); 480 if (pp->flags == 0) { 481 (void) fprintf(fp, " none\n"); 482 } else { 483 str = ""; 484 if (pp->flags & INFO_FLAG_SYSPEER) { 485 (void) fprintf(fp, " system_peer"); 486 str = ","; 487 } 488 if (pp->flags & INFO_FLAG_CONFIG) { 489 (void) fprintf(fp, "%s config", str); 490 str = ","; 491 } 492 if (pp->flags & INFO_FLAG_REFCLOCK) { 493 (void) fprintf(fp, "%s refclock", str); 494 str = ","; 495 } 496 if (pp->flags & INFO_FLAG_AUTHENABLE) { 497 (void) fprintf(fp, "%s auth", str); 498 str = ","; 499 } 500 if (pp->flags & INFO_FLAG_BCLIENT) { 501 (void) fprintf(fp, "%s bclient", str); 502 str = ","; 503 } 504 if (pp->flags & INFO_FLAG_PREFER) { 505 (void) fprintf(fp, "%s prefer", str); 506 str = ","; 507 } 508 if (pp->flags & INFO_FLAG_BURST) { 509 (void) fprintf(fp, "%s burst", str); 510 } 511 (void) fprintf(fp, "\n"); 512 } 513 514 NTOHL_FP(&pp->reftime, &tempts); 515 (void) fprintf(fp, "reference time: %s\n", 516 prettydate(&tempts)); 517 NTOHL_FP(&pp->org, &tempts); 518 (void) fprintf(fp, "originate timestamp: %s\n", 519 prettydate(&tempts)); 520 NTOHL_FP(&pp->rec, &tempts); 521 (void) fprintf(fp, "receive timestamp: %s\n", 522 prettydate(&tempts)); 523 NTOHL_FP(&pp->xmt, &tempts); 524 (void) fprintf(fp, "transmit timestamp: %s\n", 525 prettydate(&tempts)); 526 527 (void) fprintf(fp, "filter delay: "); 528 for (i = 0; i < NTP_SHIFT; i++) { 529 (void) fprintf(fp, " %-8.8s", 530 fptoa(NTOHS_FP(pp->filtdelay[i]), 5)); 531 if (i == (NTP_SHIFT>>1)-1) 532 (void) fprintf(fp, "\n "); 533 } 534 (void) fprintf(fp, "\n"); 535 536 (void) fprintf(fp, "filter offset:"); 537 for (i = 0; i < NTP_SHIFT; i++) { 538 NTOHL_FP(&pp->filtoffset[i], &tempts); 539 (void) fprintf(fp, " %-8.8s", lfptoa(&tempts, 6)); 540 if (i == (NTP_SHIFT>>1)-1) 541 (void) fprintf(fp, "\n "); 542 } 543 (void) fprintf(fp, "\n"); 544 545 (void) fprintf(fp, "filter order: "); 546 for (i = 0; i < NTP_SHIFT; i++) { 547 (void) fprintf(fp, " %-8d", pp->order[i]); 548 if (i == (NTP_SHIFT>>1)-1) 549 (void) fprintf(fp, "\n "); 550 } 551 (void) fprintf(fp, "\n"); 552 553 554 NTOHL_FP(&pp->offset, &tempts); 555 (void) fprintf(fp, 556 "offset %s, delay %s, error bound %s, filter error %s\n", 557 lfptoa(&tempts, 6), fptoa(NTOHS_FP(pp->delay), 5), 558 ufptoa(NTOHS_FP(pp->dispersion), 5), 559 ufptoa(NTOHS_FP(pp->selectdisp), 5)); 560 } 561 562 563 /* 564 * showpeer - show detailed information for a peer 565 */ 566 static void 567 showpeer( 568 struct parse *pcmd, 569 FILE *fp 570 ) 571 { 572 struct info_peer *pp; 573 /* 4 is the maximum number of peers which will fit in a packet */ 574 struct info_peer_list plist[min(MAXARGS, 4)]; 575 int qitems; 576 int items; 577 int itemsize; 578 int res; 579 580 for (qitems = 0; qitems < min(pcmd->nargs, 4); qitems++) { 581 plist[qitems].address = pcmd->argval[qitems].netnum; 582 plist[qitems].port = server_entry->s_port; 583 plist[qitems].hmode = plist[qitems].flags = 0; 584 } 585 586 res = doquery(IMPL_XNTPD, REQ_PEER_INFO, 0, qitems, 587 sizeof(struct info_peer_list), (char *)plist, &items, 588 &itemsize, (char **)&pp, 0); 589 590 if (res != 0 && items == 0) 591 return; 592 593 if (!checkitems(items, fp)) 594 return; 595 596 if (!checkitemsize(itemsize, sizeof(struct info_peer))) 597 return; 598 599 while (items-- > 0) { 600 printpeer(pp, fp); 601 if (items > 0) 602 (void) fprintf(fp, "\n"); 603 pp++; 604 } 605 } 606 607 608 /* 609 * peerstats - return statistics for a peer 610 */ 611 static void 612 peerstats( 613 struct parse *pcmd, 614 FILE *fp 615 ) 616 { 617 struct info_peer_stats *pp; 618 /* 4 is the maximum number of peers which will fit in a packet */ 619 struct info_peer_list plist[min(MAXARGS, 4)]; 620 int qitems; 621 int items; 622 int itemsize; 623 int res; 624 625 for (qitems = 0; qitems < min(pcmd->nargs, 4); qitems++) { 626 plist[qitems].address = pcmd->argval[qitems].netnum; 627 plist[qitems].port = server_entry->s_port; 628 plist[qitems].hmode = plist[qitems].flags = 0; 629 } 630 631 res = doquery(IMPL_XNTPD, REQ_PEER_STATS, 0, qitems, 632 sizeof(struct info_peer_list), (char *)plist, &items, 633 &itemsize, (char **)&pp, 0); 634 635 if (res != 0 && items == 0) 636 return; 637 638 if (!checkitems(items, fp)) 639 return; 640 641 if (!checkitemsize(itemsize, sizeof(struct info_peer_stats))) 642 return; 643 644 while (items-- > 0) { 645 (void) fprintf(fp, "remote host: %s\n", 646 nntohost(pp->srcadr)); 647 (void) fprintf(fp, "local interface: %s\n", 648 numtoa(pp->dstadr)); 649 (void) fprintf(fp, "time last received: %lds\n", 650 (long)ntohl(pp->timereceived)); 651 (void) fprintf(fp, "time until next send: %lds\n", 652 (long)ntohl(pp->timetosend)); 653 (void) fprintf(fp, "reachability change: %lds\n", 654 (long)ntohl(pp->timereachable)); 655 (void) fprintf(fp, "packets sent: %ld\n", 656 (long)ntohl(pp->sent)); 657 (void) fprintf(fp, "packets received: %ld\n", 658 (long)ntohl(pp->processed)); 659 (void) fprintf(fp, "bad authentication: %ld\n", 660 (long)ntohl(pp->badauth)); 661 (void) fprintf(fp, "bogus origin: %ld\n", 662 (long)ntohl(pp->bogusorg)); 663 (void) fprintf(fp, "duplicate: %ld\n", 664 (long)ntohl(pp->oldpkt)); 665 (void) fprintf(fp, "bad dispersion: %ld\n", 666 (long)ntohl(pp->seldisp)); 667 (void) fprintf(fp, "bad reference time: %ld\n", 668 (long)ntohl(pp->selbroken)); 669 (void) fprintf(fp, "candidate order: %d\n", 670 (int)pp->candidate); 671 if (items > 0) 672 (void) fprintf(fp, "\n"); 673 pp++; 674 } 675 } 676 677 678 /* 679 * loopinfo - show loop filter information 680 */ 681 static void 682 loopinfo( 683 struct parse *pcmd, 684 FILE *fp 685 ) 686 { 687 struct info_loop *il; 688 int items; 689 int itemsize; 690 int oneline = 0; 691 int res; 692 l_fp tempts; 693 694 if (pcmd->nargs > 0) { 695 if (STREQ(pcmd->argval[0].string, "oneline")) 696 oneline = 1; 697 else if (STREQ(pcmd->argval[0].string, "multiline")) 698 oneline = 0; 699 else { 700 (void) fprintf(stderr, "How many lines?\n"); 701 return; 702 } 703 } 704 705 res = doquery(IMPL_XNTPD, REQ_LOOP_INFO, 0, 0, 0, (char *)NULL, 706 &items, &itemsize, (char **)&il, 0); 707 708 if (res != 0 && items == 0) 709 return; 710 711 if (!check1item(items, fp)) 712 return; 713 714 if (!checkitemsize(itemsize, sizeof(struct info_loop))) 715 return; 716 717 if (oneline) { 718 l_fp temp2ts; 719 720 NTOHL_FP(&il->last_offset, &tempts); 721 NTOHL_FP(&il->drift_comp, &temp2ts); 722 723 (void) fprintf(fp, 724 "offset %s, frequency %s, time_const %ld, watchdog %ld\n", 725 lfptoa(&tempts, 6), 726 lfptoa(&temp2ts, 3), 727 (u_long)ntohl(il->compliance), 728 (u_long)ntohl(il->watchdog_timer)); 729 } else { 730 NTOHL_FP(&il->last_offset, &tempts); 731 (void) fprintf(fp, "offset: %s s\n", 732 lfptoa(&tempts, 6)); 733 NTOHL_FP(&il->drift_comp, &tempts); 734 (void) fprintf(fp, "frequency: %s ppm\n", 735 lfptoa(&tempts, 3)); 736 (void) fprintf(fp, "poll adjust: %ld\n", 737 (u_long)ntohl(il->compliance)); 738 (void) fprintf(fp, "watchdog timer: %ld s\n", 739 (u_long)ntohl(il->watchdog_timer)); 740 } 741 } 742 743 744 /* 745 * sysinfo - show current system state 746 */ 747 /*ARGSUSED*/ 748 static void 749 sysinfo( 750 struct parse *pcmd, 751 FILE *fp 752 ) 753 { 754 struct info_sys *is; 755 int items; 756 int itemsize; 757 int res; 758 l_fp tempts; 759 760 res = doquery(IMPL_XNTPD, REQ_SYS_INFO, 0, 0, 0, (char *)NULL, 761 &items, &itemsize, (char **)&is, 0); 762 763 if (res != 0 && items == 0) 764 return; 765 766 if (!check1item(items, fp)) 767 return; 768 769 if (!checkitemsize(itemsize, sizeof(struct info_sys))) 770 return; 771 772 (void) fprintf(fp, "system peer: %s\n", nntohost(is->peer)); 773 (void) fprintf(fp, "system peer mode: %s\n", modetoa(is->peer_mode)); 774 (void) fprintf(fp, "leap indicator: %c%c\n", 775 is->leap & 0x2 ? '1' : '0', 776 is->leap & 0x1 ? '1' : '0'); 777 (void) fprintf(fp, "stratum: %d\n", (int)is->stratum); 778 (void) fprintf(fp, "precision: %d\n", (int)is->precision); 779 (void) fprintf(fp, "root distance: %s s\n", 780 fptoa(NTOHS_FP(is->rootdelay), 5)); 781 (void) fprintf(fp, "root dispersion: %s s\n", 782 ufptoa(NTOHS_FP(is->rootdispersion), 5)); 783 (void) fprintf(fp, "reference ID: [%s]\n", 784 refid_string(is->refid, is->stratum)); 785 NTOHL_FP(&is->reftime, &tempts); 786 (void) fprintf(fp, "reference time: %s\n", prettydate(&tempts)); 787 788 (void) fprintf(fp, "system flags: "); 789 if ((is->flags & (INFO_FLAG_BCLIENT | INFO_FLAG_AUTHENABLE | 790 INFO_FLAG_NTP | INFO_FLAG_KERNEL| INFO_FLAG_PLL_SYNC | 791 INFO_FLAG_PPS_SYNC | INFO_FLAG_MONITOR | INFO_FLAG_FILEGEN)) == 0) { 792 (void) fprintf(fp, "none\n"); 793 } else { 794 if (is->flags & INFO_FLAG_BCLIENT) 795 (void) fprintf(fp, "bclient "); 796 if (is->flags & INFO_FLAG_AUTHENTICATE) 797 (void) fprintf(fp, "auth "); 798 if (is->flags & INFO_FLAG_MONITOR) 799 (void) fprintf(fp, "monitor "); 800 if (is->flags & INFO_FLAG_NTP) 801 (void) fprintf(fp, "ntp "); 802 if (is->flags & INFO_FLAG_KERNEL) 803 (void) fprintf(fp, "kernel "); 804 if (is->flags & INFO_FLAG_FILEGEN) 805 (void) fprintf(fp, "stats "); 806 if (is->flags & INFO_FLAG_PLL_SYNC) 807 (void) fprintf(fp, "kernel_sync "); 808 if (is->flags & INFO_FLAG_PPS_SYNC) 809 (void) fprintf(fp, "pps_sync "); 810 (void) fprintf(fp, "\n"); 811 } 812 (void) fprintf(fp, "jitter: %s s\n", 813 fptoa(ntohl(is->frequency), 6)); 814 (void) fprintf(fp, "stability: %s ppm\n", 815 ufptoa(ntohl(is->stability), 3)); 816 (void) fprintf(fp, "broadcastdelay: %s s\n", 817 fptoa(NTOHS_FP(is->bdelay), 6)); 818 NTOHL_FP(&is->authdelay, &tempts); 819 (void) fprintf(fp, "authdelay: %s s\n", lfptoa(&tempts, 6)); 820 } 821 822 823 /* 824 * sysstats - print system statistics 825 */ 826 /*ARGSUSED*/ 827 static void 828 sysstats( 829 struct parse *pcmd, 830 FILE *fp 831 ) 832 { 833 struct info_sys_stats *ss; 834 int items; 835 int itemsize; 836 int res; 837 838 res = doquery(IMPL_XNTPD, REQ_SYS_STATS, 0, 0, 0, (char *)NULL, 839 &items, &itemsize, (char **)&ss, 0); 840 841 if (res != 0 && items == 0) 842 return; 843 844 if (!check1item(items, fp)) 845 return; 846 847 if (itemsize != sizeof(struct info_sys_stats) && 848 itemsize != sizeof(struct old_info_sys_stats)) { 849 /* issue warning according to new structure size */ 850 checkitemsize(itemsize, sizeof(struct info_sys_stats)); 851 return; 852 } 853 854 (void) fprintf(fp, "system uptime: %ld\n", 855 (u_long)ntohl(ss->timeup)); 856 (void) fprintf(fp, "time since reset: %ld\n", 857 (u_long)ntohl(ss->timereset)); 858 (void) fprintf(fp, "bad stratum in packet: %ld\n", 859 (u_long)ntohl(ss->badstratum)); 860 (void) fprintf(fp, "old version packets: %ld\n", 861 (u_long)ntohl(ss->oldversionpkt)); 862 (void) fprintf(fp, "new version packets: %ld\n", 863 (u_long)ntohl(ss->newversionpkt)); 864 (void) fprintf(fp, "unknown version number: %ld\n", 865 (u_long)ntohl(ss->unknownversion)); 866 (void) fprintf(fp, "bad packet length: %ld\n", 867 (u_long)ntohl(ss->badlength)); 868 (void) fprintf(fp, "packets processed: %ld\n", 869 (u_long)ntohl(ss->processed)); 870 (void) fprintf(fp, "bad authentication: %ld\n", 871 (u_long)ntohl(ss->badauth)); 872 if (itemsize != sizeof(struct info_sys_stats)) 873 return; 874 875 (void) fprintf(fp, "limitation rejects: %ld\n", 876 (u_long)ntohl(ss->limitrejected)); 877 } 878 879 880 881 /* 882 * iostats - print I/O statistics 883 */ 884 /*ARGSUSED*/ 885 static void 886 iostats( 887 struct parse *pcmd, 888 FILE *fp 889 ) 890 { 891 struct info_io_stats *io; 892 int items; 893 int itemsize; 894 int res; 895 896 res = doquery(IMPL_XNTPD, REQ_IO_STATS, 0, 0, 0, (char *)NULL, 897 &items, &itemsize, (char **)&io, 0); 898 899 if (res != 0 && items == 0) 900 return; 901 902 if (!check1item(items, fp)) 903 return; 904 905 if (!checkitemsize(itemsize, sizeof(struct info_io_stats))) 906 return; 907 908 (void) fprintf(fp, "time since reset: %ld\n", 909 (u_long)ntohl(io->timereset)); 910 (void) fprintf(fp, "receive buffers: %d\n", 911 ntohs(io->totalrecvbufs)); 912 (void) fprintf(fp, "free receive buffers: %d\n", 913 ntohs(io->freerecvbufs)); 914 (void) fprintf(fp, "used receive buffers: %d\n", 915 ntohs(io->fullrecvbufs)); 916 (void) fprintf(fp, "low water refills: %d\n", 917 ntohs(io->lowwater)); 918 (void) fprintf(fp, "dropped packets: %ld\n", 919 (u_long)ntohl(io->dropped)); 920 (void) fprintf(fp, "ignored packets: %ld\n", 921 (u_long)ntohl(io->ignored)); 922 (void) fprintf(fp, "received packets: %ld\n", 923 (u_long)ntohl(io->received)); 924 (void) fprintf(fp, "packets sent: %ld\n", 925 (u_long)ntohl(io->sent)); 926 (void) fprintf(fp, "packets not sent: %ld\n", 927 (u_long)ntohl(io->notsent)); 928 (void) fprintf(fp, "interrupts handled: %ld\n", 929 (u_long)ntohl(io->interrupts)); 930 (void) fprintf(fp, "received by int: %ld\n", 931 (u_long)ntohl(io->int_received)); 932 } 933 934 935 /* 936 * memstats - print peer memory statistics 937 */ 938 /*ARGSUSED*/ 939 static void 940 memstats( 941 struct parse *pcmd, 942 FILE *fp 943 ) 944 { 945 struct info_mem_stats *mem; 946 int i; 947 int items; 948 int itemsize; 949 int res; 950 951 res = doquery(IMPL_XNTPD, REQ_MEM_STATS, 0, 0, 0, (char *)NULL, 952 &items, &itemsize, (char **)&mem, 0); 953 954 if (res != 0 && items == 0) 955 return; 956 957 if (!check1item(items, fp)) 958 return; 959 960 if (!checkitemsize(itemsize, sizeof(struct info_mem_stats))) 961 return; 962 963 (void) fprintf(fp, "time since reset: %ld\n", 964 (u_long)ntohl(mem->timereset)); 965 (void) fprintf(fp, "total peer memory: %d\n", 966 ntohs(mem->totalpeermem)); 967 (void) fprintf(fp, "free peer memory: %d\n", 968 ntohs(mem->freepeermem)); 969 (void) fprintf(fp, "calls to findpeer: %ld\n", 970 (u_long)ntohl(mem->findpeer_calls)); 971 (void) fprintf(fp, "new peer allocations: %ld\n", 972 (u_long)ntohl(mem->allocations)); 973 (void) fprintf(fp, "peer demobilizations: %ld\n", 974 (u_long)ntohl(mem->demobilizations)); 975 976 (void) fprintf(fp, "hash table counts: "); 977 for (i = 0; i < HASH_SIZE; i++) { 978 (void) fprintf(fp, "%4d", (int)mem->hashcount[i]); 979 if ((i % 8) == 7 && i != (HASH_SIZE-1)) { 980 (void) fprintf(fp, "\n "); 981 } 982 } 983 (void) fprintf(fp, "\n"); 984 } 985 986 987 988 /* 989 * timerstats - print timer statistics 990 */ 991 /*ARGSUSED*/ 992 static void 993 timerstats( 994 struct parse *pcmd, 995 FILE *fp 996 ) 997 { 998 struct info_timer_stats *tim; 999 int items; 1000 int itemsize; 1001 int res; 1002 1003 res = doquery(IMPL_XNTPD, REQ_TIMER_STATS, 0, 0, 0, (char *)NULL, 1004 &items, &itemsize, (char **)&tim, 0); 1005 1006 if (res != 0 && items == 0) 1007 return; 1008 1009 if (!check1item(items, fp)) 1010 return; 1011 1012 if (!checkitemsize(itemsize, sizeof(struct info_timer_stats))) 1013 return; 1014 1015 (void) fprintf(fp, "time since reset: %ld\n", 1016 (u_long)ntohl(tim->timereset)); 1017 (void) fprintf(fp, "alarms handled: %ld\n", 1018 (u_long)ntohl(tim->alarms)); 1019 (void) fprintf(fp, "alarm overruns: %ld\n", 1020 (u_long)ntohl(tim->overflows)); 1021 (void) fprintf(fp, "calls to transmit: %ld\n", 1022 (u_long)ntohl(tim->xmtcalls)); 1023 } 1024 1025 1026 /* 1027 * addpeer - configure an active mode association 1028 */ 1029 static void 1030 addpeer( 1031 struct parse *pcmd, 1032 FILE *fp 1033 ) 1034 { 1035 doconfig(pcmd, fp, MODE_ACTIVE, 0); 1036 } 1037 1038 1039 /* 1040 * addserver - configure a client mode association 1041 */ 1042 static void 1043 addserver( 1044 struct parse *pcmd, 1045 FILE *fp 1046 ) 1047 { 1048 doconfig(pcmd, fp, MODE_CLIENT, 0); 1049 } 1050 1051 /* 1052 * addrefclock - configure a reference clock association 1053 */ 1054 static void 1055 addrefclock( 1056 struct parse *pcmd, 1057 FILE *fp 1058 ) 1059 { 1060 doconfig(pcmd, fp, MODE_CLIENT, 1); 1061 } 1062 1063 /* 1064 * broadcast - configure a broadcast mode association 1065 */ 1066 static void 1067 broadcast( 1068 struct parse *pcmd, 1069 FILE *fp 1070 ) 1071 { 1072 doconfig(pcmd, fp, MODE_BROADCAST, 0); 1073 } 1074 1075 1076 /* 1077 * config - configure a new peer association 1078 */ 1079 static void 1080 doconfig( 1081 struct parse *pcmd, 1082 FILE *fp, 1083 int mode, 1084 int refc 1085 ) 1086 { 1087 struct conf_peer cpeer; 1088 int items; 1089 int itemsize; 1090 char *dummy; 1091 u_long keyid; 1092 u_int version; 1093 u_char minpoll; 1094 u_int flags; 1095 u_char cmode; 1096 int res; 1097 1098 keyid = 0; 1099 version = NTP_OLDVERSION + 1; 1100 flags = 0; 1101 res = 0; 1102 cmode = 0; 1103 minpoll = NTP_MINDPOLL; 1104 1105 items = pcmd->nargs; 1106 1107 if (refc) { 1108 if (pcmd->nargs > 1) { 1109 cmode = (u_char) pcmd->argval[1].uval; 1110 items = 2; 1111 } 1112 } else { 1113 if (pcmd->nargs > 1) { 1114 keyid = pcmd->argval[1].uval; 1115 if (keyid > 0) { 1116 flags |= CONF_FLAG_AUTHENABLE; 1117 } 1118 if (pcmd->nargs > 2) { 1119 version = (u_int)pcmd->argval[2].uval; 1120 if (version > NTP_VERSION || 1121 version < NTP_OLDVERSION) { 1122 (void)fprintf(fp, 1123 "invalid version number %u\n", 1124 version); 1125 res++; 1126 } 1127 items = 3; 1128 } 1129 } 1130 } 1131 1132 while (pcmd->nargs > items) { 1133 if (STREQ(pcmd->argval[items].string, "prefer")) 1134 flags |= CONF_FLAG_PREFER; 1135 else if (STREQ(pcmd->argval[items].string, "burst")) 1136 flags |= CONF_FLAG_BURST; 1137 else { 1138 long val; 1139 if (!atoint(pcmd->argval[items].string, &val)) { 1140 (void) fprintf(fp, 1141 "%s not understood\n", 1142 pcmd->argval[items].string); 1143 res++; 1144 break; 1145 } else { 1146 if (val >= NTP_MINPOLL && val <= NTP_MAXPOLL) { 1147 minpoll = (u_char)val; 1148 } else { 1149 (void) fprintf(fp, 1150 "minpol must be within %d..%d\n", 1151 NTP_MINPOLL, NTP_MAXPOLL); 1152 res++; 1153 break; 1154 } 1155 } 1156 } 1157 items++; 1158 } 1159 1160 if (res) 1161 return; 1162 1163 memset((void *)&cpeer, 0, sizeof cpeer); 1164 1165 cpeer.peeraddr = pcmd->argval[0].netnum; 1166 cpeer.hmode = (u_char) mode; 1167 cpeer.keyid = keyid; 1168 cpeer.version = (u_char) version; 1169 cpeer.minpoll = minpoll; 1170 cpeer.maxpoll = NTP_MAXDPOLL; 1171 cpeer.flags = (u_char)flags; 1172 cpeer.ttl = cmode; 1173 1174 res = doquery(IMPL_XNTPD, REQ_CONFIG, 1, 1, 1175 sizeof(struct conf_peer), (char *)&cpeer, &items, 1176 &itemsize, &dummy, 0); 1177 1178 if (res == 0) 1179 (void) fprintf(fp, "done!\n"); 1180 return; 1181 } 1182 1183 1184 /* 1185 * unconfig - unconfigure some associations 1186 */ 1187 static void 1188 unconfig( 1189 struct parse *pcmd, 1190 FILE *fp 1191 ) 1192 { 1193 /* 8 is the maximum number of peers which will fit in a packet */ 1194 struct conf_unpeer plist[min(MAXARGS, 8)]; 1195 int qitems; 1196 int items; 1197 int itemsize; 1198 char *dummy; 1199 int res; 1200 1201 for (qitems = 0; qitems < min(pcmd->nargs, 8); qitems++) { 1202 plist[qitems].peeraddr = pcmd->argval[qitems].netnum; 1203 } 1204 1205 res = doquery(IMPL_XNTPD, REQ_UNCONFIG, 1, qitems, 1206 sizeof(struct conf_unpeer), (char *)plist, &items, 1207 &itemsize, &dummy, 0); 1208 1209 if (res == 0) 1210 (void) fprintf(fp, "done!\n"); 1211 } 1212 1213 1214 /* 1215 * set - set some system flags 1216 */ 1217 static void 1218 set( 1219 struct parse *pcmd, 1220 FILE *fp 1221 ) 1222 { 1223 doset(pcmd, fp, REQ_SET_SYS_FLAG); 1224 } 1225 1226 1227 /* 1228 * clear - clear some system flags 1229 */ 1230 static void 1231 sys_clear( 1232 struct parse *pcmd, 1233 FILE *fp 1234 ) 1235 { 1236 doset(pcmd, fp, REQ_CLR_SYS_FLAG); 1237 } 1238 1239 1240 /* 1241 * doset - set/clear system flags 1242 */ 1243 static void 1244 doset( 1245 struct parse *pcmd, 1246 FILE *fp, 1247 int req 1248 ) 1249 { 1250 /* 8 is the maximum number of peers which will fit in a packet */ 1251 struct conf_sys_flags sys; 1252 int items; 1253 int itemsize; 1254 char *dummy; 1255 int res; 1256 1257 sys.flags = 0; 1258 res = 0; 1259 for (items = 0; items < pcmd->nargs; items++) { 1260 if (STREQ(pcmd->argval[items].string, "auth")) 1261 sys.flags |= SYS_FLAG_AUTHENTICATE; 1262 else if (STREQ(pcmd->argval[items].string, "bclient")) 1263 sys.flags |= SYS_FLAG_BCLIENT; 1264 else if (STREQ(pcmd->argval[items].string, "monitor")) 1265 sys.flags |= SYS_FLAG_MONITOR; 1266 else if (STREQ(pcmd->argval[items].string, "ntp")) 1267 sys.flags |= SYS_FLAG_NTP; 1268 else if (STREQ(pcmd->argval[items].string, "kernel")) 1269 sys.flags |= SYS_FLAG_KERNEL; 1270 else if (STREQ(pcmd->argval[items].string, "stats")) 1271 sys.flags |= SYS_FLAG_FILEGEN; 1272 else { 1273 (void) fprintf(fp, "Unknown flag %s\n", 1274 pcmd->argval[items].string); 1275 res = 1; 1276 } 1277 } 1278 1279 if (res || sys.flags == 0) 1280 return; 1281 1282 res = doquery(IMPL_XNTPD, req, 1, 1, 1283 sizeof(struct conf_sys_flags), (char *)&sys, &items, 1284 &itemsize, &dummy, 0); 1285 1286 if (res == 0) 1287 (void) fprintf(fp, "done!\n"); 1288 } 1289 1290 1291 /* 1292 * data for printing/interrpreting the restrict flags 1293 */ 1294 struct resflags { 1295 const char *str; 1296 int bit; 1297 }; 1298 1299 static struct resflags resflags[] = { 1300 { "ignore", RES_IGNORE }, 1301 { "noserve", RES_DONTSERVE }, 1302 { "notrust", RES_DONTTRUST }, 1303 { "noquery", RES_NOQUERY }, 1304 { "nomodify", RES_NOMODIFY }, 1305 { "nopeer", RES_NOPEER }, 1306 { "notrap", RES_NOTRAP }, 1307 { "lptrap", RES_LPTRAP }, 1308 { "limited", RES_LIMITED }, 1309 { "", 0 } 1310 }; 1311 1312 static struct resflags resmflags[] = { 1313 { "ntpport", RESM_NTPONLY }, 1314 { "interface", RESM_INTERFACE }, 1315 { "", 0 } 1316 }; 1317 1318 1319 /* 1320 * reslist - obtain and print the server's restrict list 1321 */ 1322 /*ARGSUSED*/ 1323 static void 1324 reslist( 1325 struct parse *pcmd, 1326 FILE *fp 1327 ) 1328 { 1329 struct info_restrict *rl; 1330 int items; 1331 int itemsize; 1332 int res; 1333 char *addr; 1334 char *mask; 1335 struct resflags *rf; 1336 u_int32 count; 1337 u_short flags; 1338 u_short mflags; 1339 char flagstr[300]; 1340 static const char *comma = ", "; 1341 1342 res = doquery(IMPL_XNTPD, REQ_GET_RESTRICT, 0, 0, 0, (char *)NULL, 1343 &items, &itemsize, (char **)&rl, 0); 1344 1345 if (res != 0 && items == 0) 1346 return; 1347 1348 if (!checkitems(items, fp)) 1349 return; 1350 1351 if (!checkitemsize(itemsize, sizeof(struct info_restrict))) 1352 return; 1353 1354 (void) fprintf(fp, 1355 " address mask count flags\n"); 1356 (void) fprintf(fp, 1357 "=====================================================================\n"); 1358 while (items > 0) { 1359 if ((rl->mask == (u_int32)0xffffffff)) 1360 addr = nntohost(rl->addr); 1361 else 1362 addr = numtoa( rl->addr ); 1363 mask = numtoa(rl->mask); 1364 count = ntohl(rl->count); 1365 flags = ntohs(rl->flags); 1366 mflags = ntohs(rl->mflags); 1367 flagstr[0] = '\0'; 1368 1369 res = 1; 1370 rf = &resmflags[0]; 1371 while (rf->bit != 0) { 1372 if (mflags & rf->bit) { 1373 if (!res) 1374 (void) strcat(flagstr, comma); 1375 res = 0; 1376 (void) strcat(flagstr, rf->str); 1377 } 1378 rf++; 1379 } 1380 1381 rf = &resflags[0]; 1382 while (rf->bit != 0) { 1383 if (flags & rf->bit) { 1384 if (!res) 1385 (void) strcat(flagstr, comma); 1386 res = 0; 1387 (void) strcat(flagstr, rf->str); 1388 } 1389 rf++; 1390 } 1391 1392 if (flagstr[0] == '\0') 1393 (void) strcpy(flagstr, "none"); 1394 1395 (void) fprintf(fp, "%-15.15s %-15.15s %9ld %s\n", 1396 addr, mask, (u_long)count, flagstr); 1397 rl++; 1398 items--; 1399 } 1400 } 1401 1402 1403 1404 /* 1405 * new_restrict - create/add a set of restrictions 1406 */ 1407 static void 1408 new_restrict( 1409 struct parse *pcmd, 1410 FILE *fp 1411 ) 1412 { 1413 do_restrict(pcmd, fp, REQ_RESADDFLAGS); 1414 } 1415 1416 1417 /* 1418 * unrestrict - remove restriction flags from existing entry 1419 */ 1420 static void 1421 unrestrict( 1422 struct parse *pcmd, 1423 FILE *fp 1424 ) 1425 { 1426 do_restrict(pcmd, fp, REQ_RESSUBFLAGS); 1427 } 1428 1429 1430 /* 1431 * delrestrict - delete an existing restriction 1432 */ 1433 static void 1434 delrestrict( 1435 struct parse *pcmd, 1436 FILE *fp 1437 ) 1438 { 1439 do_restrict(pcmd, fp, REQ_UNRESTRICT); 1440 } 1441 1442 1443 /* 1444 * do_restrict - decode commandline restrictions and make the request 1445 */ 1446 static void 1447 do_restrict( 1448 struct parse *pcmd, 1449 FILE *fp, 1450 int req_code 1451 ) 1452 { 1453 struct conf_restrict cres; 1454 int items; 1455 int itemsize; 1456 char *dummy; 1457 u_int32 num; 1458 u_long bit; 1459 int i; 1460 int res; 1461 int err; 1462 1463 cres.addr = pcmd->argval[0].netnum; 1464 cres.mask = pcmd->argval[1].netnum; 1465 cres.flags = 0; 1466 cres.mflags = 0; 1467 err = 0; 1468 for (res = 2; res < pcmd->nargs; res++) { 1469 if (STREQ(pcmd->argval[res].string, "ntpport")) { 1470 cres.mflags |= RESM_NTPONLY; 1471 } else { 1472 for (i = 0; resflags[i].bit != 0; i++) { 1473 if (STREQ(pcmd->argval[res].string, 1474 resflags[i].str)) 1475 break; 1476 } 1477 if (resflags[i].bit != 0) { 1478 cres.flags |= resflags[i].bit; 1479 if (req_code == REQ_UNRESTRICT) { 1480 (void) fprintf(fp, 1481 "Flag %s inappropriate\n", 1482 resflags[i].str); 1483 err++; 1484 } 1485 } else { 1486 (void) fprintf(fp, "Unknown flag %s\n", 1487 pcmd->argval[res].string); 1488 err++; 1489 } 1490 } 1491 } 1492 1493 /* 1494 * Make sure mask for default address is zero. Otherwise, 1495 * make sure mask bits are contiguous. 1496 */ 1497 if (cres.addr == 0) { 1498 cres.mask = 0; 1499 } else { 1500 num = ntohl(cres.mask); 1501 for (bit = 0x80000000; bit != 0; bit >>= 1) 1502 if ((num & bit) == 0) 1503 break; 1504 for ( ; bit != 0; bit >>= 1) 1505 if ((num & bit) != 0) 1506 break; 1507 if (bit != 0) { 1508 (void) fprintf(fp, "Invalid mask %s\n", 1509 numtoa(cres.mask)); 1510 err++; 1511 } 1512 } 1513 1514 if (err) 1515 return; 1516 1517 res = doquery(IMPL_XNTPD, req_code, 1, 1, 1518 sizeof(struct conf_restrict), (char *)&cres, &items, 1519 &itemsize, &dummy, 0); 1520 1521 if (res == 0) 1522 (void) fprintf(fp, "done!\n"); 1523 return; 1524 } 1525 1526 1527 /* 1528 * monlist - obtain and print the server's monitor data 1529 */ 1530 /*ARGSUSED*/ 1531 static void 1532 monlist( 1533 struct parse *pcmd, 1534 FILE *fp 1535 ) 1536 { 1537 char *struct_star; 1538 struct in_addr addr; 1539 int items; 1540 int itemsize; 1541 int res; 1542 int version = -1; 1543 1544 if (pcmd->nargs > 0) { 1545 version = pcmd->argval[0].ival; 1546 } 1547 1548 res = doquery(IMPL_XNTPD, 1549 (version == 1 || version == -1) ? REQ_MON_GETLIST_1 : 1550 REQ_MON_GETLIST, 0, 0, 0, (char *)NULL, 1551 &items, &itemsize, &struct_star, 1552 (version < 0) ? (1 << INFO_ERR_REQ) : 0); 1553 1554 if (res == INFO_ERR_REQ && version < 0) 1555 res = doquery(IMPL_XNTPD, REQ_MON_GETLIST, 0, 0, 0, (char *)NULL, 1556 &items, &itemsize, &struct_star, 0); 1557 1558 if (res != 0 && items == 0) 1559 return; 1560 1561 if (!checkitems(items, fp)) 1562 return; 1563 1564 if (itemsize == sizeof(struct info_monitor_1)) { 1565 struct info_monitor_1 *ml = (struct info_monitor_1 *) struct_star; 1566 1567 (void) fprintf(fp, 1568 "remote address port local address count m ver drop last first\n"); 1569 (void) fprintf(fp, 1570 "===============================================================================\n"); 1571 while (items > 0) { 1572 addr.s_addr = ml->daddr; 1573 (void) fprintf(fp, 1574 "%-22.22s %5d %-15s %8ld %1d %1d %6lu %6lu %7lu\n", 1575 nntohost(ml->addr), 1576 ntohs(ml->port), 1577 inet_ntoa(addr), 1578 (u_long)ntohl(ml->count), 1579 ml->mode, 1580 ml->version, 1581 (u_long)ntohl(ml->lastdrop), 1582 (u_long)ntohl(ml->lasttime), 1583 (u_long)ntohl(ml->firsttime)); 1584 ml++; 1585 items--; 1586 } 1587 } else if (itemsize == sizeof(struct info_monitor)) { 1588 struct info_monitor *ml = (struct info_monitor *) struct_star; 1589 1590 (void) fprintf(fp, 1591 " address port count mode ver lastdrop lasttime firsttime\n"); 1592 (void) fprintf(fp, 1593 "===============================================================================\n"); 1594 while (items > 0) { 1595 addr.s_addr = ml->lastdrop; 1596 (void) fprintf(fp, 1597 "%-25.25s %5d %9ld %4d %2d %9lu %9lu %9lu\n", 1598 nntohost(ml->addr), 1599 ntohs(ml->port), 1600 (u_long)ntohl(ml->count), 1601 ml->mode, 1602 ml->version, 1603 (u_long)ntohl(ml->lastdrop), 1604 (u_long)ntohl(ml->lasttime), 1605 (u_long)ntohl(ml->firsttime)); 1606 ml++; 1607 items--; 1608 } 1609 } else if (itemsize == sizeof(struct old_info_monitor)) { 1610 struct old_info_monitor *oml = (struct old_info_monitor *)struct_star; 1611 (void) fprintf(fp, 1612 " address port count mode version lasttime firsttime\n"); 1613 (void) fprintf(fp, 1614 "======================================================================\n"); 1615 while (items > 0) { 1616 (void) fprintf(fp, "%-20.20s %5d %9ld %4d %3d %9lu %9lu\n", 1617 nntohost(oml->addr), 1618 ntohs(oml->port), 1619 (u_long)ntohl(oml->count), 1620 oml->mode, 1621 oml->version, 1622 (u_long)ntohl(oml->lasttime), 1623 (u_long)ntohl(oml->firsttime)); 1624 oml++; 1625 items--; 1626 } 1627 } else { 1628 /* issue warning according to new info_monitor size */ 1629 checkitemsize(itemsize, sizeof(struct info_monitor)); 1630 } 1631 } 1632 1633 1634 /* 1635 * Mapping between command line strings and stat reset flags 1636 */ 1637 struct statreset { 1638 const char *str; 1639 int flag; 1640 } sreset[] = { 1641 { "io", RESET_FLAG_IO }, 1642 { "sys", RESET_FLAG_SYS }, 1643 { "mem", RESET_FLAG_MEM }, 1644 { "timer", RESET_FLAG_TIMER }, 1645 { "auth", RESET_FLAG_AUTH }, 1646 { "allpeers", RESET_FLAG_ALLPEERS }, 1647 { "", 0 } 1648 }; 1649 1650 /* 1651 * reset - reset statistic counters 1652 */ 1653 static void 1654 reset( 1655 struct parse *pcmd, 1656 FILE *fp 1657 ) 1658 { 1659 struct reset_flags rflags; 1660 int items; 1661 int itemsize; 1662 char *dummy; 1663 int i; 1664 int res; 1665 int err; 1666 1667 err = 0; 1668 rflags.flags = 0; 1669 for (res = 0; res < pcmd->nargs; res++) { 1670 for (i = 0; sreset[i].flag != 0; i++) { 1671 if (STREQ(pcmd->argval[res].string, sreset[i].str)) 1672 break; 1673 } 1674 if (sreset[i].flag == 0) { 1675 (void) fprintf(fp, "Flag %s unknown\n", 1676 pcmd->argval[res].string); 1677 err++; 1678 } else { 1679 rflags.flags |= sreset[i].flag; 1680 } 1681 } 1682 1683 if (err) { 1684 (void) fprintf(fp, "Not done due to errors\n"); 1685 return; 1686 } 1687 1688 res = doquery(IMPL_XNTPD, REQ_RESET_STATS, 1, 1, 1689 sizeof(struct reset_flags), (char *)&rflags, &items, 1690 &itemsize, &dummy, 0); 1691 1692 if (res == 0) 1693 (void) fprintf(fp, "done!\n"); 1694 return; 1695 } 1696 1697 1698 1699 /* 1700 * preset - reset stat counters for particular peers 1701 */ 1702 static void 1703 preset( 1704 struct parse *pcmd, 1705 FILE *fp 1706 ) 1707 { 1708 /* 8 is the maximum number of peers which will fit in a packet */ 1709 struct conf_unpeer plist[min(MAXARGS, 8)]; 1710 int qitems; 1711 int items; 1712 int itemsize; 1713 char *dummy; 1714 int res; 1715 1716 for (qitems = 0; qitems < min(pcmd->nargs, 8); qitems++) { 1717 plist[qitems].peeraddr = pcmd->argval[qitems].netnum; 1718 } 1719 1720 res = doquery(IMPL_XNTPD, REQ_RESET_PEER, 1, qitems, 1721 sizeof(struct conf_unpeer), (char *)plist, &items, 1722 &itemsize, &dummy, 0); 1723 1724 if (res == 0) 1725 (void) fprintf(fp, "done!\n"); 1726 } 1727 1728 1729 /* 1730 * readkeys - request the server to reread the keys file 1731 */ 1732 /*ARGSUSED*/ 1733 static void 1734 readkeys( 1735 struct parse *pcmd, 1736 FILE *fp 1737 ) 1738 { 1739 int items; 1740 int itemsize; 1741 char *dummy; 1742 int res; 1743 1744 res = doquery(IMPL_XNTPD, REQ_REREAD_KEYS, 1, 0, 0, (char *)0, 1745 &items, &itemsize, &dummy, 0); 1746 1747 if (res == 0) 1748 (void) fprintf(fp, "done!\n"); 1749 return; 1750 } 1751 1752 1753 /* 1754 * trustkey - add some keys to the trusted key list 1755 */ 1756 static void 1757 trustkey( 1758 struct parse *pcmd, 1759 FILE *fp 1760 ) 1761 { 1762 do_trustkey(pcmd, fp, REQ_TRUSTKEY); 1763 } 1764 1765 1766 /* 1767 * untrustkey - remove some keys from the trusted key list 1768 */ 1769 static void 1770 untrustkey( 1771 struct parse *pcmd, 1772 FILE *fp 1773 ) 1774 { 1775 do_trustkey(pcmd, fp, REQ_UNTRUSTKEY); 1776 } 1777 1778 1779 /* 1780 * do_trustkey - do grunge work of adding/deleting keys 1781 */ 1782 static void 1783 do_trustkey( 1784 struct parse *pcmd, 1785 FILE *fp, 1786 int req 1787 ) 1788 { 1789 u_long keyids[MAXARGS]; 1790 int i; 1791 int items; 1792 int itemsize; 1793 char *dummy; 1794 int ritems; 1795 int res; 1796 1797 ritems = 0; 1798 for (i = 0; i < pcmd->nargs; i++) { 1799 keyids[ritems++] = pcmd->argval[i].uval; 1800 } 1801 1802 res = doquery(IMPL_XNTPD, req, 1, ritems, sizeof(u_long), 1803 (char *)keyids, &items, &itemsize, &dummy, 0); 1804 1805 if (res == 0) 1806 (void) fprintf(fp, "done!\n"); 1807 return; 1808 } 1809 1810 1811 1812 /* 1813 * authinfo - obtain and print info about authentication 1814 */ 1815 /*ARGSUSED*/ 1816 static void 1817 authinfo( 1818 struct parse *pcmd, 1819 FILE *fp 1820 ) 1821 { 1822 struct info_auth *ia; 1823 int items; 1824 int itemsize; 1825 int res; 1826 1827 res = doquery(IMPL_XNTPD, REQ_AUTHINFO, 0, 0, 0, (char *)NULL, 1828 &items, &itemsize, (char **)&ia, 0); 1829 1830 if (res != 0 && items == 0) 1831 return; 1832 1833 if (!check1item(items, fp)) 1834 return; 1835 1836 if (!checkitemsize(itemsize, sizeof(struct info_auth))) 1837 return; 1838 1839 (void) fprintf(fp, "time since reset: %ld\n", 1840 (u_long)ntohl(ia->timereset)); 1841 (void) fprintf(fp, "stored keys: %ld\n", 1842 (u_long)ntohl(ia->numkeys)); 1843 (void) fprintf(fp, "free keys: %ld\n", 1844 (u_long)ntohl(ia->numfreekeys)); 1845 (void) fprintf(fp, "key lookups: %ld\n", 1846 (u_long)ntohl(ia->keylookups)); 1847 (void) fprintf(fp, "keys not found: %ld\n", 1848 (u_long)ntohl(ia->keynotfound)); 1849 (void) fprintf(fp, "uncached keys: %ld\n", 1850 (u_long)ntohl(ia->keyuncached)); 1851 (void) fprintf(fp, "encryptions: %ld\n", 1852 (u_long)ntohl(ia->encryptions)); 1853 (void) fprintf(fp, "decryptions: %ld\n", 1854 (u_long)ntohl(ia->decryptions)); 1855 (void) fprintf(fp, "expired keys: %ld\n", 1856 (u_long)ntohl(ia->expired)); 1857 } 1858 1859 1860 1861 /* 1862 * traps - obtain and print a list of traps 1863 */ 1864 /*ARGSUSED*/ 1865 static void 1866 traps( 1867 struct parse *pcmd, 1868 FILE *fp 1869 ) 1870 { 1871 int i; 1872 struct info_trap *it; 1873 int items; 1874 int itemsize; 1875 int res; 1876 1877 res = doquery(IMPL_XNTPD, REQ_TRAPS, 0, 0, 0, (char *)NULL, 1878 &items, &itemsize, (char **)&it, 0); 1879 1880 if (res != 0 && items == 0) 1881 return; 1882 1883 if (!checkitems(items, fp)) 1884 return; 1885 1886 if (!checkitemsize(itemsize, sizeof(struct info_trap))) 1887 return; 1888 1889 for (i = 0; i < items; i++ ) { 1890 if (i != 0) 1891 (void) fprintf(fp, "\n"); 1892 (void) fprintf(fp, "address %s, port %d\n", 1893 numtoa(it->trap_address), ntohs(it->trap_port)); 1894 (void) fprintf(fp, "interface: %s, ", 1895 (it->local_address == 0) 1896 ? "wildcard" 1897 : numtoa(it->local_address)); 1898 1899 if (ntohl(it->flags) & TRAP_CONFIGURED) 1900 (void) fprintf(fp, "configured\n"); 1901 else if (ntohl(it->flags) & TRAP_NONPRIO) 1902 (void) fprintf(fp, "low priority\n"); 1903 else 1904 (void) fprintf(fp, "normal priority\n"); 1905 1906 (void) fprintf(fp, "set for %ld secs, last set %ld secs ago\n", 1907 (long)ntohl(it->origtime), 1908 (long)ntohl(it->settime)); 1909 (void) fprintf(fp, "sequence %d, number of resets %ld\n", 1910 ntohs(it->sequence), 1911 (long)ntohl(it->resets)); 1912 } 1913 } 1914 1915 1916 /* 1917 * addtrap - configure a trap 1918 */ 1919 static void 1920 addtrap( 1921 struct parse *pcmd, 1922 FILE *fp 1923 ) 1924 { 1925 do_addclr_trap(pcmd, fp, REQ_ADD_TRAP); 1926 } 1927 1928 1929 /* 1930 * clrtrap - clear a trap from the server 1931 */ 1932 static void 1933 clrtrap( 1934 struct parse *pcmd, 1935 FILE *fp 1936 ) 1937 { 1938 do_addclr_trap(pcmd, fp, REQ_CLR_TRAP); 1939 } 1940 1941 1942 /* 1943 * do_addclr_trap - do grunge work of adding/deleting traps 1944 */ 1945 static void 1946 do_addclr_trap( 1947 struct parse *pcmd, 1948 FILE *fp, 1949 int req 1950 ) 1951 { 1952 struct conf_trap ctrap; 1953 int items; 1954 int itemsize; 1955 char *dummy; 1956 int res; 1957 1958 ctrap.trap_address = pcmd->argval[0].netnum; 1959 ctrap.local_address = 0; 1960 ctrap.trap_port = htons(TRAPPORT); 1961 ctrap.unused = 0; 1962 1963 if (pcmd->nargs > 1) { 1964 ctrap.trap_port 1965 = htons((u_short)(pcmd->argval[1].uval & 0xffff)); 1966 if (pcmd->nargs > 2) 1967 ctrap.local_address = pcmd->argval[2].netnum; 1968 } 1969 1970 res = doquery(IMPL_XNTPD, req, 1, 1, sizeof(struct conf_trap), 1971 (char *)&ctrap, &items, &itemsize, &dummy, 0); 1972 1973 if (res == 0) 1974 (void) fprintf(fp, "done!\n"); 1975 return; 1976 } 1977 1978 1979 1980 /* 1981 * requestkey - change the server's request key (a dangerous request) 1982 */ 1983 static void 1984 requestkey( 1985 struct parse *pcmd, 1986 FILE *fp 1987 ) 1988 { 1989 do_changekey(pcmd, fp, REQ_REQUEST_KEY); 1990 } 1991 1992 1993 /* 1994 * controlkey - change the server's control key 1995 */ 1996 static void 1997 controlkey( 1998 struct parse *pcmd, 1999 FILE *fp 2000 ) 2001 { 2002 do_changekey(pcmd, fp, REQ_CONTROL_KEY); 2003 } 2004 2005 2006 2007 /* 2008 * do_changekey - do grunge work of changing keys 2009 */ 2010 static void 2011 do_changekey( 2012 struct parse *pcmd, 2013 FILE *fp, 2014 int req 2015 ) 2016 { 2017 u_long key; 2018 int items; 2019 int itemsize; 2020 char *dummy; 2021 int res; 2022 2023 2024 key = htonl((u_int32)pcmd->argval[0].uval); 2025 2026 res = doquery(IMPL_XNTPD, req, 1, 1, sizeof(u_int32), 2027 (char *)&key, &items, &itemsize, &dummy, 0); 2028 2029 if (res == 0) 2030 (void) fprintf(fp, "done!\n"); 2031 return; 2032 } 2033 2034 2035 2036 /* 2037 * ctlstats - obtain and print info about authentication 2038 */ 2039 /*ARGSUSED*/ 2040 static void 2041 ctlstats( 2042 struct parse *pcmd, 2043 FILE *fp 2044 ) 2045 { 2046 struct info_control *ic; 2047 int items; 2048 int itemsize; 2049 int res; 2050 2051 res = doquery(IMPL_XNTPD, REQ_GET_CTLSTATS, 0, 0, 0, (char *)NULL, 2052 &items, &itemsize, (char **)&ic, 0); 2053 2054 if (res != 0 && items == 0) 2055 return; 2056 2057 if (!check1item(items, fp)) 2058 return; 2059 2060 if (!checkitemsize(itemsize, sizeof(struct info_control))) 2061 return; 2062 2063 (void) fprintf(fp, "time since reset: %ld\n", 2064 (u_long)ntohl(ic->ctltimereset)); 2065 (void) fprintf(fp, "requests received: %ld\n", 2066 (u_long)ntohl(ic->numctlreq)); 2067 (void) fprintf(fp, "responses sent: %ld\n", 2068 (u_long)ntohl(ic->numctlresponses)); 2069 (void) fprintf(fp, "fragments sent: %ld\n", 2070 (u_long)ntohl(ic->numctlfrags)); 2071 (void) fprintf(fp, "async messages sent: %ld\n", 2072 (u_long)ntohl(ic->numasyncmsgs)); 2073 (void) fprintf(fp, "error msgs sent: %ld\n", 2074 (u_long)ntohl(ic->numctlerrors)); 2075 (void) fprintf(fp, "total bad pkts: %ld\n", 2076 (u_long)ntohl(ic->numctlbadpkts)); 2077 (void) fprintf(fp, "packet too short: %ld\n", 2078 (u_long)ntohl(ic->numctltooshort)); 2079 (void) fprintf(fp, "response on input: %ld\n", 2080 (u_long)ntohl(ic->numctlinputresp)); 2081 (void) fprintf(fp, "fragment on input: %ld\n", 2082 (u_long)ntohl(ic->numctlinputfrag)); 2083 (void) fprintf(fp, "error set on input: %ld\n", 2084 (u_long)ntohl(ic->numctlinputerr)); 2085 (void) fprintf(fp, "bad offset on input: %ld\n", 2086 (u_long)ntohl(ic->numctlbadoffset)); 2087 (void) fprintf(fp, "bad version packets: %ld\n", 2088 (u_long)ntohl(ic->numctlbadversion)); 2089 (void) fprintf(fp, "data in pkt too short: %ld\n", 2090 (u_long)ntohl(ic->numctldatatooshort)); 2091 (void) fprintf(fp, "unknown op codes: %ld\n", 2092 (u_long)ntohl(ic->numctlbadop)); 2093 } 2094 2095 2096 /* 2097 * clockstat - get and print clock status information 2098 */ 2099 static void 2100 clockstat( 2101 struct parse *pcmd, 2102 FILE *fp 2103 ) 2104 { 2105 struct info_clock *cl; 2106 /* 8 is the maximum number of clocks which will fit in a packet */ 2107 u_long clist[min(MAXARGS, 8)]; 2108 int qitems; 2109 int items; 2110 int itemsize; 2111 int res; 2112 l_fp ts; 2113 struct clktype *clk; 2114 u_long ltemp; 2115 2116 for (qitems = 0; qitems < min(pcmd->nargs, 8); qitems++) 2117 clist[qitems] = pcmd->argval[qitems].netnum; 2118 2119 res = doquery(IMPL_XNTPD, REQ_GET_CLOCKINFO, 0, qitems, 2120 sizeof(u_int32), (char *)clist, &items, 2121 &itemsize, (char **)&cl, 0); 2122 2123 if (res != 0 && items == 0) 2124 return; 2125 2126 if (!checkitems(items, fp)) 2127 return; 2128 2129 if (!checkitemsize(itemsize, sizeof(struct info_clock))) 2130 return; 2131 2132 while (items-- > 0) { 2133 (void) fprintf(fp, "clock address: %s\n", 2134 numtoa(cl->clockadr)); 2135 for (clk = clktypes; clk->code >= 0; clk++) 2136 if (clk->code == cl->type) 2137 break; 2138 if (clk->code >= 0) 2139 (void) fprintf(fp, "clock type: %s\n", 2140 clk->clocktype); 2141 else 2142 (void) fprintf(fp, "clock type: unknown type (%d)\n", 2143 cl->type); 2144 (void) fprintf(fp, "last event: %d\n", 2145 cl->lastevent); 2146 (void) fprintf(fp, "current status: %d\n", 2147 cl->currentstatus); 2148 (void) fprintf(fp, "number of polls: %lu\n", 2149 (u_long)ntohl(cl->polls)); 2150 (void) fprintf(fp, "no response to poll: %lu\n", 2151 (u_long)ntohl(cl->noresponse)); 2152 (void) fprintf(fp, "bad format responses: %lu\n", 2153 (u_long)ntohl(cl->badformat)); 2154 (void) fprintf(fp, "bad data responses: %lu\n", 2155 (u_long)ntohl(cl->baddata)); 2156 (void) fprintf(fp, "running time: %lu\n", 2157 (u_long)ntohl(cl->timestarted)); 2158 NTOHL_FP(&cl->fudgetime1, &ts); 2159 (void) fprintf(fp, "fudge time 1: %s\n", 2160 lfptoa(&ts, 6)); 2161 NTOHL_FP(&cl->fudgetime2, &ts); 2162 (void) fprintf(fp, "fudge time 2: %s\n", 2163 lfptoa(&ts, 6)); 2164 (void) fprintf(fp, "stratum: %ld\n", 2165 (u_long)ntohl(cl->fudgeval1)); 2166 ltemp = ntohl(cl->fudgeval2); 2167 (void) fprintf(fp, "reference ID: %s\n", 2168 (char *)<emp); 2169 (void) fprintf(fp, "fudge flags: 0x%x\n", 2170 cl->flags); 2171 2172 if (items > 0) 2173 (void) fprintf(fp, "\n"); 2174 cl++; 2175 } 2176 } 2177 2178 2179 /* 2180 * fudge - set clock fudge factors 2181 */ 2182 static void 2183 fudge( 2184 struct parse *pcmd, 2185 FILE *fp 2186 ) 2187 { 2188 struct conf_fudge fudgedata; 2189 int items; 2190 int itemsize; 2191 char *dummy; 2192 l_fp ts; 2193 int res; 2194 long val; 2195 u_long u_val; 2196 int err; 2197 2198 2199 err = 0; 2200 memset((char *)&fudgedata, 0, sizeof fudgedata); 2201 fudgedata.clockadr = pcmd->argval[0].netnum; 2202 2203 if (STREQ(pcmd->argval[1].string, "time1")) { 2204 fudgedata.which = htonl(FUDGE_TIME1); 2205 if (!atolfp(pcmd->argval[2].string, &ts)) 2206 err = 1; 2207 else 2208 NTOHL_FP(&ts, &fudgedata.fudgetime); 2209 } else if (STREQ(pcmd->argval[1].string, "time2")) { 2210 fudgedata.which = htonl(FUDGE_TIME2); 2211 if (!atolfp(pcmd->argval[2].string, &ts)) 2212 err = 1; 2213 else 2214 NTOHL_FP(&ts, &fudgedata.fudgetime); 2215 } else if (STREQ(pcmd->argval[1].string, "val1")) { 2216 fudgedata.which = htonl(FUDGE_VAL1); 2217 if (!atoint(pcmd->argval[2].string, &val)) 2218 err = 1; 2219 else 2220 fudgedata.fudgeval_flags = htonl(val); 2221 } else if (STREQ(pcmd->argval[1].string, "val2")) { 2222 fudgedata.which = htonl(FUDGE_VAL2); 2223 if (!atoint(pcmd->argval[2].string, &val)) 2224 err = 1; 2225 else 2226 fudgedata.fudgeval_flags = htonl((u_int32)val); 2227 } else if (STREQ(pcmd->argval[1].string, "flags")) { 2228 fudgedata.which = htonl(FUDGE_FLAGS); 2229 if (!hextoint(pcmd->argval[2].string, &u_val)) 2230 err = 1; 2231 else 2232 fudgedata.fudgeval_flags = htonl((u_int32)(u_val & 0xf)); 2233 } else { 2234 (void) fprintf(stderr, "What fudge is %s?\n", 2235 pcmd->argval[1].string); 2236 return; 2237 } 2238 2239 if (err) { 2240 (void) fprintf(stderr, "Unknown fudge parameter %s\n", 2241 pcmd->argval[2].string); 2242 return; 2243 } 2244 2245 2246 res = doquery(IMPL_XNTPD, REQ_SET_CLKFUDGE, 1, 1, 2247 sizeof(struct conf_fudge), (char *)&fudgedata, &items, 2248 &itemsize, &dummy, 0); 2249 2250 if (res == 0) 2251 (void) fprintf(fp, "done!\n"); 2252 return; 2253 } 2254 2255 /* 2256 * clkbug - get and print clock debugging information 2257 */ 2258 static void 2259 clkbug( 2260 struct parse *pcmd, 2261 FILE *fp 2262 ) 2263 { 2264 register int i; 2265 register int n; 2266 register u_int32 s; 2267 struct info_clkbug *cl; 2268 /* 8 is the maximum number of clocks which will fit in a packet */ 2269 u_long clist[min(MAXARGS, 8)]; 2270 u_int32 ltemp; 2271 int qitems; 2272 int items; 2273 int itemsize; 2274 int res; 2275 int needsp; 2276 l_fp ts; 2277 2278 for (qitems = 0; qitems < min(pcmd->nargs, 8); qitems++) 2279 clist[qitems] = pcmd->argval[qitems].netnum; 2280 2281 res = doquery(IMPL_XNTPD, REQ_GET_CLKBUGINFO, 0, qitems, 2282 sizeof(u_int32), (char *)clist, &items, 2283 &itemsize, (char **)&cl, 0); 2284 2285 if (res != 0 && items == 0) 2286 return; 2287 2288 if (!checkitems(items, fp)) 2289 return; 2290 2291 if (!checkitemsize(itemsize, sizeof(struct info_clkbug))) 2292 return; 2293 2294 while (items-- > 0) { 2295 (void) fprintf(fp, "clock address: %s\n", 2296 numtoa(cl->clockadr)); 2297 n = (int)cl->nvalues; 2298 (void) fprintf(fp, "values: %d", n); 2299 s = ntohs(cl->svalues); 2300 if (n > NUMCBUGVALUES) 2301 n = NUMCBUGVALUES; 2302 for (i = 0; i < n; i++) { 2303 ltemp = ntohl(cl->values[i]); 2304 ltemp &= 0xffffffff; /* HMS: This does nothing now */ 2305 if ((i & 0x3) == 0) 2306 (void) fprintf(fp, "\n"); 2307 if (s & (1 << i)) 2308 (void) fprintf(fp, "%12ld", (u_long)ltemp); 2309 else 2310 (void) fprintf(fp, "%12lu", (u_long)ltemp); 2311 } 2312 (void) fprintf(fp, "\n"); 2313 2314 n = (int)cl->ntimes; 2315 (void) fprintf(fp, "times: %d", n); 2316 s = ntohl(cl->stimes); 2317 if (n > NUMCBUGTIMES) 2318 n = NUMCBUGTIMES; 2319 needsp = 0; 2320 for (i = 0; i < n; i++) { 2321 if ((i & 0x1) == 0) { 2322 (void) fprintf(fp, "\n"); 2323 } else { 2324 for (;needsp > 0; needsp--) 2325 putc(' ', fp); 2326 } 2327 NTOHL_FP(&cl->times[i], &ts); 2328 if (s & (1 << i)) { 2329 (void) fprintf(fp, "%17s", 2330 lfptoa(&ts, 6)); 2331 needsp = 22; 2332 } else { 2333 (void) fprintf(fp, "%37s", 2334 uglydate(&ts)); 2335 needsp = 2; 2336 } 2337 } 2338 (void) fprintf(fp, "\n"); 2339 if (items > 0) { 2340 cl++; 2341 (void) fprintf(fp, "\n"); 2342 } 2343 } 2344 } 2345 2346 2347 /* 2348 * kerninfo - display the kernel pll/pps variables 2349 */ 2350 static void 2351 kerninfo( 2352 struct parse *pcmd, 2353 FILE *fp 2354 ) 2355 { 2356 struct info_kernel *ik; 2357 int items; 2358 int itemsize; 2359 int res; 2360 unsigned status; 2361 double tscale = 1e-6; 2362 2363 res = doquery(IMPL_XNTPD, REQ_GET_KERNEL, 0, 0, 0, (char *)NULL, 2364 &items, &itemsize, (char **)&ik, 0); 2365 if (res != 0 && items == 0) 2366 return; 2367 if (!check1item(items, fp)) 2368 return; 2369 if (!checkitemsize(itemsize, sizeof(struct info_kernel))) 2370 return; 2371 2372 status = ntohs(ik->status) & 0xffff; 2373 /* 2374 * pll variables. We know more than we should about the NANO bit. 2375 */ 2376 #ifdef STA_NANO 2377 if (status & STA_NANO) 2378 tscale = 1e-9; 2379 #endif 2380 (void)fprintf(fp, "pll offset: %g s\n", 2381 (long)ntohl(ik->offset) * tscale); 2382 (void)fprintf(fp, "pll frequency: %s ppm\n", 2383 fptoa((s_fp)ntohl(ik->freq), 3)); 2384 (void)fprintf(fp, "maximum error: %g s\n", 2385 (u_long)ntohl(ik->maxerror) * 1e-6); 2386 (void)fprintf(fp, "estimated error: %g s\n", 2387 (u_long)ntohl(ik->esterror) * 1e-6); 2388 (void)fprintf(fp, "status: %04x ", status); 2389 #ifdef STA_PLL 2390 if (status & STA_PLL) (void)fprintf(fp, " pll"); 2391 #endif 2392 #ifdef STA_PPSFREQ 2393 if (status & STA_PPSFREQ) (void)fprintf(fp, " ppsfreq"); 2394 #endif 2395 #ifdef STA_PPSTIME 2396 if (status & STA_PPSTIME) (void)fprintf(fp, " ppstime"); 2397 #endif 2398 #ifdef STA_FLL 2399 if (status & STA_FLL) (void)fprintf(fp, " fll"); 2400 #endif 2401 #ifdef STA_INS 2402 if (status & STA_INS) (void)fprintf(fp, " ins"); 2403 #endif 2404 #ifdef STA_DEL 2405 if (status & STA_DEL) (void)fprintf(fp, " del"); 2406 #endif 2407 #ifdef STA_UNSYNC 2408 if (status & STA_UNSYNC) (void)fprintf(fp, " unsync"); 2409 #endif 2410 #ifdef STA_FREQHOLD 2411 if (status & STA_FREQHOLD) (void)fprintf(fp, " freqhold"); 2412 #endif 2413 #ifdef STA_PPSSIGNAL 2414 if (status & STA_PPSSIGNAL) (void)fprintf(fp, " ppssignal"); 2415 #endif 2416 #ifdef STA_PPSJITTER 2417 if (status & STA_PPSJITTER) (void)fprintf(fp, " ppsjitter"); 2418 #endif 2419 #ifdef STA_PPSWANDER 2420 if (status & STA_PPSWANDER) (void)fprintf(fp, " ppswander"); 2421 #endif 2422 #ifdef STA_PPSERROR 2423 if (status & STA_PPSERROR) (void)fprintf(fp, " ppserror"); 2424 #endif 2425 #ifdef STA_CLOCKERR 2426 if (status & STA_CLOCKERR) (void)fprintf(fp, " clockerr"); 2427 #endif 2428 #ifdef STA_NANO 2429 if (status & STA_NANO) (void)fprintf(fp, " nano"); 2430 #endif 2431 #ifdef STA_MODE 2432 if (status & STA_MODE) (void)fprintf(fp, " mode=fll"); 2433 #endif 2434 #ifdef STA_CLK 2435 if (status & STA_CLK) (void)fprintf(fp, " src=B"); 2436 #endif 2437 (void)fprintf(fp, "\n"); 2438 (void)fprintf(fp, "pll time constant: %ld\n", 2439 (u_long)ntohl(ik->constant)); 2440 (void)fprintf(fp, "precision: %g s\n", 2441 (u_long)ntohl(ik->precision) * tscale); 2442 (void)fprintf(fp, "frequency tolerance: %s ppm\n", 2443 fptoa((s_fp)ntohl(ik->tolerance), 0)); 2444 2445 /* 2446 * For backwards compatibility (ugh), we find the pps variables 2447 * only if the shift member is nonzero. 2448 */ 2449 if (!ik->shift) 2450 return; 2451 2452 /* 2453 * pps variables 2454 */ 2455 (void)fprintf(fp, "pps frequency: %s ppm\n", 2456 fptoa((s_fp)ntohl(ik->ppsfreq), 3)); 2457 (void)fprintf(fp, "pps stability: %s ppm\n", 2458 fptoa((s_fp)ntohl(ik->stabil), 3)); 2459 (void)fprintf(fp, "pps jitter: %g s\n", 2460 (u_long)ntohl(ik->jitter) * tscale); 2461 (void)fprintf(fp, "calibration interval: %d s\n", 2462 1 << ntohs(ik->shift)); 2463 (void)fprintf(fp, "calibration cycles: %ld\n", 2464 (u_long)ntohl(ik->calcnt)); 2465 (void)fprintf(fp, "jitter exceeded: %ld\n", 2466 (u_long)ntohl(ik->jitcnt)); 2467 (void)fprintf(fp, "stability exceeded: %ld\n", 2468 (u_long)ntohl(ik->stbcnt)); 2469 (void)fprintf(fp, "calibration errors: %ld\n", 2470 (u_long)ntohl(ik->errcnt)); 2471 } 2472