/contrib/ntp/ntpdc/ntpdc_ops.c
C | 3204 lines | 2646 code | 348 blank | 210 comment | 641 complexity | 33377576bde5c816cdfcd6b3cbb75390 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
1/* 2 * ntpdc_ops.c - subroutines which are called to perform operations by xntpdc 3 */ 4 5#ifdef HAVE_CONFIG_H 6# include <config.h> 7#endif 8 9#include <stdio.h> 10#include <stddef.h> 11 12#include "ntpdc.h" 13#include "ntp_control.h" 14#include "ntp_refclock.h" 15#include "ntp_stdlib.h" 16 17#include <ctype.h> 18#ifdef HAVE_SYS_TIMEX_H 19# include <sys/timex.h> 20#endif 21#if !defined(__bsdi__) && !defined(apollo) 22#include <netinet/in.h> 23#endif 24 25#include <arpa/inet.h> 26 27/* 28 * Declarations for command handlers in here 29 */ 30static int checkitems P((int, FILE *)); 31static int checkitemsize P((int, int)); 32static int check1item P((int, FILE *)); 33static void peerlist P((struct parse *, FILE *)); 34static void peers P((struct parse *, FILE *)); 35static void doconfig P((struct parse *pcmd, FILE *fp, int mode, int refc)); 36static void dmpeers P((struct parse *, FILE *)); 37static void dopeers P((struct parse *, FILE *, int)); 38static void printpeer P((struct info_peer *, FILE *)); 39static void showpeer P((struct parse *, FILE *)); 40static void peerstats P((struct parse *, FILE *)); 41static void loopinfo P((struct parse *, FILE *)); 42static void sysinfo P((struct parse *, FILE *)); 43static void sysstats P((struct parse *, FILE *)); 44static void iostats P((struct parse *, FILE *)); 45static void memstats P((struct parse *, FILE *)); 46static void timerstats P((struct parse *, FILE *)); 47static void addpeer P((struct parse *, FILE *)); 48static void addserver P((struct parse *, FILE *)); 49static void addrefclock P((struct parse *, FILE *)); 50static void broadcast P((struct parse *, FILE *)); 51static void doconfig P((struct parse *, FILE *, int, int)); 52static void unconfig P((struct parse *, FILE *)); 53static void set P((struct parse *, FILE *)); 54static void sys_clear P((struct parse *, FILE *)); 55static void doset P((struct parse *, FILE *, int)); 56static void reslist P((struct parse *, FILE *)); 57static void new_restrict P((struct parse *, FILE *)); 58static void unrestrict P((struct parse *, FILE *)); 59static void delrestrict P((struct parse *, FILE *)); 60static void do_restrict P((struct parse *, FILE *, int)); 61static void monlist P((struct parse *, FILE *)); 62static void reset P((struct parse *, FILE *)); 63static void preset P((struct parse *, FILE *)); 64static void readkeys P((struct parse *, FILE *)); 65static void trustkey P((struct parse *, FILE *)); 66static void untrustkey P((struct parse *, FILE *)); 67static void do_trustkey P((struct parse *, FILE *, int)); 68static void authinfo P((struct parse *, FILE *)); 69static void traps P((struct parse *, FILE *)); 70static void addtrap P((struct parse *, FILE *)); 71static void clrtrap P((struct parse *, FILE *)); 72static void do_addclr_trap P((struct parse *, FILE *, int)); 73static void requestkey P((struct parse *, FILE *)); 74static void controlkey P((struct parse *, FILE *)); 75static void do_changekey P((struct parse *, FILE *, int)); 76static void ctlstats P((struct parse *, FILE *)); 77static void clockstat P((struct parse *, FILE *)); 78static void fudge P((struct parse *, FILE *)); 79static void clkbug P((struct parse *, FILE *)); 80static void kerninfo P((struct parse *, FILE *)); 81static void get_if_stats P((struct parse *, FILE *)); 82static void do_if_reload P((struct parse *, FILE *)); 83 84/* 85 * Commands we understand. Ntpdc imports this. 86 */ 87struct xcmd opcmds[] = { 88 { "listpeers", peerlist, { OPT|IP_VERSION, NO, NO, NO }, 89 { "-4|-6", "", "", "" }, 90 "display list of peers the server knows about [IP Version]" }, 91 { "peers", peers, { OPT|IP_VERSION, NO, NO, NO }, 92 { "-4|-6", "", "", "" }, 93 "display peer summary information [IP Version]" }, 94 { "dmpeers", dmpeers, { OPT|IP_VERSION, NO, NO, NO }, 95 { "-4|-6", "", "", "" }, 96 "display peer summary info the way Dave Mills likes it (IP Version)" }, 97 { "showpeer", showpeer, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD}, 98 { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 99 "display detailed information for one or more peers" }, 100 { "pstats", peerstats, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 101 { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 102 "display statistical information for one or more peers" }, 103 { "loopinfo", loopinfo, { OPT|NTP_STR, NO, NO, NO }, 104 { "oneline|multiline", "", "", "" }, 105 "display loop filter information" }, 106 { "sysinfo", sysinfo, { NO, NO, NO, NO }, 107 { "", "", "", "" }, 108 "display local server information" }, 109 { "sysstats", sysstats, { NO, NO, NO, NO }, 110 { "", "", "", "" }, 111 "display local server statistics" }, 112 { "memstats", memstats, { NO, NO, NO, NO }, 113 { "", "", "", "" }, 114 "display peer memory usage statistics" }, 115 { "iostats", iostats, { NO, NO, NO, NO }, 116 { "", "", "", "" }, 117 "display I/O subsystem statistics" }, 118 { "timerstats", timerstats, { NO, NO, NO, NO }, 119 { "", "", "", "" }, 120 "display event timer subsystem statistics" }, 121 { "addpeer", addpeer, { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 122 { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." }, 123 "configure a new peer association" }, 124 { "addserver", addserver, { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 125 { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." }, 126 "configure a new server" }, 127 { "addrefclock",addrefclock, { NTP_ADD, OPT|NTP_UINT, OPT|NTP_STR, OPT|NTP_STR }, 128 { "addr", "mode", "minpoll|prefer", "minpoll|prefer" }, 129 "configure a new server" }, 130 { "broadcast", broadcast, { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 131 { "addr", "keyid", "version", "minpoll" }, 132 "configure broadcasting time service" }, 133 { "unconfig", unconfig, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 134 { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 135 "unconfigure existing peer assocations" }, 136 { "enable", set, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 137 { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." }, 138 "set a system flag (auth, bclient, monitor, pll, kernel, stats)" }, 139 { "disable", sys_clear, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 140 { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." }, 141 "clear a system flag (auth, bclient, monitor, pll, kernel, stats)" }, 142 { "reslist", reslist, {OPT|IP_VERSION, NO, NO, NO }, 143 { "-4|-6", "", "", "" }, 144 "display the server's restrict list" }, 145 { "restrict", new_restrict, { NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR }, 146 { "address", "mask", 147 "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod", 148 "..." }, 149 "create restrict entry/add flags to entry" }, 150 { "unrestrict", unrestrict, { NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR }, 151 { "address", "mask", 152 "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod", 153 "..." }, 154 "remove flags from a restrict entry" }, 155 { "delrestrict", delrestrict, { NTP_ADD, NTP_ADD, OPT|NTP_STR, NO }, 156 { "address", "mask", "ntpport", "" }, 157 "delete a restrict entry" }, 158 { "monlist", monlist, { OPT|NTP_INT, NO, NO, NO }, 159 { "version", "", "", "" }, 160 "display data the server's monitor routines have collected" }, 161 { "reset", reset, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 162 { "io|sys|mem|timer|auth|allpeers", "...", "...", "..." }, 163 "reset various subsystem statistics counters" }, 164 { "preset", preset, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 165 { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 166 "reset stat counters associated with particular peer(s)" }, 167 { "readkeys", readkeys, { NO, NO, NO, NO }, 168 { "", "", "", "" }, 169 "request a reread of the keys file and re-init of system keys" }, 170 { "trustedkey", trustkey, { NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT }, 171 { "keyid", "keyid", "keyid", "keyid" }, 172 "add one or more key ID's to the trusted list" }, 173 { "untrustedkey", untrustkey, { NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT }, 174 { "keyid", "keyid", "keyid", "keyid" }, 175 "remove one or more key ID's from the trusted list" }, 176 { "authinfo", authinfo, { NO, NO, NO, NO }, 177 { "", "", "", "" }, 178 "display the state of the authentication code" }, 179 { "traps", traps, { NO, NO, NO, NO }, 180 { "", "", "", "" }, 181 "display the traps set in the server" }, 182 { "addtrap", addtrap, { NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO }, 183 { "address", "port", "interface", "" }, 184 "configure a trap in the server" }, 185 { "clrtrap", clrtrap, { NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO }, 186 { "address", "port", "interface", "" }, 187 "remove a trap (configured or otherwise) from the server" }, 188 { "requestkey", requestkey, { NTP_UINT, NO, NO, NO }, 189 { "keyid", "", "", "" }, 190 "change the keyid the server uses to authenticate requests" }, 191 { "controlkey", controlkey, { NTP_UINT, NO, NO, NO }, 192 { "keyid", "", "", "" }, 193 "change the keyid the server uses to authenticate control messages" }, 194 { "ctlstats", ctlstats, { NO, NO, NO, NO }, 195 { "", "", "", "" }, 196 "display packet count statistics from the control module" }, 197 { "clockstat", clockstat, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 198 { "address", "address", "address", "address" }, 199 "display clock status information" }, 200 { "fudge", fudge, { NTP_ADD, NTP_STR, NTP_STR, NO }, 201 { "address", "time1|time2|val1|val2|flags", "value", "" }, 202 "set/change one of a clock's fudge factors" }, 203 { "clkbug", clkbug, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 204 { "address", "address", "address", "address" }, 205 "display clock debugging information" }, 206 { "kerninfo", kerninfo, { NO, NO, NO, NO }, 207 { "", "", "", "" }, 208 "display the kernel pll/pps variables" }, 209 { "ifstats", get_if_stats, { NO, NO, NO, NO }, 210 { "", "", "", "" }, 211 "list interface statistics" }, 212 { "ifreload", do_if_reload, { NO, NO, NO, NO }, 213 { "", "", "", "" }, 214 "reload interface configuration" }, 215 { 0, 0, { NO, NO, NO, NO }, 216 { "", "", "", "" }, "" } 217}; 218 219/* 220 * For quick string comparisons 221 */ 222#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) 223 224 225/* 226 * checkitems - utility to print a message if no items were returned 227 */ 228static int 229checkitems( 230 int items, 231 FILE *fp 232 ) 233{ 234 if (items == 0) { 235 (void) fprintf(fp, "No data returned in response to query\n"); 236 return 0; 237 } 238 return 1; 239} 240 241 242/* 243 * checkitemsize - utility to print a message if the item size is wrong 244 */ 245static int 246checkitemsize( 247 int itemsize, 248 int expected 249 ) 250{ 251 if (itemsize != expected) { 252 (void) fprintf(stderr, 253 "***Incorrect item size returned by remote host (%d should be %d)\n", 254 itemsize, expected); 255 return 0; 256 } 257 return 1; 258} 259 260 261/* 262 * check1item - check to make sure we have exactly one item 263 */ 264static int 265check1item( 266 int items, 267 FILE *fp 268 ) 269{ 270 if (items == 0) { 271 (void) fprintf(fp, "No data returned in response to query\n"); 272 return 0; 273 } 274 if (items > 1) { 275 (void) fprintf(fp, "Expected one item in response, got %d\n", 276 items); 277 return 0; 278 } 279 return 1; 280} 281 282 283 284/* 285 * peerlist - get a short list of peers 286 */ 287/*ARGSUSED*/ 288static void 289peerlist( 290 struct parse *pcmd, 291 FILE *fp 292 ) 293{ 294 struct info_peer_list *plist; 295 struct sockaddr_storage paddr; 296 int items; 297 int itemsize; 298 int res; 299 300again: 301 res = doquery(impl_ver, REQ_PEER_LIST, 0, 0, 0, (char *)NULL, &items, 302 &itemsize, (void *)&plist, 0, 303 sizeof(struct info_peer_list)); 304 305 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 306 impl_ver = IMPL_XNTPD_OLD; 307 goto again; 308 } 309 310 if (res != 0) 311 return; 312 313 if (!checkitems(items, fp)) 314 return; 315 316 if (!checkitemsize(itemsize, sizeof(struct info_peer_list)) && 317 !checkitemsize(itemsize, v4sizeof(struct info_peer_list))) 318 return; 319 320 while (items > 0) { 321 memset((char *)&paddr, 0, sizeof(paddr)); 322 if (plist->v6_flag != 0) { 323 GET_INADDR6(paddr) = plist->addr6; 324 paddr.ss_family = AF_INET6; 325 } else { 326 GET_INADDR(paddr) = plist->addr; 327 paddr.ss_family = AF_INET; 328 } 329#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 330 paddr.ss_len = SOCKLEN(&paddr); 331#endif 332 if ((pcmd->nargs == 0) || 333 ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) || 334 ((pcmd->argval->ival == 4) && (plist->v6_flag == 0))) 335 (void) fprintf(fp, "%-9s %s\n", 336 modetoa(plist->hmode), 337 nntohost(&paddr)); 338 plist++; 339 items--; 340 } 341} 342 343 344/* 345 * peers - show peer summary 346 */ 347static void 348peers( 349 struct parse *pcmd, 350 FILE *fp 351 ) 352{ 353 dopeers(pcmd, fp, 0); 354} 355 356/* 357 * dmpeers - show peer summary, Dave Mills style 358 */ 359static void 360dmpeers( 361 struct parse *pcmd, 362 FILE *fp 363 ) 364{ 365 dopeers(pcmd, fp, 1); 366} 367 368 369/* 370 * peers - show peer summary 371 */ 372/*ARGSUSED*/ 373static void 374dopeers( 375 struct parse *pcmd, 376 FILE *fp, 377 int dmstyle 378 ) 379{ 380 struct info_peer_summary *plist; 381 struct sockaddr_storage dstadr; 382 struct sockaddr_storage srcadr; 383 int items; 384 int itemsize; 385 int ntp_poll; 386 int res; 387 int c; 388 l_fp tempts; 389 390again: 391 res = doquery(impl_ver, REQ_PEER_LIST_SUM, 0, 0, 0, (char *)NULL, 392 &items, &itemsize, (void *)&plist, 0, 393 sizeof(struct info_peer_summary)); 394 395 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 396 impl_ver = IMPL_XNTPD_OLD; 397 goto again; 398 } 399 400 if (res != 0) 401 return; 402 403 if (!checkitems(items, fp)) 404 return; 405 406 if (!checkitemsize(itemsize, sizeof(struct info_peer_summary)) && 407 !checkitemsize(itemsize, v4sizeof(struct info_peer_summary))) 408 return; 409 410 (void) fprintf(fp, 411 " remote local st poll reach delay offset disp\n"); 412 (void) fprintf(fp, 413 "=======================================================================\n"); 414 while (items > 0) { 415 if (!dmstyle) { 416 if (plist->flags & INFO_FLAG_SYSPEER) 417 c = '*'; 418 else if (plist->hmode == MODE_ACTIVE) 419 c = '+'; 420 else if (plist->hmode == MODE_PASSIVE) 421 c = '-'; 422 else if (plist->hmode == MODE_CLIENT) 423 c = '='; 424 else if (plist->hmode == MODE_BROADCAST) 425 c = '^'; 426 else if (plist->hmode == MODE_BCLIENT) 427 c = '~'; 428 else 429 c = ' '; 430 } else { 431 if (plist->flags & INFO_FLAG_SYSPEER) 432 c = '*'; 433 else if (plist->flags & INFO_FLAG_SHORTLIST) 434 c = '+'; 435 else if (plist->flags & INFO_FLAG_SEL_CANDIDATE) 436 c = '.'; 437 else 438 c = ' '; 439 } 440 NTOHL_FP(&(plist->offset), &tempts); 441 ntp_poll = 1<<max(min3(plist->ppoll, plist->hpoll, NTP_MAXPOLL), 442 NTP_MINPOLL); 443 memset((char *)&dstadr, 0, sizeof(dstadr)); 444 memset((char *)&srcadr, 0, sizeof(srcadr)); 445 if (plist->v6_flag != 0) { 446 GET_INADDR6(dstadr) = plist->dstadr6; 447 GET_INADDR6(srcadr) = plist->srcadr6; 448 srcadr.ss_family = AF_INET6; 449 dstadr.ss_family = AF_INET6; 450 } else { 451 GET_INADDR(dstadr) = plist->dstadr; 452 GET_INADDR(srcadr) = plist->srcadr; 453 srcadr.ss_family = AF_INET; 454 dstadr.ss_family = AF_INET; 455 } 456#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 457 srcadr.ss_len = SOCKLEN(&srcadr); 458 dstadr.ss_len = SOCKLEN(&dstadr); 459#endif 460 if ((pcmd->nargs == 0) || 461 ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) || 462 ((pcmd->argval->ival == 4) && (plist->v6_flag == 0))) 463 (void) fprintf(fp, 464 "%c%-15.15s %-15.15s %2d %4d %3o %7.7s %9.9s %7.7s\n", 465 c, nntohost(&srcadr), stoa(&dstadr), 466 plist->stratum, ntp_poll, plist->reach, 467 fptoa(NTOHS_FP(plist->delay), 5), 468 lfptoa(&tempts, 6), 469 ufptoa(NTOHS_FP(plist->dispersion), 5)); 470 plist++; 471 items--; 472 } 473} 474 475/* Convert a refid & stratum (in host order) to a string */ 476static char* 477refid_string( 478 u_int32 refid, 479 int stratum 480 ) 481{ 482 if (stratum <= 1) { 483 static char junk[5]; 484 junk[4] = 0; 485 memmove(junk, (char *)&refid, 4); 486 return junk; 487 } 488 489 return numtoa(refid); 490} 491 492static void 493print_pflag( 494 FILE *fp, 495 u_int32 flags 496 ) 497{ 498 const char *str; 499 500 if (flags == 0) { 501 (void) fprintf(fp, " none\n"); 502 } else { 503 str = ""; 504 if (flags & INFO_FLAG_SYSPEER) { 505 (void) fprintf(fp, " system_peer"); 506 str = ","; 507 } 508 if (flags & INFO_FLAG_CONFIG) { 509 (void) fprintf(fp, "%s config", str); 510 str = ","; 511 } 512 if (flags & INFO_FLAG_REFCLOCK) { 513 (void) fprintf(fp, "%s refclock", str); 514 str = ","; 515 } 516 if (flags & INFO_FLAG_AUTHENABLE) { 517 (void) fprintf(fp, "%s auth", str); 518 str = ","; 519 } 520 if (flags & INFO_FLAG_BCLIENT) { 521 (void) fprintf(fp, "%s bclient", str); 522 str = ","; 523 } 524 if (flags & INFO_FLAG_PREFER) { 525 (void) fprintf(fp, "%s prefer", str); 526 str = ","; 527 } 528 if (flags & INFO_FLAG_IBURST) { 529 (void) fprintf(fp, "%s iburst", str); 530 str = ","; 531 } 532 if (flags & INFO_FLAG_BURST) { 533 (void) fprintf(fp, "%s burst", str); 534 } 535 (void) fprintf(fp, "\n"); 536 } 537} 538/* 539 * printpeer - print detail information for a peer 540 */ 541static void 542printpeer( 543 register struct info_peer *pp, 544 FILE *fp 545 ) 546{ 547 register int i; 548 l_fp tempts; 549 struct sockaddr_storage srcadr, dstadr; 550 551 memset((char *)&srcadr, 0, sizeof(srcadr)); 552 memset((char *)&dstadr, 0, sizeof(dstadr)); 553 if (pp->v6_flag != 0) { 554 srcadr.ss_family = AF_INET6; 555 dstadr.ss_family = AF_INET6; 556 GET_INADDR6(srcadr) = pp->srcadr6; 557 GET_INADDR6(dstadr) = pp->dstadr6; 558 } else { 559 srcadr.ss_family = AF_INET; 560 dstadr.ss_family = AF_INET; 561 GET_INADDR(srcadr) = pp->srcadr; 562 GET_INADDR(dstadr) = pp->dstadr; 563 } 564#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 565 srcadr.ss_len = SOCKLEN(&srcadr); 566 dstadr.ss_len = SOCKLEN(&dstadr); 567#endif 568 (void) fprintf(fp, "remote %s, local %s\n", 569 stoa(&srcadr), stoa(&dstadr)); 570 (void) fprintf(fp, "hmode %s, pmode %s, stratum %d, precision %d\n", 571 modetoa(pp->hmode), modetoa(pp->pmode), 572 pp->stratum, pp->precision); 573 574 (void) fprintf(fp, 575 "leap %c%c, refid [%s], rootdistance %s, rootdispersion %s\n", 576 pp->leap & 0x2 ? '1' : '0', 577 pp->leap & 0x1 ? '1' : '0', 578 refid_string(pp->refid, pp->stratum), fptoa(NTOHS_FP(pp->rootdelay), 5), 579 ufptoa(NTOHS_FP(pp->rootdispersion), 5)); 580 581 (void) fprintf(fp, 582 "ppoll %d, hpoll %d, keyid %lu, version %d, association %u\n", 583 pp->ppoll, pp->hpoll, (u_long)pp->keyid, pp->version, ntohs(pp->associd)); 584 585 (void) fprintf(fp, 586 "reach %03o, unreach %d, flash 0x%04x, ", 587 pp->reach, pp->unreach, pp->flash2); 588 589 (void) fprintf(fp, "boffset %s, ttl/mode %d\n", 590 fptoa(NTOHS_FP(pp->estbdelay), 5), pp->ttl); 591 592 (void) fprintf(fp, "timer %lds, flags", (long)ntohl(pp->timer)); 593 print_pflag(fp, pp->flags); 594 595 NTOHL_FP(&pp->reftime, &tempts); 596 (void) fprintf(fp, "reference time: %s\n", 597 prettydate(&tempts)); 598 NTOHL_FP(&pp->org, &tempts); 599 (void) fprintf(fp, "originate timestamp: %s\n", 600 prettydate(&tempts)); 601 NTOHL_FP(&pp->rec, &tempts); 602 (void) fprintf(fp, "receive timestamp: %s\n", 603 prettydate(&tempts)); 604 NTOHL_FP(&pp->xmt, &tempts); 605 (void) fprintf(fp, "transmit timestamp: %s\n", 606 prettydate(&tempts)); 607 608 (void) fprintf(fp, "filter delay: "); 609 for (i = 0; i < NTP_SHIFT; i++) { 610 (void) fprintf(fp, " %-8.8s", 611 fptoa(NTOHS_FP(pp->filtdelay[i]), 5)); 612 if (i == (NTP_SHIFT>>1)-1) 613 (void) fprintf(fp, "\n "); 614 } 615 (void) fprintf(fp, "\n"); 616 617 (void) fprintf(fp, "filter offset:"); 618 for (i = 0; i < NTP_SHIFT; i++) { 619 NTOHL_FP(&pp->filtoffset[i], &tempts); 620 (void) fprintf(fp, " %-8.8s", lfptoa(&tempts, 6)); 621 if (i == (NTP_SHIFT>>1)-1) 622 (void) fprintf(fp, "\n "); 623 } 624 (void) fprintf(fp, "\n"); 625 626 (void) fprintf(fp, "filter order: "); 627 for (i = 0; i < NTP_SHIFT; i++) { 628 (void) fprintf(fp, " %-8d", pp->order[i]); 629 if (i == (NTP_SHIFT>>1)-1) 630 (void) fprintf(fp, "\n "); 631 } 632 (void) fprintf(fp, "\n"); 633 634 635 NTOHL_FP(&pp->offset, &tempts); 636 (void) fprintf(fp, 637 "offset %s, delay %s, error bound %s, filter error %s\n", 638 lfptoa(&tempts, 6), fptoa(NTOHS_FP(pp->delay), 5), 639 ufptoa(NTOHS_FP(pp->dispersion), 5), 640 ufptoa(NTOHS_FP(pp->selectdisp), 5)); 641} 642 643 644/* 645 * showpeer - show detailed information for a peer 646 */ 647static void 648showpeer( 649 struct parse *pcmd, 650 FILE *fp 651 ) 652{ 653 struct info_peer *pp; 654 /* 4 is the maximum number of peers which will fit in a packet */ 655 struct info_peer_list *pl, plist[min(MAXARGS, 4)]; 656 int qitems; 657 int items; 658 int itemsize; 659 int res; 660 int sendsize; 661 662again: 663 if (impl_ver == IMPL_XNTPD) 664 sendsize = sizeof(struct info_peer_list); 665 else 666 sendsize = v4sizeof(struct info_peer_list); 667 668 for (qitems = 0, pl = plist; qitems < min(pcmd->nargs, 4); qitems++) { 669 if (pcmd->argval[qitems].netnum.ss_family == AF_INET) { 670 pl->addr = GET_INADDR(pcmd->argval[qitems].netnum); 671 if (impl_ver == IMPL_XNTPD) 672 pl->v6_flag = 0; 673 } else { 674 if (impl_ver == IMPL_XNTPD_OLD) { 675 fprintf(stderr, 676 "***Server doesn't understand IPv6 addresses\n"); 677 return; 678 } 679 pl->addr6 = GET_INADDR6(pcmd->argval[qitems].netnum); 680 pl->v6_flag = 1; 681 } 682 pl->port = (u_short)s_port; 683 pl->hmode = pl->flags = 0; 684 pl = (struct info_peer_list *)((char *)pl + sendsize); 685 } 686 687 res = doquery(impl_ver, REQ_PEER_INFO, 0, qitems, 688 sendsize, (char *)plist, &items, 689 &itemsize, (void *)&pp, 0, sizeof(struct info_peer)); 690 691 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 692 impl_ver = IMPL_XNTPD_OLD; 693 goto again; 694 } 695 696 if (res != 0) 697 return; 698 699 if (!checkitems(items, fp)) 700 return; 701 702 if (!checkitemsize(itemsize, sizeof(struct info_peer)) && 703 !checkitemsize(itemsize, v4sizeof(struct info_peer))) 704 return; 705 706 while (items-- > 0) { 707 printpeer(pp, fp); 708 if (items > 0) 709 (void) fprintf(fp, "\n"); 710 pp++; 711 } 712} 713 714 715/* 716 * peerstats - return statistics for a peer 717 */ 718static void 719peerstats( 720 struct parse *pcmd, 721 FILE *fp 722 ) 723{ 724 struct info_peer_stats *pp; 725 /* 4 is the maximum number of peers which will fit in a packet */ 726 struct info_peer_list *pl, plist[min(MAXARGS, 4)]; 727 struct sockaddr_storage src, dst; 728 int qitems; 729 int items; 730 int itemsize; 731 int res; 732 int sendsize; 733 734again: 735 if (impl_ver == IMPL_XNTPD) 736 sendsize = sizeof(struct info_peer_list); 737 else 738 sendsize = v4sizeof(struct info_peer_list); 739 740 memset((char *)plist, 0, sizeof(struct info_peer_list) * min(MAXARGS, 4)); 741 for (qitems = 0, pl = plist; qitems < min(pcmd->nargs, 4); qitems++) { 742 if (pcmd->argval[qitems].netnum.ss_family == AF_INET) { 743 pl->addr = GET_INADDR(pcmd->argval[qitems].netnum); 744 if (impl_ver == IMPL_XNTPD) 745 pl->v6_flag = 0; 746 } else { 747 if (impl_ver == IMPL_XNTPD_OLD) { 748 fprintf(stderr, 749 "***Server doesn't understand IPv6 addresses\n"); 750 return; 751 } 752 pl->addr6 = GET_INADDR6(pcmd->argval[qitems].netnum); 753 pl->v6_flag = 1; 754 } 755 pl->port = (u_short)s_port; 756 pl->hmode = plist[qitems].flags = 0; 757 pl = (struct info_peer_list *)((char *)pl + sendsize); 758 } 759 760 res = doquery(impl_ver, REQ_PEER_STATS, 0, qitems, 761 sendsize, (char *)plist, &items, 762 &itemsize, (void *)&pp, 0, 763 sizeof(struct info_peer_stats)); 764 765 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 766 impl_ver = IMPL_XNTPD_OLD; 767 goto again; 768 } 769 770 if (res != 0) 771 return; 772 773 if (!checkitems(items, fp)) 774 return; 775 776 if (!checkitemsize(itemsize, sizeof(struct info_peer_stats)) && 777 !checkitemsize(itemsize, v4sizeof(struct info_peer_stats))) 778 return; 779 780 while (items-- > 0) { 781 memset((char *)&src, 0, sizeof(src)); 782 memset((char *)&dst, 0, sizeof(dst)); 783 if (pp->v6_flag != 0) { 784 GET_INADDR6(src) = pp->srcadr6; 785 GET_INADDR6(dst) = pp->dstadr6; 786 src.ss_family = AF_INET6; 787 dst.ss_family = AF_INET6; 788 } else { 789 GET_INADDR(src) = pp->srcadr; 790 GET_INADDR(dst) = pp->dstadr; 791 src.ss_family = AF_INET; 792 dst.ss_family = AF_INET; 793 } 794#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 795 src.ss_len = SOCKLEN(&src); 796 dst.ss_len = SOCKLEN(&dst); 797#endif 798 (void) fprintf(fp, "remote host: %s\n", 799 nntohost(&src)); 800 (void) fprintf(fp, "local interface: %s\n", 801 stoa(&dst)); 802 (void) fprintf(fp, "time last received: %lds\n", 803 (long)ntohl(pp->timereceived)); 804 (void) fprintf(fp, "time until next send: %lds\n", 805 (long)ntohl(pp->timetosend)); 806 (void) fprintf(fp, "reachability change: %lds\n", 807 (long)ntohl(pp->timereachable)); 808 (void) fprintf(fp, "packets sent: %ld\n", 809 (long)ntohl(pp->sent)); 810 (void) fprintf(fp, "packets received: %ld\n", 811 (long)ntohl(pp->processed)); 812 (void) fprintf(fp, "bad authentication: %ld\n", 813 (long)ntohl(pp->badauth)); 814 (void) fprintf(fp, "bogus origin: %ld\n", 815 (long)ntohl(pp->bogusorg)); 816 (void) fprintf(fp, "duplicate: %ld\n", 817 (long)ntohl(pp->oldpkt)); 818 (void) fprintf(fp, "bad dispersion: %ld\n", 819 (long)ntohl(pp->seldisp)); 820 (void) fprintf(fp, "bad reference time: %ld\n", 821 (long)ntohl(pp->selbroken)); 822 (void) fprintf(fp, "candidate order: %d\n", 823 (int)pp->candidate); 824 if (items > 0) 825 (void) fprintf(fp, "\n"); 826 (void) fprintf(fp, "flags: "); 827 print_pflag(fp, ntohs(pp->flags)); 828 pp++; 829 } 830} 831 832 833/* 834 * loopinfo - show loop filter information 835 */ 836static void 837loopinfo( 838 struct parse *pcmd, 839 FILE *fp 840 ) 841{ 842 struct info_loop *il; 843 int items; 844 int itemsize; 845 int oneline = 0; 846 int res; 847 l_fp tempts; 848 849 if (pcmd->nargs > 0) { 850 if (STREQ(pcmd->argval[0].string, "oneline")) 851 oneline = 1; 852 else if (STREQ(pcmd->argval[0].string, "multiline")) 853 oneline = 0; 854 else { 855 (void) fprintf(stderr, "How many lines?\n"); 856 return; 857 } 858 } 859 860again: 861 res = doquery(impl_ver, REQ_LOOP_INFO, 0, 0, 0, (char *)NULL, 862 &items, &itemsize, (void *)&il, 0, 863 sizeof(struct info_loop)); 864 865 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 866 impl_ver = IMPL_XNTPD_OLD; 867 goto again; 868 } 869 870 if (res != 0) 871 return; 872 873 if (!check1item(items, fp)) 874 return; 875 876 if (!checkitemsize(itemsize, sizeof(struct info_loop))) 877 return; 878 879 if (oneline) { 880 l_fp temp2ts; 881 882 NTOHL_FP(&il->last_offset, &tempts); 883 NTOHL_FP(&il->drift_comp, &temp2ts); 884 885 (void) fprintf(fp, 886 "offset %s, frequency %s, time_const %ld, watchdog %ld\n", 887 lfptoa(&tempts, 6), 888 lfptoa(&temp2ts, 3), 889 (long)(int32_t)ntohl((u_long)il->compliance), 890 (u_long)ntohl((u_long)il->watchdog_timer)); 891 } else { 892 NTOHL_FP(&il->last_offset, &tempts); 893 (void) fprintf(fp, "offset: %s s\n", 894 lfptoa(&tempts, 6)); 895 NTOHL_FP(&il->drift_comp, &tempts); 896 (void) fprintf(fp, "frequency: %s ppm\n", 897 lfptoa(&tempts, 3)); 898 (void) fprintf(fp, "poll adjust: %ld\n", 899 (long)(int32_t)ntohl(il->compliance)); 900 (void) fprintf(fp, "watchdog timer: %ld s\n", 901 (u_long)ntohl(il->watchdog_timer)); 902 } 903} 904 905 906/* 907 * sysinfo - show current system state 908 */ 909/*ARGSUSED*/ 910static void 911sysinfo( 912 struct parse *pcmd, 913 FILE *fp 914 ) 915{ 916 struct info_sys *is; 917 struct sockaddr_storage peeraddr; 918 int items; 919 int itemsize; 920 int res; 921 l_fp tempts; 922 923again: 924 res = doquery(impl_ver, REQ_SYS_INFO, 0, 0, 0, (char *)NULL, 925 &items, &itemsize, (void *)&is, 0, 926 sizeof(struct info_sys)); 927 928 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 929 impl_ver = IMPL_XNTPD_OLD; 930 goto again; 931 } 932 933 if (res != 0) 934 return; 935 936 if (!check1item(items, fp)) 937 return; 938 939 if (!checkitemsize(itemsize, sizeof(struct info_sys)) && 940 !checkitemsize(itemsize, v4sizeof(struct info_sys))) 941 return; 942 943 memset((char *)&peeraddr, 0, sizeof(peeraddr)); 944 if (is->v6_flag != 0) { 945 GET_INADDR6(peeraddr) = is->peer6; 946 peeraddr.ss_family = AF_INET6; 947 } else { 948 GET_INADDR(peeraddr) = is->peer; 949 peeraddr.ss_family = AF_INET; 950 } 951#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 952 peeraddr.ss_len = SOCKLEN(&peeraddr); 953#endif 954 (void) fprintf(fp, "system peer: %s\n", nntohost(&peeraddr)); 955 (void) fprintf(fp, "system peer mode: %s\n", modetoa(is->peer_mode)); 956 (void) fprintf(fp, "leap indicator: %c%c\n", 957 is->leap & 0x2 ? '1' : '0', 958 is->leap & 0x1 ? '1' : '0'); 959 (void) fprintf(fp, "stratum: %d\n", (int)is->stratum); 960 (void) fprintf(fp, "precision: %d\n", (int)is->precision); 961 (void) fprintf(fp, "root distance: %s s\n", 962 fptoa(NTOHS_FP(is->rootdelay), 5)); 963 (void) fprintf(fp, "root dispersion: %s s\n", 964 ufptoa(NTOHS_FP(is->rootdispersion), 5)); 965 (void) fprintf(fp, "reference ID: [%s]\n", 966 refid_string(is->refid, is->stratum)); 967 NTOHL_FP(&is->reftime, &tempts); 968 (void) fprintf(fp, "reference time: %s\n", prettydate(&tempts)); 969 970 (void) fprintf(fp, "system flags: "); 971 if ((is->flags & (INFO_FLAG_BCLIENT | INFO_FLAG_AUTHENABLE | 972 INFO_FLAG_NTP | INFO_FLAG_KERNEL| INFO_FLAG_CAL | 973 INFO_FLAG_PPS_SYNC | INFO_FLAG_MONITOR | INFO_FLAG_FILEGEN)) == 0) { 974 (void) fprintf(fp, "none\n"); 975 } else { 976 if (is->flags & INFO_FLAG_BCLIENT) 977 (void) fprintf(fp, "bclient "); 978 if (is->flags & INFO_FLAG_AUTHENTICATE) 979 (void) fprintf(fp, "auth "); 980 if (is->flags & INFO_FLAG_MONITOR) 981 (void) fprintf(fp, "monitor "); 982 if (is->flags & INFO_FLAG_NTP) 983 (void) fprintf(fp, "ntp "); 984 if (is->flags & INFO_FLAG_KERNEL) 985 (void) fprintf(fp, "kernel "); 986 if (is->flags & INFO_FLAG_FILEGEN) 987 (void) fprintf(fp, "stats "); 988 if (is->flags & INFO_FLAG_CAL) 989 (void) fprintf(fp, "calibrate "); 990 if (is->flags & INFO_FLAG_PPS_SYNC) 991 (void) fprintf(fp, "pps "); 992 (void) fprintf(fp, "\n"); 993 } 994 (void) fprintf(fp, "jitter: %s s\n", 995 fptoa(ntohl(is->frequency), 6)); 996 (void) fprintf(fp, "stability: %s ppm\n", 997 ufptoa(ntohl(is->stability), 3)); 998 (void) fprintf(fp, "broadcastdelay: %s s\n", 999 fptoa(NTOHS_FP(is->bdelay), 6)); 1000 NTOHL_FP(&is->authdelay, &tempts); 1001 (void) fprintf(fp, "authdelay: %s s\n", lfptoa(&tempts, 6)); 1002} 1003 1004 1005/* 1006 * sysstats - print system statistics 1007 */ 1008/*ARGSUSED*/ 1009static void 1010sysstats( 1011 struct parse *pcmd, 1012 FILE *fp 1013 ) 1014{ 1015 struct info_sys_stats *ss; 1016 int items; 1017 int itemsize; 1018 int res; 1019 1020again: 1021 res = doquery(impl_ver, REQ_SYS_STATS, 0, 0, 0, (char *)NULL, 1022 &items, &itemsize, (void *)&ss, 0, 1023 sizeof(struct info_sys_stats)); 1024 1025 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1026 impl_ver = IMPL_XNTPD_OLD; 1027 goto again; 1028 } 1029 1030 if (res != 0) 1031 return; 1032 1033 if (!check1item(items, fp)) 1034 return; 1035 1036 if (itemsize != sizeof(struct info_sys_stats) && 1037 itemsize != sizeof(struct old_info_sys_stats)) { 1038 /* issue warning according to new structure size */ 1039 checkitemsize(itemsize, sizeof(struct info_sys_stats)); 1040 return; 1041 } 1042 fprintf(fp, "time since restart: %ld\n", 1043 (u_long)ntohl(ss->timeup)); 1044 fprintf(fp, "time since reset: %ld\n", 1045 (u_long)ntohl(ss->timereset)); 1046 fprintf(fp, "packets received: %ld\n", 1047 (u_long)ntohl(ss->received)); 1048 fprintf(fp, "packets processed: %ld\n", 1049 (u_long)ntohl(ss->processed)); 1050 fprintf(fp, "current version: %ld\n", 1051 (u_long)ntohl(ss->newversionpkt)); 1052 fprintf(fp, "previous version: %ld\n", 1053 (u_long)ntohl(ss->oldversionpkt)); 1054 fprintf(fp, "bad version: %ld\n", 1055 (u_long)ntohl(ss->unknownversion)); 1056 fprintf(fp, "access denied: %ld\n", 1057 (u_long)ntohl(ss->denied)); 1058 fprintf(fp, "bad length or format: %ld\n", 1059 (u_long)ntohl(ss->badlength)); 1060 fprintf(fp, "bad authentication: %ld\n", 1061 (u_long)ntohl(ss->badauth)); 1062 if (itemsize != sizeof(struct info_sys_stats)) 1063 return; 1064 1065 fprintf(fp, "rate exceeded: %ld\n", 1066 (u_long)ntohl(ss->limitrejected)); 1067} 1068 1069 1070 1071/* 1072 * iostats - print I/O statistics 1073 */ 1074/*ARGSUSED*/ 1075static void 1076iostats( 1077 struct parse *pcmd, 1078 FILE *fp 1079 ) 1080{ 1081 struct info_io_stats *io; 1082 int items; 1083 int itemsize; 1084 int res; 1085 1086again: 1087 res = doquery(impl_ver, REQ_IO_STATS, 0, 0, 0, (char *)NULL, 1088 &items, &itemsize, (void *)&io, 0, 1089 sizeof(struct info_io_stats)); 1090 1091 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1092 impl_ver = IMPL_XNTPD_OLD; 1093 goto again; 1094 } 1095 1096 if (res != 0) 1097 return; 1098 1099 if (!check1item(items, fp)) 1100 return; 1101 1102 if (!checkitemsize(itemsize, sizeof(struct info_io_stats))) 1103 return; 1104 1105 (void) fprintf(fp, "time since reset: %ld\n", 1106 (u_long)ntohl(io->timereset)); 1107 (void) fprintf(fp, "receive buffers: %d\n", 1108 ntohs(io->totalrecvbufs)); 1109 (void) fprintf(fp, "free receive buffers: %d\n", 1110 ntohs(io->freerecvbufs)); 1111 (void) fprintf(fp, "used receive buffers: %d\n", 1112 ntohs(io->fullrecvbufs)); 1113 (void) fprintf(fp, "low water refills: %d\n", 1114 ntohs(io->lowwater)); 1115 (void) fprintf(fp, "dropped packets: %ld\n", 1116 (u_long)ntohl(io->dropped)); 1117 (void) fprintf(fp, "ignored packets: %ld\n", 1118 (u_long)ntohl(io->ignored)); 1119 (void) fprintf(fp, "received packets: %ld\n", 1120 (u_long)ntohl(io->received)); 1121 (void) fprintf(fp, "packets sent: %ld\n", 1122 (u_long)ntohl(io->sent)); 1123 (void) fprintf(fp, "packets not sent: %ld\n", 1124 (u_long)ntohl(io->notsent)); 1125 (void) fprintf(fp, "interrupts handled: %ld\n", 1126 (u_long)ntohl(io->interrupts)); 1127 (void) fprintf(fp, "received by int: %ld\n", 1128 (u_long)ntohl(io->int_received)); 1129} 1130 1131 1132/* 1133 * memstats - print peer memory statistics 1134 */ 1135/*ARGSUSED*/ 1136static void 1137memstats( 1138 struct parse *pcmd, 1139 FILE *fp 1140 ) 1141{ 1142 struct info_mem_stats *mem; 1143 int i; 1144 int items; 1145 int itemsize; 1146 int res; 1147 1148again: 1149 res = doquery(impl_ver, REQ_MEM_STATS, 0, 0, 0, (char *)NULL, 1150 &items, &itemsize, (void *)&mem, 0, 1151 sizeof(struct info_mem_stats)); 1152 1153 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1154 impl_ver = IMPL_XNTPD_OLD; 1155 goto again; 1156 } 1157 1158 if (res != 0) 1159 return; 1160 1161 if (!check1item(items, fp)) 1162 return; 1163 1164 if (!checkitemsize(itemsize, sizeof(struct info_mem_stats))) 1165 return; 1166 1167 (void) fprintf(fp, "time since reset: %ld\n", 1168 (u_long)ntohl(mem->timereset)); 1169 (void) fprintf(fp, "total peer memory: %d\n", 1170 ntohs(mem->totalpeermem)); 1171 (void) fprintf(fp, "free peer memory: %d\n", 1172 ntohs(mem->freepeermem)); 1173 (void) fprintf(fp, "calls to findpeer: %ld\n", 1174 (u_long)ntohl(mem->findpeer_calls)); 1175 (void) fprintf(fp, "new peer allocations: %ld\n", 1176 (u_long)ntohl(mem->allocations)); 1177 (void) fprintf(fp, "peer demobilizations: %ld\n", 1178 (u_long)ntohl(mem->demobilizations)); 1179 1180 (void) fprintf(fp, "hash table counts: "); 1181 for (i = 0; i < NTP_HASH_SIZE; i++) { 1182 (void) fprintf(fp, "%4d", (int)mem->hashcount[i]); 1183 if ((i % 8) == 7 && i != (NTP_HASH_SIZE-1)) { 1184 (void) fprintf(fp, "\n "); 1185 } 1186 } 1187 (void) fprintf(fp, "\n"); 1188} 1189 1190 1191 1192/* 1193 * timerstats - print timer statistics 1194 */ 1195/*ARGSUSED*/ 1196static void 1197timerstats( 1198 struct parse *pcmd, 1199 FILE *fp 1200 ) 1201{ 1202 struct info_timer_stats *tim; 1203 int items; 1204 int itemsize; 1205 int res; 1206 1207again: 1208 res = doquery(impl_ver, REQ_TIMER_STATS, 0, 0, 0, (char *)NULL, 1209 &items, &itemsize, (void *)&tim, 0, 1210 sizeof(struct info_timer_stats)); 1211 1212 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1213 impl_ver = IMPL_XNTPD_OLD; 1214 goto again; 1215 } 1216 1217 if (res != 0) 1218 return; 1219 1220 if (!check1item(items, fp)) 1221 return; 1222 1223 if (!checkitemsize(itemsize, sizeof(struct info_timer_stats))) 1224 return; 1225 1226 (void) fprintf(fp, "time since reset: %ld\n", 1227 (u_long)ntohl(tim->timereset)); 1228 (void) fprintf(fp, "alarms handled: %ld\n", 1229 (u_long)ntohl(tim->alarms)); 1230 (void) fprintf(fp, "alarm overruns: %ld\n", 1231 (u_long)ntohl(tim->overflows)); 1232 (void) fprintf(fp, "calls to transmit: %ld\n", 1233 (u_long)ntohl(tim->xmtcalls)); 1234} 1235 1236 1237/* 1238 * addpeer - configure an active mode association 1239 */ 1240static void 1241addpeer( 1242 struct parse *pcmd, 1243 FILE *fp 1244 ) 1245{ 1246 doconfig(pcmd, fp, MODE_ACTIVE, 0); 1247} 1248 1249 1250/* 1251 * addserver - configure a client mode association 1252 */ 1253static void 1254addserver( 1255 struct parse *pcmd, 1256 FILE *fp 1257 ) 1258{ 1259 doconfig(pcmd, fp, MODE_CLIENT, 0); 1260} 1261 1262/* 1263 * addrefclock - configure a reference clock association 1264 */ 1265static void 1266addrefclock( 1267 struct parse *pcmd, 1268 FILE *fp 1269 ) 1270{ 1271 doconfig(pcmd, fp, MODE_CLIENT, 1); 1272} 1273 1274/* 1275 * broadcast - configure a broadcast mode association 1276 */ 1277static void 1278broadcast( 1279 struct parse *pcmd, 1280 FILE *fp 1281 ) 1282{ 1283 doconfig(pcmd, fp, MODE_BROADCAST, 0); 1284} 1285 1286 1287/* 1288 * config - configure a new peer association 1289 */ 1290static void 1291doconfig( 1292 struct parse *pcmd, 1293 FILE *fp, 1294 int mode, 1295 int refc 1296 ) 1297{ 1298 struct conf_peer cpeer; 1299 int items; 1300 int itemsize; 1301 char *dummy; 1302 u_long keyid; 1303 u_int version; 1304 u_char minpoll; 1305 u_char maxpoll; 1306 u_int flags; 1307 u_char cmode; 1308 int res; 1309 int sendsize; 1310 int numtyp; 1311 1312again: 1313 keyid = 0; 1314 version = 3; 1315 flags = 0; 1316 res = 0; 1317 cmode = 0; 1318 minpoll = NTP_MINDPOLL; 1319 maxpoll = NTP_MAXDPOLL; 1320 numtyp = 1; 1321 if (refc) 1322 numtyp = 5; 1323 1324 if (impl_ver == IMPL_XNTPD) 1325 sendsize = sizeof(struct conf_peer); 1326 else 1327 sendsize = v4sizeof(struct conf_peer); 1328 1329 items = 1; 1330 while (pcmd->nargs > items) { 1331 if (STREQ(pcmd->argval[items].string, "prefer")) 1332 flags |= CONF_FLAG_PREFER; 1333 else if (STREQ(pcmd->argval[items].string, "burst")) 1334 flags |= CONF_FLAG_BURST; 1335 else if (STREQ(pcmd->argval[items].string, "dynamic")) 1336 (void) fprintf(fp, "Warning: the \"dynamic\" keyword has been obsoleted and will be removed in the next release\n"); 1337 else if (STREQ(pcmd->argval[items].string, "iburst")) 1338 flags |= CONF_FLAG_IBURST; 1339 else if (!refc && STREQ(pcmd->argval[items].string, "keyid")) 1340 numtyp = 1; 1341 else if (!refc && STREQ(pcmd->argval[items].string, "version")) 1342 numtyp = 2; 1343 else if (STREQ(pcmd->argval[items].string, "minpoll")) 1344 numtyp = 3; 1345 else if (STREQ(pcmd->argval[items].string, "maxpoll")) 1346 numtyp = 4; 1347 else { 1348 long val; 1349 if (!atoint(pcmd->argval[items].string, &val)) 1350 numtyp = 0; 1351 switch (numtyp) { 1352 case 1: 1353 keyid = val; 1354 numtyp = 2; 1355 break; 1356 1357 case 2: 1358 version = (u_int) val; 1359 numtyp = 0; 1360 break; 1361 1362 case 3: 1363 minpoll = (u_char)val; 1364 numtyp = 0; 1365 break; 1366 1367 case 4: 1368 maxpoll = (u_char)val; 1369 numtyp = 0; 1370 break; 1371 1372 case 5: 1373 cmode = (u_char)val; 1374 numtyp = 0; 1375 break; 1376 1377 default: 1378 (void) fprintf(fp, "*** '%s' not understood\n", 1379 pcmd->argval[items].string); 1380 res++; 1381 numtyp = 0; 1382 } 1383 if (val < 0) { 1384 (void) fprintf(stderr, 1385 "***Value '%s' should be unsigned\n", 1386 pcmd->argval[items].string); 1387 res++; 1388 } 1389 } 1390 items++; 1391 } 1392 if (keyid > 0) 1393 flags |= CONF_FLAG_AUTHENABLE; 1394 if (version > NTP_VERSION || 1395 version < NTP_OLDVERSION) { 1396 (void)fprintf(fp, "***invalid version number: %u\n", 1397 version); 1398 res++; 1399 } 1400 if (minpoll < NTP_MINPOLL || minpoll > NTP_MAXPOLL || 1401 maxpoll < NTP_MINPOLL || maxpoll > NTP_MAXPOLL || 1402 minpoll > maxpoll) { 1403 (void) fprintf(fp, "***min/max-poll must be within %d..%d\n", 1404 NTP_MINPOLL, NTP_MAXPOLL); 1405 res++; 1406 } 1407 1408 if (res) 1409 return; 1410 1411 memset((void *)&cpeer, 0, sizeof(cpeer)); 1412 1413 if (pcmd->argval[0].netnum.ss_family == AF_INET) { 1414 cpeer.peeraddr = GET_INADDR(pcmd->argval[0].netnum); 1415 if (impl_ver == IMPL_XNTPD) 1416 cpeer.v6_flag = 0; 1417 } else { 1418 if (impl_ver == IMPL_XNTPD_OLD) { 1419 fprintf(stderr, 1420 "***Server doesn't understand IPv6 addresses\n"); 1421 return; 1422 } 1423 cpeer.peeraddr6 = GET_INADDR6(pcmd->argval[0].netnum); 1424 cpeer.v6_flag = 1; 1425 } 1426 cpeer.hmode = (u_char) mode; 1427 cpeer.keyid = keyid; 1428 cpeer.version = (u_char) version; 1429 cpeer.minpoll = minpoll; 1430 cpeer.maxpoll = maxpoll; 1431 cpeer.flags = (u_char)flags; 1432 cpeer.ttl = cmode; 1433 1434 res = doquery(impl_ver, REQ_CONFIG, 1, 1, 1435 sendsize, (char *)&cpeer, &items, 1436 &itemsize, &dummy, 0, sizeof(struct conf_peer)); 1437 1438 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1439 impl_ver = IMPL_XNTPD_OLD; 1440 goto again; 1441 } 1442 1443 if (res == INFO_ERR_FMT) { 1444 (void) fprintf(fp, 1445 "***Retrying command with old conf_peer size\n"); 1446 res = doquery(impl_ver, REQ_CONFIG, 1, 1, 1447 sizeof(struct old_conf_peer), (char *)&cpeer, 1448 &items, &itemsize, &dummy, 0, 1449 sizeof(struct conf_peer)); 1450 } 1451 if (res == 0) 1452 (void) fprintf(fp, "done!\n"); 1453 return; 1454} 1455 1456 1457/* 1458 * unconfig - unconfigure some associations 1459 */ 1460static void 1461unconfig( 1462 struct parse *pcmd, 1463 FILE *fp 1464 ) 1465{ 1466 /* 8 is the maximum number of peers which will fit in a packet */ 1467 struct conf_unpeer *pl, plist[min(MAXARGS, 8)]; 1468 int qitems; 1469 int items; 1470 int itemsize; 1471 char *dummy; 1472 int res; 1473 int sendsize; 1474 1475again: 1476 if (impl_ver == IMPL_XNTPD) 1477 sendsize = sizeof(struct conf_unpeer); 1478 else 1479 sendsize = v4sizeof(struct conf_unpeer); 1480 1481 for (qitems = 0, pl = plist; qitems < min(pcmd->nargs, 8); qitems++) { 1482 if (pcmd->argval[0].netnum.ss_family == AF_INET) { 1483 pl->peeraddr = GET_INADDR(pcmd->argval[qitems].netnum); 1484 if (impl_ver == IMPL_XNTPD) 1485 pl->v6_flag = 0; 1486 } else { 1487 if (impl_ver == IMPL_XNTPD_OLD) { 1488 fprintf(stderr, 1489 "***Server doesn't understand IPv6 addresses\n"); 1490 return; 1491 } 1492 pl->peeraddr6 = 1493 GET_INADDR6(pcmd->argval[qitems].netnum); 1494 pl->v6_flag = 1; 1495 } 1496 pl = (struct conf_unpeer *)((char *)pl + sendsize); 1497 } 1498 1499 res = doquery(impl_ver, REQ_UNCONFIG, 1, qitems, 1500 sendsize, (char *)plist, &items, 1501 &itemsize, &dummy, 0, sizeof(struct conf_unpeer)); 1502 1503 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1504 impl_ver = IMPL_XNTPD_OLD; 1505 goto again; 1506 } 1507 1508 if (res == 0) 1509 (void) fprintf(fp, "done!\n"); 1510} 1511 1512 1513/* 1514 * set - set some system flags 1515 */ 1516static void 1517set( 1518 struct parse *pcmd, 1519 FILE *fp 1520 ) 1521{ 1522 doset(pcmd, fp, REQ_SET_SYS_FLAG); 1523} 1524 1525 1526/* 1527 * clear - clear some system flags 1528 */ 1529static void 1530sys_clear( 1531 struct parse *pcmd, 1532 FILE *fp 1533 ) 1534{ 1535 doset(pcmd, fp, REQ_CLR_SYS_FLAG); 1536} 1537 1538 1539/* 1540 * doset - set/clear system flags 1541 */ 1542static void 1543doset( 1544 struct parse *pcmd, 1545 FILE *fp, 1546 int req 1547 ) 1548{ 1549 /* 8 is the maximum number of peers which will fit in a packet */ 1550 struct conf_sys_flags sys; 1551 int items; 1552 int itemsize; 1553 char *dummy; 1554 int res; 1555 1556 sys.flags = 0; 1557 res = 0; 1558 for (items = 0; items < pcmd->nargs; items++) { 1559 if (STREQ(pcmd->argval[items].string, "auth")) 1560 sys.flags |= SYS_FLAG_AUTH; 1561 else if (STREQ(pcmd->argval[items].string, "bclient")) 1562 sys.flags |= SYS_FLAG_BCLIENT; 1563 else if (STREQ(pcmd->argval[items].string, "calibrate")) 1564 sys.flags |= SYS_FLAG_CAL; 1565 else if (STREQ(pcmd->argval[items].string, "kernel")) 1566 sys.flags |= SYS_FLAG_KERNEL; 1567 else if (STREQ(pcmd->argval[items].string, "monitor")) 1568 sys.flags |= SYS_FLAG_MONITOR; 1569 else if (STREQ(pcmd->argval[items].string, "ntp")) 1570 sys.flags |= SYS_FLAG_NTP; 1571 else if (STREQ(pcmd->argval[items].string, "pps")) 1572 sys.flags |= SYS_FLAG_PPS; 1573 else if (STREQ(pcmd->argval[items].string, "stats")) 1574 sys.flags |= SYS_FLAG_FILEGEN; 1575 else { 1576 (void) fprintf(fp, "Unknown flag %s\n", 1577 pcmd->argval[items].string); 1578 res = 1; 1579 } 1580 } 1581 1582 sys.flags = htonl(sys.flags); 1583 if (res || sys.flags == 0) 1584 return; 1585 1586again: 1587 res = doquery(impl_ver, req, 1, 1, 1588 sizeof(struct conf_sys_flags), (char *)&sys, &items, 1589 &itemsize, &dummy, 0, sizeof(struct conf_sys_flags)); 1590 1591 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1592 impl_ver = IMPL_XNTPD_OLD; 1593 goto again; 1594 } 1595 1596 if (res == 0) 1597 (void) fprintf(fp, "done!\n"); 1598} 1599 1600 1601/* 1602 * data for printing/interrpreting the restrict flags 1603 */ 1604struct resflags { 1605 const char *str; 1606 int bit; 1607}; 1608 1609/* XXX: HMS: we apparently don't report set bits we do not recognize. */ 1610 1611static struct resflags resflagsV2[] = { 1612 { "ignore", 0x001 }, 1613 { "noserve", 0x002 }, 1614 { "notrust", 0x004 }, 1615 { "noquery", 0x008 }, 1616 { "nomodify", 0x010 }, 1617 { "nopeer", 0x020 }, 1618 { "notrap", 0x040 }, 1619 { "lptrap", 0x080 }, 1620 { "limited", 0x100 }, 1621 { "", 0 } 1622}; 1623 1624static struct resflags resflagsV3[] = { 1625 { "ignore", RES_IGNORE }, 1626 { "noserve", RES_DONTSERVE }, 1627 { "notrust", RES_DONTTRUST }, 1628 { "noquery", RES_NOQUERY }, 1629 { "nomodify", RES_NOMODIFY }, 1630 { "nopeer", RES_NOPEER }, 1631 { "notrap", RES_NOTRAP }, 1632 { "lptrap", RES_LPTRAP }, 1633 { "limited", RES_LIMITED }, 1634 { "version", RES_VERSION }, 1635 { "kod", RES_DEMOBILIZE }, 1636 { "timeout", RES_TIMEOUT }, 1637 1638 { "", 0 } 1639}; 1640 1641static struct resflags resmflags[] = { 1642 { "ntpport", RESM_NTPONLY }, 1643 { "interface", RESM_INTERFACE }, 1644 { "", 0 } 1645}; 1646 1647 1648/* 1649 * reslist - obtain and print the server's restrict list 1650 */ 1651/*ARGSUSED*/ 1652static void 1653reslist( 1654 struct parse *pcmd, 1655 FILE *fp 1656 ) 1657{ 1658 struct info_restrict *rl; 1659 struct sockaddr_storage resaddr; 1660 struct sockaddr_storage maskaddr; 1661 int items; 1662 int itemsize; 1663 int res; 1664 int skip; 1665 char *addr; 1666 char *mask; 1667 struct resflags *rf; 1668 u_int32 count; 1669 u_short flags; 1670 u_short mflags; 1671 char flagstr[300]; 1672 static const char *comma = ", "; 1673 1674again: 1675 res = doquery(impl_ver, REQ_GET_RESTRICT, 0, 0, 0, (char *)NULL, 1676 &items, &itemsize, (void *)&rl, 0, 1677 sizeof(struct info_restrict)); 1678 1679 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1680 impl_ver = IMPL_XNTPD_OLD; 1681 goto again; 1682 } 1683 1684 if (res != 0) 1685 return; 1686 1687 if (!checkitems(items, fp)) 1688 return; 1689 1690 if (!checkitemsize(itemsize, sizeof(struct info_restrict)) && 1691 !checkitemsize(itemsize, v4sizeof(struct info_restrict))) 1692 return; 1693 1694 (void) fprintf(fp, 1695 " address mask count flags\n"); 1696 (void) fprintf(fp, 1697 "=====================================================================\n"); 1698 1699 while (items > 0) { 1700 memset((char *)&resaddr, 0, sizeof(resaddr)); 1701 memset((char *)&maskaddr, 0, sizeof(maskaddr)); 1702 if (rl->v6_flag != 0) { 1703 GET_INADDR6(resaddr) = rl->addr6; 1704 GET_INADDR6(maskaddr) = rl->mask6; 1705 resaddr.ss_family = AF_INET6; 1706 maskaddr.ss_family = AF_INET6; 1707#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 1708 resaddr.ss_len = SOCKLEN(&resaddr); 1709#endif 1710 addr = nntohost(&resaddr); 1711 } else { 1712 GET_INADDR(resaddr) = rl->addr; 1713 GET_INADDR(maskaddr) = rl->mask; 1714 resaddr.ss_family = AF_INET; 1715 maskaddr.ss_family = AF_INET; 1716#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 1717 resaddr.ss_len = SOCKLEN(&resaddr); 1718#endif 1719 if ((rl->mask == (u_int32)0xffffffff)) 1720 addr = nntohost(&resaddr); 1721 else 1722 addr = stoa(&resaddr); 1723 } 1724 mask = stoa(&maskaddr); 1725 skip = 1; 1726 if ((pcmd->nargs == 0) || 1727 ((pcmd->argval->ival == 6) && (rl->v6_flag != 0)) || 1728 ((pcmd->argval->ival == 4) && (rl->v6_flag == 0))) 1729 skip = 0; 1730 count = ntohl(rl->count); 1731 flags = ntohs(rl->flags); 1732 mflags = ntohs(rl->mflags); 1733 flagstr[0] = '\0'; 1734 1735 res = 1; 1736 rf = &resmflags[0]; 1737 while (rf->bit != 0) { 1738 if (mflags & rf->bit) { 1739 if (!res) 1740 (void) strcat(flagstr, comma); 1741 res = 0; 1742 (void) strcat(flagstr, rf->str); 1743 } 1744 rf++; 1745 } 1746 1747 rf = (impl_ver == IMPL_XNTPD_OLD) 1748 ? &resflagsV2[0] 1749 : &resflagsV3[0] 1750 ; 1751 while (rf->bit != 0) { 1752 if (flags & rf->bit) { 1753 if (!res) 1754 (void) strcat(flagstr, comma); 1755 res = 0; 1756 (void) strcat(flagstr, rf->str); 1757 } 1758 rf++; 1759 } 1760 1761 if (flagstr[0] == '\0') 1762 (void) strcpy(flagstr, "none"); 1763 1764 if (!skip) 1765 (void) fprintf(fp, "%-15.15s %-15.15s %9ld %s\n", 1766 addr, mask, (u_long)count, flagstr); 1767 rl++; 1768 items--; 1769 } 1770} 1771 1772 1773 1774/* 1775 * new_restrict - create/add a set of restrictions 1776 */ 1777static void 1778new_restrict( 1779 struct parse *pcmd, 1780 FILE *fp 1781 ) 1782{ 1783 do_restrict(pcmd, fp, REQ_RESADDFLAGS); 1784} 1785 1786 1787/* 1788 * unrestrict - remove restriction flags from existing entry 1789 */ 1790static void 1791unrestrict( 1792 struct parse *pcmd, 1793 FILE *fp 1794 ) 1795{ 1796 do_restrict(pcmd, fp, REQ_RESSUBFLAGS); 1797} 1798 1799 1800/* 1801 * delrestrict - delete an existing restriction 1802 */ 1803static void 1804delrestrict( 1805 struct parse *pcmd, 1806 FILE *fp 1807 ) 1808{ 1809 do_restrict(pcmd, fp, REQ_UNRESTRICT); 1810} 1811 1812 1813/* 1814 * do_restrict - decode commandline restrictions and make the request 1815 */ 1816static void 1817do_restrict( 1818 struct parse *pcmd, 1819 FILE *fp, 1820 int req_code 1821 ) 1822{ 1823 struct conf_restrict cres; 1824 int items; 1825 int itemsize; 1826 char *dummy; 1827 u_int32 num; 1828 u_long bit; 1829 int i; 1830 int res; 1831 int err; 1832 int sendsize; 1833 1834 /* Initialize cres */ 1835 cres.addr = 0; 1836 cres.mask = 0; 1837 cres.flags = 0; 1838 cres.mflags = 0; 1839 cres.v6_flag = 0; 1840 1841again: 1842 if (impl_ver == IMPL_XNTPD) 1843 sendsize = sizeof(struct conf_restrict); 1844 else 1845 sendsize = v4sizeof(struct conf_restrict); 1846 1847 if (pcmd->argval[0].netnum.ss_family == AF_INET) { 1848 cres.addr = GET_INADDR(pcmd->argval[0].netnum); 1849 cres.mask = GET_INADDR(pcmd->argval[1].netnum); 1850 if (impl_ver == IMPL_XNTPD) 1851 cres.v6_flag = 0; 1852 } else { 1853 if (impl_ver == IMPL_XNTPD_OLD) { 1854 fprintf(stderr, 1855 "***Server doesn't understand IPv6 addresses\n"); 1856 return; 1857 } 1858 cres.addr6 = GET_INADDR6(pcmd->argval[0].netnum); 1859 cres.v6_flag = 1; 1860 } 1861 cres.flags = 0; 1862 cres.mflags = 0; 1863 err = 0; 1864 for (res = 2; res < pcmd->nargs; res++) { 1865 if (STREQ(pcmd->argval[res].string, "ntpport")) { 1866 cres.mflags |= RESM_NTPONLY; 1867 } else { 1868 for (i = 0; resflagsV3[i].bit != 0; i++) { 1869 if (STREQ(pcmd->argval[res].string, 1870 resflagsV3[i].str)) 1871 break; 1872 } 1873 if (resflagsV3[i].bit != 0) { 1874 cres.flags |= resflagsV3[i].bit; 1875 if (req_code == REQ_UNRESTRICT) { 1876 (void) fprintf(fp, 1877 "Flag %s inappropriate\n", 1878 resflagsV3[i].str); 1879 err++; 1880 } 1881 } else { 1882 (void) fprintf(fp, "Unknown flag %s\n", 1883 pcmd->argval[res].string); 1884 err++; 1885 } 1886 } 1887 } 1888 cres.flags = htons(cres.flags); 1889 cres.mflags = htons(cres.mflags); 1890 1891 /* 1892 * Make sure mask for default address is zero. Otherwise, 1893 * make sure mask bits are contiguous. 1894 */ 1895 if (pcmd->argval[0].netnum.ss_family == AF_INET) { 1896 if (cres.addr == 0) { 1897 cres.mask = 0; 1898 } else { 1899 num = ntohl(cres.mask); 1900 for (bit = 0x80000000; bit != 0; bit >>= 1) 1901 if ((num & bit) == 0) 1902 break; 1903 for ( ; bit != 0; bit >>= 1) 1904 if ((num & bit) != 0) 1905 break; 1906 if (bit != 0) { 1907 (void) fprintf(fp, "Invalid mask %s\n", 1908 numtoa(cres.mask)); 1909 err++; 1910 } 1911 } 1912 } else { 1913 /* XXX IPv6 sanity checking stuff */ 1914 } 1915 1916 if (err) 1917 return; 1918 1919 res = doquery(impl_ver, req_code, 1, 1, 1920 sendsize, (char *)&cres, &items, 1921 &itemsize, &dummy, 0, sizeof(struct conf_restrict)); 1922 1923 if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1924 impl_ver = IMPL_XNTPD_OLD; 1925 goto again; 1926 } 1927 1928 if (res == 0) 1929 (void) fprintf(fp, "done!\n"); 1930 return; 1931} 1932 1933 1934/* 1935 * monlist - obtain and print the server's monitor data 1936 */ 1937/*ARGSUSED*/ 1938static void 1939monlist( 1940 struct parse *pcmd, 1941 FILE *fp 1942 ) 1943{ 1944 char *struct_star; 1945 …
Large files files are truncated, but you can click here to view the full file