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