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