Annotation of embedaddon/ntp/ntpq/ntpq-subs.c, revision 1.1
1.1 ! misho 1: /*
! 2: * ntpq_ops.c - subroutines which are called to perform operations by ntpq
! 3: */
! 4:
! 5: #include <stdio.h>
! 6: #include <ctype.h>
! 7: #include <sys/types.h>
! 8: #include <sys/time.h>
! 9:
! 10: #include "ntp_stdlib.h"
! 11: #include "ntpq.h"
! 12: #include "ntpq-opts.h"
! 13:
! 14: extern char * chosts[];
! 15: extern char currenthost[];
! 16: extern int currenthostisnum;
! 17: extern int numhosts;
! 18: int maxhostlen;
! 19:
! 20: /*
! 21: * Declarations for command handlers in here
! 22: */
! 23: static associd_t checkassocid (u_int32);
! 24: static struct varlist *findlistvar (struct varlist *, char *);
! 25: static void doaddvlist (struct varlist *, const char *);
! 26: static void dormvlist (struct varlist *, const char *);
! 27: static void doclearvlist (struct varlist *);
! 28: static void makequerydata (struct varlist *, int *, char *);
! 29: static int doquerylist (struct varlist *, int, associd_t, int,
! 30: u_short *, int *, const char **);
! 31: static void doprintvlist (struct varlist *, FILE *);
! 32: static void addvars (struct parse *, FILE *);
! 33: static void rmvars (struct parse *, FILE *);
! 34: static void clearvars (struct parse *, FILE *);
! 35: static void showvars (struct parse *, FILE *);
! 36: static int dolist (struct varlist *, associd_t, int, int,
! 37: FILE *);
! 38: static void readlist (struct parse *, FILE *);
! 39: static void writelist (struct parse *, FILE *);
! 40: static void readvar (struct parse *, FILE *);
! 41: static void writevar (struct parse *, FILE *);
! 42: static void clocklist (struct parse *, FILE *);
! 43: static void clockvar (struct parse *, FILE *);
! 44: static int findassidrange (u_int32, u_int32, int *, int *);
! 45: static void mreadlist (struct parse *, FILE *);
! 46: static void mreadvar (struct parse *, FILE *);
! 47: static int dogetassoc (FILE *);
! 48: static void printassoc (int, FILE *);
! 49: static void associations (struct parse *, FILE *);
! 50: static void lassociations (struct parse *, FILE *);
! 51: static void passociations (struct parse *, FILE *);
! 52: static void lpassociations (struct parse *, FILE *);
! 53:
! 54: #ifdef UNUSED
! 55: static void radiostatus (struct parse *, FILE *);
! 56: #endif /* UNUSED */
! 57:
! 58: static void pstatus (struct parse *, FILE *);
! 59: static long when (l_fp *, l_fp *, l_fp *);
! 60: static char * prettyinterval (char *, size_t, long);
! 61: static int doprintpeers (struct varlist *, int, int, int, const char *, FILE *, int);
! 62: static int dogetpeers (struct varlist *, associd_t, FILE *, int);
! 63: static void dopeers (int, FILE *, int);
! 64: static void peers (struct parse *, FILE *);
! 65: static void lpeers (struct parse *, FILE *);
! 66: static void doopeers (int, FILE *, int);
! 67: static void opeers (struct parse *, FILE *);
! 68: static void lopeers (struct parse *, FILE *);
! 69: static void config (struct parse *, FILE *);
! 70: static void saveconfig (struct parse *, FILE *);
! 71: static void config_from_file(struct parse *, FILE *);
! 72:
! 73:
! 74: /*
! 75: * Commands we understand. Ntpdc imports this.
! 76: */
! 77: struct xcmd opcmds[] = {
! 78: { "saveconfig", saveconfig, { NTP_STR, NO, NO, NO },
! 79: { "filename", "", "", ""},
! 80: "save ntpd configuration to file, . for current config file"},
! 81: { "associations", associations, { NO, NO, NO, NO },
! 82: { "", "", "", "" },
! 83: "print list of association ID's and statuses for the server's peers" },
! 84: { "passociations", passociations, { NO, NO, NO, NO },
! 85: { "", "", "", "" },
! 86: "print list of associations returned by last associations command" },
! 87: { "lassociations", lassociations, { NO, NO, NO, NO },
! 88: { "", "", "", "" },
! 89: "print list of associations including all client information" },
! 90: { "lpassociations", lpassociations, { NO, NO, NO, NO },
! 91: { "", "", "", "" },
! 92: "print last obtained list of associations, including client information" },
! 93: { "addvars", addvars, { NTP_STR, NO, NO, NO },
! 94: { "name[=value][,...]", "", "", "" },
! 95: "add variables to the variable list or change their values" },
! 96: { "rmvars", rmvars, { NTP_STR, NO, NO, NO },
! 97: { "name[,...]", "", "", "" },
! 98: "remove variables from the variable list" },
! 99: { "clearvars", clearvars, { NO, NO, NO, NO },
! 100: { "", "", "", "" },
! 101: "remove all variables from the variable list" },
! 102: { "showvars", showvars, { NO, NO, NO, NO },
! 103: { "", "", "", "" },
! 104: "print variables on the variable list" },
! 105: { "readlist", readlist, { OPT|NTP_UINT, NO, NO, NO },
! 106: { "assocID", "", "", "" },
! 107: "read the system or peer variables included in the variable list" },
! 108: { "rl", readlist, { OPT|NTP_UINT, NO, NO, NO },
! 109: { "assocID", "", "", "" },
! 110: "read the system or peer variables included in the variable list" },
! 111: { "writelist", writelist, { OPT|NTP_UINT, NO, NO, NO },
! 112: { "assocID", "", "", "" },
! 113: "write the system or peer variables included in the variable list" },
! 114: { "readvar", readvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
! 115: { "assocID", "name=value[,...]", "", "" },
! 116: "read system or peer variables" },
! 117: { "rv", readvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
! 118: { "assocID", "name=value[,...]", "", "" },
! 119: "read system or peer variables" },
! 120: { "writevar", writevar, { NTP_UINT, NTP_STR, NO, NO },
! 121: { "assocID", "name=value,[...]", "", "" },
! 122: "write system or peer variables" },
! 123: { "mreadlist", mreadlist, { NTP_UINT, NTP_UINT, NO, NO },
! 124: { "assocID", "assocID", "", "" },
! 125: "read the peer variables in the variable list for multiple peers" },
! 126: { "mrl", mreadlist, { NTP_UINT, NTP_UINT, NO, NO },
! 127: { "assocID", "assocID", "", "" },
! 128: "read the peer variables in the variable list for multiple peers" },
! 129: { "mreadvar", mreadvar, { NTP_UINT, NTP_UINT, OPT|NTP_STR, NO },
! 130: { "assocID", "assocID", "name=value[,...]", "" },
! 131: "read peer variables from multiple peers" },
! 132: { "mrv", mreadvar, { NTP_UINT, NTP_UINT, OPT|NTP_STR, NO },
! 133: { "assocID", "assocID", "name=value[,...]", "" },
! 134: "read peer variables from multiple peers" },
! 135: { "clocklist", clocklist, { OPT|NTP_UINT, NO, NO, NO },
! 136: { "assocID", "", "", "" },
! 137: "read the clock variables included in the variable list" },
! 138: { "cl", clocklist, { OPT|NTP_UINT, NO, NO, NO },
! 139: { "assocID", "", "", "" },
! 140: "read the clock variables included in the variable list" },
! 141: { "clockvar", clockvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
! 142: { "assocID", "name=value[,...]", "", "" },
! 143: "read clock variables" },
! 144: { "cv", clockvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
! 145: { "assocID", "name=value[,...]", "", "" },
! 146: "read clock variables" },
! 147: { "pstatus", pstatus, { NTP_UINT, NO, NO, NO },
! 148: { "assocID", "", "", "" },
! 149: "print status information returned for a peer" },
! 150: { "peers", peers, { OPT|IP_VERSION, NO, NO, NO },
! 151: { "-4|-6", "", "", "" },
! 152: "obtain and print a list of the server's peers [IP version]" },
! 153: { "lpeers", lpeers, { OPT|IP_VERSION, NO, NO, NO },
! 154: { "-4|-6", "", "", "" },
! 155: "obtain and print a list of all peers and clients [IP version]" },
! 156: { "opeers", opeers, { OPT|IP_VERSION, NO, NO, NO },
! 157: { "-4|-6", "", "", "" },
! 158: "print peer list the old way, with dstadr shown rather than refid [IP version]" },
! 159: { "lopeers", lopeers, { OPT|IP_VERSION, NO, NO, NO },
! 160: { "-4|-6", "", "", "" },
! 161: "obtain and print a list of all peers and clients showing dstadr [IP version]" },
! 162: { ":config", config, { NTP_STR, NO, NO, NO },
! 163: { "<configuration command line>", "", "", "" },
! 164: "send a remote configuration command to ntpd" },
! 165: { "config-from-file", config_from_file, { NTP_STR, NO, NO, NO },
! 166: { "<configuration filename>", "", "", "" },
! 167: "configure ntpd using the configuration filename" },
! 168: { 0, 0, { NO, NO, NO, NO },
! 169: { "-4|-6", "", "", "" }, "" }
! 170: };
! 171:
! 172:
! 173: /*
! 174: * Variable list data space
! 175: */
! 176: #define MAXLINE 512 /* maximum length of a line */
! 177: #define MAXLIST 64 /* maximum number of variables in list */
! 178: #define LENHOSTNAME 256 /* host name is 256 characters long */
! 179: /*
! 180: * Old CTL_PST defines for version 2.
! 181: */
! 182: #define OLD_CTL_PST_CONFIG 0x80
! 183: #define OLD_CTL_PST_AUTHENABLE 0x40
! 184: #define OLD_CTL_PST_AUTHENTIC 0x20
! 185: #define OLD_CTL_PST_REACH 0x10
! 186: #define OLD_CTL_PST_SANE 0x08
! 187: #define OLD_CTL_PST_DISP 0x04
! 188:
! 189: #define OLD_CTL_PST_SEL_REJECT 0
! 190: #define OLD_CTL_PST_SEL_SELCAND 1
! 191: #define OLD_CTL_PST_SEL_SYNCCAND 2
! 192: #define OLD_CTL_PST_SEL_SYSPEER 3
! 193:
! 194: char flash2[] = " .+* "; /* flash decode for version 2 */
! 195: char flash3[] = " x.-+#*o"; /* flash decode for peer status version 3 */
! 196:
! 197: struct varlist {
! 198: char *name;
! 199: char *value;
! 200: } g_varlist[MAXLIST] = { { 0, 0 } };
! 201:
! 202: /*
! 203: * Imported from ntpq.c
! 204: */
! 205: extern int showhostnames;
! 206: extern int rawmode;
! 207: extern struct servent *server_entry;
! 208: extern struct association assoc_cache[];
! 209: extern int numassoc;
! 210: extern u_char pktversion;
! 211: extern struct ctl_var peer_var[];
! 212:
! 213: /*
! 214: * For quick string comparisons
! 215: */
! 216: #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
! 217:
! 218:
! 219: /*
! 220: * checkassocid - return the association ID, checking to see if it is valid
! 221: */
! 222: static associd_t
! 223: checkassocid(
! 224: u_int32 value
! 225: )
! 226: {
! 227: associd_t associd;
! 228: u_long ulvalue;
! 229:
! 230: associd = (associd_t)value;
! 231: if (0 == associd || value != associd) {
! 232: ulvalue = value;
! 233: fprintf(stderr,
! 234: "***Invalid association ID %lu specified\n",
! 235: ulvalue);
! 236: return 0;
! 237: }
! 238:
! 239: return associd;
! 240: }
! 241:
! 242:
! 243: /*
! 244: * findlistvar - look for the named variable in a list and return if found
! 245: */
! 246: static struct varlist *
! 247: findlistvar(
! 248: struct varlist *list,
! 249: char *name
! 250: )
! 251: {
! 252: register struct varlist *vl;
! 253:
! 254: for (vl = list; vl < list + MAXLIST && vl->name != 0; vl++)
! 255: if (STREQ(name, vl->name))
! 256: return vl;
! 257: if (vl < list + MAXLIST)
! 258: return vl;
! 259: return (struct varlist *)0;
! 260: }
! 261:
! 262:
! 263: /*
! 264: * doaddvlist - add variable(s) to the variable list
! 265: */
! 266: static void
! 267: doaddvlist(
! 268: struct varlist *vlist,
! 269: const char *vars
! 270: )
! 271: {
! 272: register struct varlist *vl;
! 273: int len;
! 274: char *name;
! 275: char *value;
! 276:
! 277: len = strlen(vars);
! 278: while (nextvar(&len, &vars, &name, &value)) {
! 279: vl = findlistvar(vlist, name);
! 280: if (vl == 0) {
! 281: (void) fprintf(stderr, "Variable list full\n");
! 282: return;
! 283: }
! 284:
! 285: if (vl->name == 0) {
! 286: vl->name = estrdup(name);
! 287: } else if (vl->value != 0) {
! 288: free(vl->value);
! 289: vl->value = 0;
! 290: }
! 291:
! 292: if (value != 0)
! 293: vl->value = estrdup(value);
! 294: }
! 295: }
! 296:
! 297:
! 298: /*
! 299: * dormvlist - remove variable(s) from the variable list
! 300: */
! 301: static void
! 302: dormvlist(
! 303: struct varlist *vlist,
! 304: const char *vars
! 305: )
! 306: {
! 307: register struct varlist *vl;
! 308: int len;
! 309: char *name;
! 310: char *value;
! 311:
! 312: len = strlen(vars);
! 313: while (nextvar(&len, &vars, &name, &value)) {
! 314: vl = findlistvar(vlist, name);
! 315: if (vl == 0 || vl->name == 0) {
! 316: (void) fprintf(stderr, "Variable `%s' not found\n",
! 317: name);
! 318: } else {
! 319: free((void *)vl->name);
! 320: if (vl->value != 0)
! 321: free(vl->value);
! 322: for ( ; (vl+1) < (g_varlist + MAXLIST)
! 323: && (vl+1)->name != 0; vl++) {
! 324: vl->name = (vl+1)->name;
! 325: vl->value = (vl+1)->value;
! 326: }
! 327: vl->name = vl->value = 0;
! 328: }
! 329: }
! 330: }
! 331:
! 332:
! 333: /*
! 334: * doclearvlist - clear a variable list
! 335: */
! 336: static void
! 337: doclearvlist(
! 338: struct varlist *vlist
! 339: )
! 340: {
! 341: register struct varlist *vl;
! 342:
! 343: for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
! 344: free((void *)vl->name);
! 345: vl->name = 0;
! 346: if (vl->value != 0) {
! 347: free(vl->value);
! 348: vl->value = 0;
! 349: }
! 350: }
! 351: }
! 352:
! 353:
! 354: /*
! 355: * makequerydata - form a data buffer to be included with a query
! 356: */
! 357: static void
! 358: makequerydata(
! 359: struct varlist *vlist,
! 360: int *datalen,
! 361: char *data
! 362: )
! 363: {
! 364: register struct varlist *vl;
! 365: register char *cp, *cpend;
! 366: register int namelen, valuelen;
! 367: register int totallen;
! 368:
! 369: cp = data;
! 370: cpend = data + *datalen;
! 371:
! 372: for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
! 373: namelen = strlen(vl->name);
! 374: if (vl->value == 0)
! 375: valuelen = 0;
! 376: else
! 377: valuelen = strlen(vl->value);
! 378: totallen = namelen + valuelen + (valuelen != 0) + (cp != data);
! 379: if (cp + totallen > cpend)
! 380: break;
! 381:
! 382: if (cp != data)
! 383: *cp++ = ',';
! 384: memmove(cp, vl->name, (unsigned)namelen);
! 385: cp += namelen;
! 386: if (valuelen != 0) {
! 387: *cp++ = '=';
! 388: memmove(cp, vl->value, (unsigned)valuelen);
! 389: cp += valuelen;
! 390: }
! 391: }
! 392: *datalen = cp - data;
! 393: }
! 394:
! 395:
! 396: /*
! 397: * doquerylist - send a message including variables in a list
! 398: */
! 399: static int
! 400: doquerylist(
! 401: struct varlist *vlist,
! 402: int op,
! 403: associd_t associd,
! 404: int auth,
! 405: u_short *rstatus,
! 406: int *dsize,
! 407: const char **datap
! 408: )
! 409: {
! 410: char data[CTL_MAX_DATA_LEN];
! 411: int datalen;
! 412:
! 413: datalen = sizeof(data);
! 414: makequerydata(vlist, &datalen, data);
! 415:
! 416: return doquery(op, associd, auth, datalen, data, rstatus,
! 417: dsize, datap);
! 418: }
! 419:
! 420:
! 421: /*
! 422: * doprintvlist - print the variables on a list
! 423: */
! 424: static void
! 425: doprintvlist(
! 426: struct varlist *vlist,
! 427: FILE *fp
! 428: )
! 429: {
! 430: register struct varlist *vl;
! 431:
! 432: if (vlist->name == 0) {
! 433: (void) fprintf(fp, "No variables on list\n");
! 434: } else {
! 435: for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
! 436: if (vl->value == 0) {
! 437: (void) fprintf(fp, "%s\n", vl->name);
! 438: } else {
! 439: (void) fprintf(fp, "%s=%s\n",
! 440: vl->name, vl->value);
! 441: }
! 442: }
! 443: }
! 444: }
! 445:
! 446: /*
! 447: * addvars - add variables to the variable list
! 448: */
! 449: /*ARGSUSED*/
! 450: static void
! 451: addvars(
! 452: struct parse *pcmd,
! 453: FILE *fp
! 454: )
! 455: {
! 456: doaddvlist(g_varlist, pcmd->argval[0].string);
! 457: }
! 458:
! 459:
! 460: /*
! 461: * rmvars - remove variables from the variable list
! 462: */
! 463: /*ARGSUSED*/
! 464: static void
! 465: rmvars(
! 466: struct parse *pcmd,
! 467: FILE *fp
! 468: )
! 469: {
! 470: dormvlist(g_varlist, pcmd->argval[0].string);
! 471: }
! 472:
! 473:
! 474: /*
! 475: * clearvars - clear the variable list
! 476: */
! 477: /*ARGSUSED*/
! 478: static void
! 479: clearvars(
! 480: struct parse *pcmd,
! 481: FILE *fp
! 482: )
! 483: {
! 484: doclearvlist(g_varlist);
! 485: }
! 486:
! 487:
! 488: /*
! 489: * showvars - show variables on the variable list
! 490: */
! 491: /*ARGSUSED*/
! 492: static void
! 493: showvars(
! 494: struct parse *pcmd,
! 495: FILE *fp
! 496: )
! 497: {
! 498: doprintvlist(g_varlist, fp);
! 499: }
! 500:
! 501:
! 502: /*
! 503: * dolist - send a request with the given list of variables
! 504: */
! 505: static int
! 506: dolist(
! 507: struct varlist *vlist,
! 508: associd_t associd,
! 509: int op,
! 510: int type,
! 511: FILE *fp
! 512: )
! 513: {
! 514: const char *datap;
! 515: int res;
! 516: int dsize;
! 517: u_short rstatus;
! 518: int quiet;
! 519:
! 520: /*
! 521: * if we're asking for specific variables don't include the
! 522: * status header line in the output.
! 523: */
! 524: if (old_rv)
! 525: quiet = 0;
! 526: else
! 527: quiet = (vlist->name != NULL);
! 528:
! 529: res = doquerylist(vlist, op, associd, 0, &rstatus, &dsize, &datap);
! 530:
! 531: if (res != 0)
! 532: return 0;
! 533:
! 534: if (numhosts > 1)
! 535: (void) fprintf(fp, "server=%s ", currenthost);
! 536: if (dsize == 0) {
! 537: if (associd == 0)
! 538: (void) fprintf(fp, "No system%s variables returned\n",
! 539: (type == TYPE_CLOCK) ? " clock" : "");
! 540: else
! 541: (void) fprintf(fp,
! 542: "No information returned for%s association %u\n",
! 543: (type == TYPE_CLOCK) ? " clock" : "", associd);
! 544: return 1;
! 545: }
! 546:
! 547: if (!quiet)
! 548: fprintf(fp,"associd=%d ",associd);
! 549: printvars(dsize, datap, (int)rstatus, type, quiet, fp);
! 550: return 1;
! 551: }
! 552:
! 553:
! 554: /*
! 555: * readlist - send a read variables request with the variables on the list
! 556: */
! 557: static void
! 558: readlist(
! 559: struct parse *pcmd,
! 560: FILE *fp
! 561: )
! 562: {
! 563: associd_t associd;
! 564: int type;
! 565:
! 566: if (pcmd->nargs == 0) {
! 567: associd = 0;
! 568: } else {
! 569: /* HMS: I think we want the u_int32 target here, not the u_long */
! 570: if (pcmd->argval[0].uval == 0)
! 571: associd = 0;
! 572: else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
! 573: return;
! 574: }
! 575:
! 576: type = (0 == associd)
! 577: ? TYPE_SYS
! 578: : TYPE_PEER;
! 579: dolist(g_varlist, associd, CTL_OP_READVAR, type, fp);
! 580: }
! 581:
! 582:
! 583: /*
! 584: * writelist - send a write variables request with the variables on the list
! 585: */
! 586: static void
! 587: writelist(
! 588: struct parse *pcmd,
! 589: FILE *fp
! 590: )
! 591: {
! 592: const char *datap;
! 593: int res;
! 594: associd_t associd;
! 595: int dsize;
! 596: u_short rstatus;
! 597:
! 598: if (pcmd->nargs == 0) {
! 599: associd = 0;
! 600: } else {
! 601: /* HMS: Do we really want uval here? */
! 602: if (pcmd->argval[0].uval == 0)
! 603: associd = 0;
! 604: else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
! 605: return;
! 606: }
! 607:
! 608: res = doquerylist(g_varlist, CTL_OP_WRITEVAR, associd, 1, &rstatus,
! 609: &dsize, &datap);
! 610:
! 611: if (res != 0)
! 612: return;
! 613:
! 614: if (numhosts > 1)
! 615: (void) fprintf(fp, "server=%s ", currenthost);
! 616: if (dsize == 0)
! 617: (void) fprintf(fp, "done! (no data returned)\n");
! 618: else {
! 619: (void) fprintf(fp,"associd=%d ",associd);
! 620: printvars(dsize, datap, (int)rstatus,
! 621: (associd != 0) ? TYPE_PEER : TYPE_SYS, 0, fp);
! 622: }
! 623: return;
! 624: }
! 625:
! 626:
! 627: /*
! 628: * readvar - send a read variables request with the specified variables
! 629: */
! 630: static void
! 631: readvar(
! 632: struct parse *pcmd,
! 633: FILE *fp
! 634: )
! 635: {
! 636: associd_t associd;
! 637: int type;
! 638: struct varlist tmplist[MAXLIST];
! 639:
! 640:
! 641: /* HMS: uval? */
! 642: if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
! 643: associd = 0;
! 644: else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
! 645: return;
! 646:
! 647: memset(tmplist, 0, sizeof(tmplist));
! 648: if (pcmd->nargs >= 2)
! 649: doaddvlist(tmplist, pcmd->argval[1].string);
! 650:
! 651: type = (0 == associd)
! 652: ? TYPE_SYS
! 653: : TYPE_PEER;
! 654: dolist(tmplist, associd, CTL_OP_READVAR, type, fp);
! 655:
! 656: doclearvlist(tmplist);
! 657: }
! 658:
! 659:
! 660: /*
! 661: * writevar - send a write variables request with the specified variables
! 662: */
! 663: static void
! 664: writevar(
! 665: struct parse *pcmd,
! 666: FILE *fp
! 667: )
! 668: {
! 669: const char *datap;
! 670: int res;
! 671: associd_t associd;
! 672: int type;
! 673: int dsize;
! 674: u_short rstatus;
! 675: struct varlist tmplist[MAXLIST];
! 676:
! 677: /* HMS: uval? */
! 678: if (pcmd->argval[0].uval == 0)
! 679: associd = 0;
! 680: else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
! 681: return;
! 682:
! 683: memset((char *)tmplist, 0, sizeof(tmplist));
! 684: doaddvlist(tmplist, pcmd->argval[1].string);
! 685:
! 686: res = doquerylist(tmplist, CTL_OP_WRITEVAR, associd, 1, &rstatus,
! 687: &dsize, &datap);
! 688:
! 689: doclearvlist(tmplist);
! 690:
! 691: if (res != 0)
! 692: return;
! 693:
! 694: if (numhosts > 1)
! 695: fprintf(fp, "server=%s ", currenthost);
! 696: if (dsize == 0)
! 697: fprintf(fp, "done! (no data returned)\n");
! 698: else {
! 699: fprintf(fp,"associd=%d ",associd);
! 700: type = (0 == associd)
! 701: ? TYPE_SYS
! 702: : TYPE_PEER;
! 703: printvars(dsize, datap, (int)rstatus, type, 0, fp);
! 704: }
! 705: return;
! 706: }
! 707:
! 708:
! 709: /*
! 710: * clocklist - send a clock variables request with the variables on the list
! 711: */
! 712: static void
! 713: clocklist(
! 714: struct parse *pcmd,
! 715: FILE *fp
! 716: )
! 717: {
! 718: associd_t associd;
! 719:
! 720: /* HMS: uval? */
! 721: if (pcmd->nargs == 0) {
! 722: associd = 0;
! 723: } else {
! 724: if (pcmd->argval[0].uval == 0)
! 725: associd = 0;
! 726: else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
! 727: return;
! 728: }
! 729:
! 730: dolist(g_varlist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
! 731: }
! 732:
! 733:
! 734: /*
! 735: * clockvar - send a clock variables request with the specified variables
! 736: */
! 737: static void
! 738: clockvar(
! 739: struct parse *pcmd,
! 740: FILE *fp
! 741: )
! 742: {
! 743: associd_t associd;
! 744: struct varlist tmplist[MAXLIST];
! 745:
! 746: /* HMS: uval? */
! 747: if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
! 748: associd = 0;
! 749: else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
! 750: return;
! 751:
! 752: memset(tmplist, 0, sizeof(tmplist));
! 753: if (pcmd->nargs >= 2)
! 754: doaddvlist(tmplist, pcmd->argval[1].string);
! 755:
! 756: dolist(tmplist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
! 757:
! 758: doclearvlist(tmplist);
! 759: }
! 760:
! 761:
! 762: /*
! 763: * findassidrange - verify a range of association ID's
! 764: */
! 765: static int
! 766: findassidrange(
! 767: u_int32 assid1,
! 768: u_int32 assid2,
! 769: int *from,
! 770: int *to
! 771: )
! 772: {
! 773: associd_t assids[2];
! 774: int ind[COUNTOF(assids)];
! 775: int i;
! 776: size_t a;
! 777:
! 778: assids[0] = checkassocid(assid1);
! 779: if (0 == assids[0])
! 780: return 0;
! 781: assids[1] = checkassocid(assid2);
! 782: if (0 == assids[1])
! 783: return 0;
! 784:
! 785: for (a = 0; a < COUNTOF(assids); a++) {
! 786: ind[a] = -1;
! 787: for (i = 0; i < numassoc; i++)
! 788: if (assoc_cache[i].assid == assids[a])
! 789: ind[a] = i;
! 790: }
! 791: for (a = 0; a < COUNTOF(assids); a++)
! 792: if (-1 == ind[a]) {
! 793: fprintf(stderr,
! 794: "***Association ID %u not found in list\n",
! 795: assids[a]);
! 796: return 0;
! 797: }
! 798:
! 799: if (ind[0] < ind[1]) {
! 800: *from = ind[0];
! 801: *to = ind[1];
! 802: } else {
! 803: *to = ind[0];
! 804: *from = ind[1];
! 805: }
! 806: return 1;
! 807: }
! 808:
! 809:
! 810:
! 811: /*
! 812: * mreadlist - send a read variables request for multiple associations
! 813: */
! 814: static void
! 815: mreadlist(
! 816: struct parse *pcmd,
! 817: FILE *fp
! 818: )
! 819: {
! 820: int i;
! 821: int from;
! 822: int to;
! 823:
! 824: /* HMS: uval? */
! 825: if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
! 826: &from, &to))
! 827: return;
! 828:
! 829: for (i = from; i <= to; i++) {
! 830: if (i != from)
! 831: (void) fprintf(fp, "\n");
! 832: if (!dolist(g_varlist, (int)assoc_cache[i].assid,
! 833: CTL_OP_READVAR, TYPE_PEER, fp))
! 834: return;
! 835: }
! 836: return;
! 837: }
! 838:
! 839:
! 840: /*
! 841: * mreadvar - send a read variables request for multiple associations
! 842: */
! 843: static void
! 844: mreadvar(
! 845: struct parse *pcmd,
! 846: FILE *fp
! 847: )
! 848: {
! 849: int i;
! 850: int from;
! 851: int to;
! 852: struct varlist tmplist[MAXLIST];
! 853: struct varlist *pvars;
! 854:
! 855: /* HMS: uval? */
! 856: if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
! 857: &from, &to))
! 858: return;
! 859:
! 860: if (pcmd->nargs >= 3) {
! 861: memset(tmplist, 0, sizeof(tmplist));
! 862: doaddvlist(tmplist, pcmd->argval[2].string);
! 863: pvars = tmplist;
! 864: } else {
! 865: pvars = g_varlist;
! 866: }
! 867:
! 868: for (i = from; i <= to; i++) {
! 869: if (i != from)
! 870: fprintf(fp, "\n");
! 871: if (!dolist(pvars, (int)assoc_cache[i].assid,
! 872: CTL_OP_READVAR, TYPE_PEER, fp))
! 873: break;
! 874: }
! 875: doclearvlist(tmplist);
! 876: return;
! 877: }
! 878:
! 879:
! 880: /*
! 881: * dogetassoc - query the host for its list of associations
! 882: */
! 883: static int
! 884: dogetassoc(
! 885: FILE *fp
! 886: )
! 887: {
! 888: const char *datap;
! 889: int res;
! 890: int dsize;
! 891: u_short rstatus;
! 892:
! 893: res = doquery(CTL_OP_READSTAT, 0, 0, 0, (char *)0, &rstatus,
! 894: &dsize, &datap);
! 895:
! 896: if (res != 0)
! 897: return 0;
! 898:
! 899: if (dsize == 0) {
! 900: if (numhosts > 1)
! 901: (void) fprintf(fp, "server=%s ", currenthost);
! 902: (void) fprintf(fp, "No association ID's returned\n");
! 903: return 0;
! 904: }
! 905:
! 906: if (dsize & 0x3) {
! 907: if (numhosts > 1)
! 908: (void) fprintf(stderr, "server=%s ", currenthost);
! 909: (void) fprintf(stderr,
! 910: "***Server returned %d octets, should be multiple of 4\n",
! 911: dsize);
! 912: return 0;
! 913: }
! 914:
! 915: numassoc = 0;
! 916: while (dsize > 0) {
! 917: assoc_cache[numassoc].assid = ntohs(*((const u_short *)datap));
! 918: datap += sizeof(u_short);
! 919: assoc_cache[numassoc].status = ntohs(*((const u_short *)datap));
! 920: datap += sizeof(u_short);
! 921: if (++numassoc >= MAXASSOC)
! 922: break;
! 923: dsize -= sizeof(u_short) + sizeof(u_short);
! 924: }
! 925: sortassoc();
! 926: return 1;
! 927: }
! 928:
! 929:
! 930: /*
! 931: * printassoc - print the current list of associations
! 932: */
! 933: static void
! 934: printassoc(
! 935: int showall,
! 936: FILE *fp
! 937: )
! 938: {
! 939: register char *bp;
! 940: int i;
! 941: u_char statval;
! 942: int event;
! 943: u_long event_count;
! 944: const char *conf;
! 945: const char *reach;
! 946: const char *auth;
! 947: const char *condition = "";
! 948: const char *last_event;
! 949: const char *cnt;
! 950: char buf[128];
! 951:
! 952: if (numassoc == 0) {
! 953: (void) fprintf(fp, "No association ID's in list\n");
! 954: return;
! 955: }
! 956:
! 957: /*
! 958: * Output a header
! 959: */
! 960: (void) fprintf(fp,
! 961: "\nind assid status conf reach auth condition last_event cnt\n");
! 962: (void) fprintf(fp,
! 963: "===========================================================\n");
! 964: for (i = 0; i < numassoc; i++) {
! 965: statval = (u_char) CTL_PEER_STATVAL(assoc_cache[i].status);
! 966: if (!showall && !(statval & (CTL_PST_CONFIG|CTL_PST_REACH)))
! 967: continue;
! 968: event = CTL_PEER_EVENT(assoc_cache[i].status);
! 969: event_count = CTL_PEER_NEVNT(assoc_cache[i].status);
! 970: if (statval & CTL_PST_CONFIG)
! 971: conf = "yes";
! 972: else
! 973: conf = "no";
! 974: if (statval & CTL_PST_BCAST) {
! 975: reach = "none";
! 976: if (statval & CTL_PST_AUTHENABLE)
! 977: auth = "yes";
! 978: else
! 979: auth = "none";
! 980: } else {
! 981: if (statval & CTL_PST_REACH)
! 982: reach = "yes";
! 983: else
! 984: reach = "no";
! 985: if (statval & CTL_PST_AUTHENABLE) {
! 986: if (statval & CTL_PST_AUTHENTIC)
! 987: auth = "ok ";
! 988: else
! 989: auth = "bad";
! 990: } else {
! 991: auth = "none";
! 992: }
! 993: }
! 994: if (pktversion > NTP_OLDVERSION) {
! 995: switch (statval & 0x7) {
! 996:
! 997: case CTL_PST_SEL_REJECT:
! 998: condition = "reject";
! 999: break;
! 1000:
! 1001: case CTL_PST_SEL_SANE:
! 1002: condition = "falsetick";
! 1003: break;
! 1004:
! 1005: case CTL_PST_SEL_CORRECT:
! 1006: condition = "excess";
! 1007: break;
! 1008:
! 1009: case CTL_PST_SEL_SELCAND:
! 1010: condition = "outlyer";
! 1011: break;
! 1012:
! 1013: case CTL_PST_SEL_SYNCCAND:
! 1014: condition = "candidate";
! 1015: break;
! 1016:
! 1017: case CTL_PST_SEL_EXCESS:
! 1018: condition = "backup";
! 1019: break;
! 1020:
! 1021: case CTL_PST_SEL_SYSPEER:
! 1022: condition = "sys.peer";
! 1023: break;
! 1024:
! 1025: case CTL_PST_SEL_PPS:
! 1026: condition = "pps.peer";
! 1027: break;
! 1028: }
! 1029: } else {
! 1030: switch (statval & 0x3) {
! 1031:
! 1032: case OLD_CTL_PST_SEL_REJECT:
! 1033: if (!(statval & OLD_CTL_PST_SANE))
! 1034: condition = "insane";
! 1035: else if (!(statval & OLD_CTL_PST_DISP))
! 1036: condition = "hi_disp";
! 1037: else
! 1038: condition = "";
! 1039: break;
! 1040:
! 1041: case OLD_CTL_PST_SEL_SELCAND:
! 1042: condition = "sel_cand";
! 1043: break;
! 1044:
! 1045: case OLD_CTL_PST_SEL_SYNCCAND:
! 1046: condition = "sync_cand";
! 1047: break;
! 1048:
! 1049: case OLD_CTL_PST_SEL_SYSPEER:
! 1050: condition = "sys_peer";
! 1051: break;
! 1052: }
! 1053: }
! 1054: switch (PEER_EVENT|event) {
! 1055:
! 1056: case PEVNT_MOBIL:
! 1057: last_event = "mobilize";
! 1058: break;
! 1059:
! 1060: case PEVNT_DEMOBIL:
! 1061: last_event = "demobilize";
! 1062: break;
! 1063:
! 1064: case PEVNT_REACH:
! 1065: last_event = "reachable";
! 1066: break;
! 1067:
! 1068: case PEVNT_UNREACH:
! 1069: last_event = "unreachable";
! 1070: break;
! 1071:
! 1072: case PEVNT_RESTART:
! 1073: last_event = "restart";
! 1074: break;
! 1075:
! 1076: case PEVNT_REPLY:
! 1077: last_event = "no_reply";
! 1078: break;
! 1079:
! 1080: case PEVNT_RATE:
! 1081: last_event = "rate_exceeded";
! 1082: break;
! 1083:
! 1084: case PEVNT_DENY:
! 1085: last_event = "access_denied";
! 1086: break;
! 1087:
! 1088: case PEVNT_ARMED:
! 1089: last_event = "leap_armed";
! 1090: break;
! 1091:
! 1092: case PEVNT_NEWPEER:
! 1093: last_event = "sys_peer";
! 1094: break;
! 1095:
! 1096: case PEVNT_CLOCK:
! 1097: last_event = "clock_alarm";
! 1098: break;
! 1099:
! 1100: default:
! 1101: last_event = "";
! 1102: break;
! 1103: }
! 1104: cnt = uinttoa(event_count);
! 1105: snprintf(buf, sizeof(buf),
! 1106: "%3d %5u %04x %3.3s %4s %4.4s %9.9s %11s %2s",
! 1107: i + 1, assoc_cache[i].assid,
! 1108: assoc_cache[i].status, conf, reach, auth,
! 1109: condition, last_event, cnt);
! 1110: bp = buf + strlen(buf);
! 1111: while (bp > buf && ' ' == bp[-1])
! 1112: --bp;
! 1113: bp[0] = '\0';
! 1114: fprintf(fp, "%s\n", buf);
! 1115: }
! 1116: }
! 1117:
! 1118:
! 1119: /*
! 1120: * associations - get, record and print a list of associations
! 1121: */
! 1122: /*ARGSUSED*/
! 1123: static void
! 1124: associations(
! 1125: struct parse *pcmd,
! 1126: FILE *fp
! 1127: )
! 1128: {
! 1129: if (dogetassoc(fp))
! 1130: printassoc(0, fp);
! 1131: }
! 1132:
! 1133:
! 1134: /*
! 1135: * lassociations - get, record and print a long list of associations
! 1136: */
! 1137: /*ARGSUSED*/
! 1138: static void
! 1139: lassociations(
! 1140: struct parse *pcmd,
! 1141: FILE *fp
! 1142: )
! 1143: {
! 1144: if (dogetassoc(fp))
! 1145: printassoc(1, fp);
! 1146: }
! 1147:
! 1148:
! 1149: /*
! 1150: * passociations - print the association list
! 1151: */
! 1152: /*ARGSUSED*/
! 1153: static void
! 1154: passociations(
! 1155: struct parse *pcmd,
! 1156: FILE *fp
! 1157: )
! 1158: {
! 1159: printassoc(0, fp);
! 1160: }
! 1161:
! 1162:
! 1163: /*
! 1164: * lpassociations - print the long association list
! 1165: */
! 1166: /*ARGSUSED*/
! 1167: static void
! 1168: lpassociations(
! 1169: struct parse *pcmd,
! 1170: FILE *fp
! 1171: )
! 1172: {
! 1173: printassoc(1, fp);
! 1174: }
! 1175:
! 1176:
! 1177: /*
! 1178: * saveconfig - dump ntp server configuration to server file
! 1179: */
! 1180: static void
! 1181: saveconfig(
! 1182: struct parse *pcmd,
! 1183: FILE *fp
! 1184: )
! 1185: {
! 1186: const char *datap;
! 1187: int res;
! 1188: int dsize;
! 1189: u_short rstatus;
! 1190:
! 1191: if (0 == pcmd->nargs)
! 1192: return;
! 1193:
! 1194: res = doquery(CTL_OP_SAVECONFIG, 0, 1,
! 1195: strlen(pcmd->argval[0].string),
! 1196: pcmd->argval[0].string, &rstatus, &dsize,
! 1197: &datap);
! 1198:
! 1199: if (res != 0)
! 1200: return;
! 1201:
! 1202: if (0 == dsize)
! 1203: fprintf(fp, "(no response message, curiously)");
! 1204: else
! 1205: fprintf(fp, "%.*s", dsize, datap);
! 1206: }
! 1207:
! 1208:
! 1209: #ifdef UNUSED
! 1210: /*
! 1211: * radiostatus - print the radio status returned by the server
! 1212: */
! 1213: /*ARGSUSED*/
! 1214: static void
! 1215: radiostatus(
! 1216: struct parse *pcmd,
! 1217: FILE *fp
! 1218: )
! 1219: {
! 1220: char *datap;
! 1221: int res;
! 1222: int dsize;
! 1223: u_short rstatus;
! 1224:
! 1225: res = doquery(CTL_OP_READCLOCK, 0, 0, 0, (char *)0, &rstatus,
! 1226: &dsize, &datap);
! 1227:
! 1228: if (res != 0)
! 1229: return;
! 1230:
! 1231: if (numhosts > 1)
! 1232: (void) fprintf(fp, "server=%s ", currenthost);
! 1233: if (dsize == 0) {
! 1234: (void) fprintf(fp, "No radio status string returned\n");
! 1235: return;
! 1236: }
! 1237:
! 1238: asciize(dsize, datap, fp);
! 1239: }
! 1240: #endif /* UNUSED */
! 1241:
! 1242: /*
! 1243: * pstatus - print peer status returned by the server
! 1244: */
! 1245: static void
! 1246: pstatus(
! 1247: struct parse *pcmd,
! 1248: FILE *fp
! 1249: )
! 1250: {
! 1251: const char *datap;
! 1252: int res;
! 1253: associd_t associd;
! 1254: int dsize;
! 1255: u_short rstatus;
! 1256:
! 1257: /* HMS: uval? */
! 1258: if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
! 1259: return;
! 1260:
! 1261: res = doquery(CTL_OP_READSTAT, associd, 0, 0, NULL, &rstatus,
! 1262: &dsize, &datap);
! 1263:
! 1264: if (res != 0)
! 1265: return;
! 1266:
! 1267: if (numhosts > 1)
! 1268: fprintf(fp, "server=%s ", currenthost);
! 1269: if (dsize == 0) {
! 1270: fprintf(fp,
! 1271: "No information returned for association %u\n",
! 1272: associd);
! 1273: return;
! 1274: }
! 1275:
! 1276: fprintf(fp, "associd=%u ", associd);
! 1277: printvars(dsize, datap, (int)rstatus, TYPE_PEER, 0, fp);
! 1278: }
! 1279:
! 1280:
! 1281: /*
! 1282: * when - print how long its been since his last packet arrived
! 1283: */
! 1284: static long
! 1285: when(
! 1286: l_fp *ts,
! 1287: l_fp *rec,
! 1288: l_fp *reftime
! 1289: )
! 1290: {
! 1291: l_fp *lasttime;
! 1292:
! 1293: if (rec->l_ui != 0)
! 1294: lasttime = rec;
! 1295: else if (reftime->l_ui != 0)
! 1296: lasttime = reftime;
! 1297: else
! 1298: return 0;
! 1299:
! 1300: return (ts->l_ui - lasttime->l_ui);
! 1301: }
! 1302:
! 1303:
! 1304: /*
! 1305: * Pretty-print an interval into the given buffer, in a human-friendly format.
! 1306: */
! 1307: static char *
! 1308: prettyinterval(
! 1309: char *buf,
! 1310: size_t cb,
! 1311: long diff
! 1312: )
! 1313: {
! 1314: if (diff <= 0) {
! 1315: buf[0] = '-';
! 1316: buf[1] = 0;
! 1317: return buf;
! 1318: }
! 1319:
! 1320: if (diff <= 2048) {
! 1321: snprintf(buf, cb, "%ld", diff);
! 1322: return buf;
! 1323: }
! 1324:
! 1325: diff = (diff + 29) / 60;
! 1326: if (diff <= 300) {
! 1327: snprintf(buf, cb, "%ldm", diff);
! 1328: return buf;
! 1329: }
! 1330:
! 1331: diff = (diff + 29) / 60;
! 1332: if (diff <= 96) {
! 1333: snprintf(buf, cb, "%ldh", diff);
! 1334: return buf;
! 1335: }
! 1336:
! 1337: diff = (diff + 11) / 24;
! 1338: snprintf(buf, cb, "%ldd", diff);
! 1339: return buf;
! 1340: }
! 1341:
! 1342: static char
! 1343: decodeaddrtype(
! 1344: sockaddr_u *sock
! 1345: )
! 1346: {
! 1347: char ch = '-';
! 1348: u_int32 dummy;
! 1349:
! 1350: switch(AF(sock)) {
! 1351: case AF_INET:
! 1352: dummy = SRCADR(sock);
! 1353: ch = (char)(((dummy&0xf0000000)==0xe0000000) ? 'm' :
! 1354: ((dummy&0x000000ff)==0x000000ff) ? 'b' :
! 1355: ((dummy&0xffffffff)==0x7f000001) ? 'l' :
! 1356: ((dummy&0xffffffe0)==0x00000000) ? '-' :
! 1357: 'u');
! 1358: break;
! 1359: case AF_INET6:
! 1360: if (IN6_IS_ADDR_MULTICAST(PSOCK_ADDR6(sock)))
! 1361: ch = 'm';
! 1362: else
! 1363: ch = 'u';
! 1364: break;
! 1365: default:
! 1366: ch = '-';
! 1367: break;
! 1368: }
! 1369: return ch;
! 1370: }
! 1371:
! 1372: /*
! 1373: * A list of variables required by the peers command
! 1374: */
! 1375: struct varlist opeervarlist[] = {
! 1376: { "srcadr", 0 }, /* 0 */
! 1377: { "dstadr", 0 }, /* 1 */
! 1378: { "stratum", 0 }, /* 2 */
! 1379: { "hpoll", 0 }, /* 3 */
! 1380: { "ppoll", 0 }, /* 4 */
! 1381: { "reach", 0 }, /* 5 */
! 1382: { "delay", 0 }, /* 6 */
! 1383: { "offset", 0 }, /* 7 */
! 1384: { "jitter", 0 }, /* 8 */
! 1385: { "dispersion", 0 }, /* 9 */
! 1386: { "rec", 0 }, /* 10 */
! 1387: { "reftime", 0 }, /* 11 */
! 1388: { "srcport", 0 }, /* 12 */
! 1389: { 0, 0 }
! 1390: };
! 1391:
! 1392: struct varlist peervarlist[] = {
! 1393: { "srcadr", 0 }, /* 0 */
! 1394: { "refid", 0 }, /* 1 */
! 1395: { "stratum", 0 }, /* 2 */
! 1396: { "hpoll", 0 }, /* 3 */
! 1397: { "ppoll", 0 }, /* 4 */
! 1398: { "reach", 0 }, /* 5 */
! 1399: { "delay", 0 }, /* 6 */
! 1400: { "offset", 0 }, /* 7 */
! 1401: { "jitter", 0 }, /* 8 */
! 1402: { "dispersion", 0 }, /* 9 */
! 1403: { "rec", 0 }, /* 10 */
! 1404: { "reftime", 0 }, /* 11 */
! 1405: { "srcport", 0 }, /* 12 */
! 1406: { 0, 0 }
! 1407: };
! 1408:
! 1409: #define HAVE_SRCADR 0
! 1410: #define HAVE_DSTADR 1
! 1411: #define HAVE_REFID 1
! 1412: #define HAVE_STRATUM 2
! 1413: #define HAVE_HPOLL 3
! 1414: #define HAVE_PPOLL 4
! 1415: #define HAVE_REACH 5
! 1416: #define HAVE_DELAY 6
! 1417: #define HAVE_OFFSET 7
! 1418: #define HAVE_JITTER 8
! 1419: #define HAVE_DISPERSION 9
! 1420: #define HAVE_REC 10
! 1421: #define HAVE_REFTIME 11
! 1422: #define HAVE_SRCPORT 12
! 1423: #define MAXHAVE 13
! 1424:
! 1425: /*
! 1426: * Decode an incoming data buffer and print a line in the peer list
! 1427: */
! 1428: static int
! 1429: doprintpeers(
! 1430: struct varlist *pvl,
! 1431: int associd,
! 1432: int rstatus,
! 1433: int datalen,
! 1434: const char *data,
! 1435: FILE *fp,
! 1436: int af
! 1437: )
! 1438: {
! 1439: char *name;
! 1440: char *value = NULL;
! 1441: int i;
! 1442: int c;
! 1443:
! 1444: sockaddr_u srcadr;
! 1445: sockaddr_u dstadr;
! 1446: sockaddr_u refidadr;
! 1447: u_long srcport = 0;
! 1448: char *dstadr_refid = "0.0.0.0";
! 1449: char *serverlocal;
! 1450: size_t drlen;
! 1451: u_long stratum = 0;
! 1452: long ppoll = 0;
! 1453: long hpoll = 0;
! 1454: u_long reach = 0;
! 1455: l_fp estoffset;
! 1456: l_fp estdelay;
! 1457: l_fp estjitter;
! 1458: l_fp estdisp;
! 1459: l_fp reftime;
! 1460: l_fp rec;
! 1461: l_fp ts;
! 1462: u_char havevar[MAXHAVE];
! 1463: u_long poll_sec;
! 1464: char type = '?';
! 1465: char refid_string[10];
! 1466: char whenbuf[8], pollbuf[8];
! 1467: char clock_name[LENHOSTNAME];
! 1468:
! 1469: memset((char *)havevar, 0, sizeof(havevar));
! 1470: get_systime(&ts);
! 1471:
! 1472: ZERO_SOCK(&srcadr);
! 1473: ZERO_SOCK(&dstadr);
! 1474:
! 1475: /* Initialize by zeroing out estimate variables */
! 1476: memset((char *)&estoffset, 0, sizeof(l_fp));
! 1477: memset((char *)&estdelay, 0, sizeof(l_fp));
! 1478: memset((char *)&estjitter, 0, sizeof(l_fp));
! 1479: memset((char *)&estdisp, 0, sizeof(l_fp));
! 1480:
! 1481: while (nextvar(&datalen, &data, &name, &value)) {
! 1482: sockaddr_u dum_store;
! 1483:
! 1484: i = findvar(name, peer_var, 1);
! 1485: if (i == 0)
! 1486: continue; /* don't know this one */
! 1487: switch (i) {
! 1488: case CP_SRCADR:
! 1489: if (decodenetnum(value, &srcadr)) {
! 1490: havevar[HAVE_SRCADR] = 1;
! 1491: }
! 1492: break;
! 1493: case CP_DSTADR:
! 1494: if (decodenetnum(value, &dum_store)) {
! 1495: type = decodeaddrtype(&dum_store);
! 1496: havevar[HAVE_DSTADR] = 1;
! 1497: dstadr = dum_store;
! 1498: if (pvl == opeervarlist) {
! 1499: dstadr_refid = trunc_left(stoa(&dstadr), 15);
! 1500: }
! 1501: }
! 1502: break;
! 1503: case CP_REFID:
! 1504: if (pvl == peervarlist) {
! 1505: havevar[HAVE_REFID] = 1;
! 1506: if (*value == '\0') {
! 1507: dstadr_refid = "";
! 1508: } else if (strlen(value) <= 4) {
! 1509: refid_string[0] = '.';
! 1510: (void) strcpy(&refid_string[1], value);
! 1511: i = strlen(refid_string);
! 1512: refid_string[i] = '.';
! 1513: refid_string[i+1] = '\0';
! 1514: dstadr_refid = refid_string;
! 1515: } else if (decodenetnum(value, &refidadr)) {
! 1516: if (SOCK_UNSPEC(&refidadr))
! 1517: dstadr_refid = "0.0.0.0";
! 1518: else if (ISREFCLOCKADR(&refidadr))
! 1519: dstadr_refid =
! 1520: refnumtoa(&refidadr);
! 1521: else
! 1522: dstadr_refid =
! 1523: stoa(&refidadr);
! 1524: } else {
! 1525: havevar[HAVE_REFID] = 0;
! 1526: }
! 1527: }
! 1528: break;
! 1529: case CP_STRATUM:
! 1530: if (decodeuint(value, &stratum))
! 1531: havevar[HAVE_STRATUM] = 1;
! 1532: break;
! 1533: case CP_HPOLL:
! 1534: if (decodeint(value, &hpoll)) {
! 1535: havevar[HAVE_HPOLL] = 1;
! 1536: if (hpoll < 0)
! 1537: hpoll = NTP_MINPOLL;
! 1538: }
! 1539: break;
! 1540: case CP_PPOLL:
! 1541: if (decodeint(value, &ppoll)) {
! 1542: havevar[HAVE_PPOLL] = 1;
! 1543: if (ppoll < 0)
! 1544: ppoll = NTP_MINPOLL;
! 1545: }
! 1546: break;
! 1547: case CP_REACH:
! 1548: if (decodeuint(value, &reach))
! 1549: havevar[HAVE_REACH] = 1;
! 1550: break;
! 1551: case CP_DELAY:
! 1552: if (decodetime(value, &estdelay))
! 1553: havevar[HAVE_DELAY] = 1;
! 1554: break;
! 1555: case CP_OFFSET:
! 1556: if (decodetime(value, &estoffset))
! 1557: havevar[HAVE_OFFSET] = 1;
! 1558: break;
! 1559: case CP_JITTER:
! 1560: if (pvl == peervarlist)
! 1561: if (decodetime(value, &estjitter))
! 1562: havevar[HAVE_JITTER] = 1;
! 1563: break;
! 1564: case CP_DISPERSION:
! 1565: if (decodetime(value, &estdisp))
! 1566: havevar[HAVE_DISPERSION] = 1;
! 1567: break;
! 1568: case CP_REC:
! 1569: if (decodets(value, &rec))
! 1570: havevar[HAVE_REC] = 1;
! 1571: break;
! 1572: case CP_SRCPORT:
! 1573: if (decodeuint(value, &srcport))
! 1574: havevar[HAVE_SRCPORT] = 1;
! 1575: break;
! 1576: case CP_REFTIME:
! 1577: havevar[HAVE_REFTIME] = 1;
! 1578: if (!decodets(value, &reftime))
! 1579: L_CLR(&reftime);
! 1580: break;
! 1581: default:
! 1582: break;
! 1583: }
! 1584: }
! 1585:
! 1586: /*
! 1587: * Check to see if the srcport is NTP's port. If not this probably
! 1588: * isn't a valid peer association.
! 1589: */
! 1590: if (havevar[HAVE_SRCPORT] && srcport != NTP_PORT)
! 1591: return (1);
! 1592:
! 1593: /*
! 1594: * Got everything, format the line
! 1595: */
! 1596: poll_sec = 1<<max(min3(ppoll, hpoll, NTP_MAXPOLL), NTP_MINPOLL);
! 1597: if (pktversion > NTP_OLDVERSION)
! 1598: c = flash3[CTL_PEER_STATVAL(rstatus) & 0x7];
! 1599: else
! 1600: c = flash2[CTL_PEER_STATVAL(rstatus) & 0x3];
! 1601: if (numhosts > 1) {
! 1602: if (peervarlist == pvl && havevar[HAVE_DSTADR]) {
! 1603: serverlocal = nntohost_col(&dstadr,
! 1604: (size_t)min(LIB_BUFLENGTH - 1, maxhostlen),
! 1605: TRUE);
! 1606: } else {
! 1607: if (currenthostisnum)
! 1608: serverlocal = trunc_left(currenthost,
! 1609: maxhostlen);
! 1610: else
! 1611: serverlocal = currenthost;
! 1612: }
! 1613: fprintf(fp, "%-*s ", maxhostlen, serverlocal);
! 1614: }
! 1615: if (AF_UNSPEC == af || AF(&srcadr) == af) {
! 1616: strncpy(clock_name, nntohost(&srcadr), sizeof(clock_name));
! 1617: fprintf(fp, "%c%-15.15s ", c, clock_name);
! 1618: drlen = strlen(dstadr_refid);
! 1619: makeascii(drlen, dstadr_refid, fp);
! 1620: while (drlen++ < 15)
! 1621: fputc(' ', fp);
! 1622: fprintf(fp,
! 1623: " %2ld %c %4.4s %4.4s %3lo %7.7s %8.7s %7.7s\n",
! 1624: stratum, type,
! 1625: prettyinterval(whenbuf, sizeof(whenbuf),
! 1626: when(&ts, &rec, &reftime)),
! 1627: prettyinterval(pollbuf, sizeof(pollbuf),
! 1628: (int)poll_sec),
! 1629: reach, lfptoms(&estdelay, 3),
! 1630: lfptoms(&estoffset, 3),
! 1631: (havevar[HAVE_JITTER])
! 1632: ? lfptoms(&estjitter, 3)
! 1633: : lfptoms(&estdisp, 3));
! 1634: return (1);
! 1635: }
! 1636: else
! 1637: return(1);
! 1638: }
! 1639:
! 1640: #undef HAVE_SRCADR
! 1641: #undef HAVE_DSTADR
! 1642: #undef HAVE_STRATUM
! 1643: #undef HAVE_PPOLL
! 1644: #undef HAVE_HPOLL
! 1645: #undef HAVE_REACH
! 1646: #undef HAVE_ESTDELAY
! 1647: #undef HAVE_ESTOFFSET
! 1648: #undef HAVE_JITTER
! 1649: #undef HAVE_ESTDISP
! 1650: #undef HAVE_REFID
! 1651: #undef HAVE_REC
! 1652: #undef HAVE_SRCPORT
! 1653: #undef HAVE_REFTIME
! 1654: #undef MAXHAVE
! 1655:
! 1656:
! 1657: /*
! 1658: * dogetpeers - given an association ID, read and print the spreadsheet
! 1659: * peer variables.
! 1660: */
! 1661: static int
! 1662: dogetpeers(
! 1663: struct varlist *pvl,
! 1664: associd_t associd,
! 1665: FILE *fp,
! 1666: int af
! 1667: )
! 1668: {
! 1669: const char *datap;
! 1670: int res;
! 1671: int dsize;
! 1672: u_short rstatus;
! 1673:
! 1674: #ifdef notdef
! 1675: res = doquerylist(pvl, CTL_OP_READVAR, associd, 0, &rstatus,
! 1676: &dsize, &datap);
! 1677: #else
! 1678: /*
! 1679: * Damn fuzzballs
! 1680: */
! 1681: res = doquery(CTL_OP_READVAR, associd, 0, 0, NULL, &rstatus,
! 1682: &dsize, &datap);
! 1683: #endif
! 1684:
! 1685: if (res != 0)
! 1686: return 0;
! 1687:
! 1688: if (dsize == 0) {
! 1689: if (numhosts > 1)
! 1690: fprintf(stderr, "server=%s ", currenthost);
! 1691: fprintf(stderr,
! 1692: "***No information returned for association %u\n",
! 1693: associd);
! 1694: return 0;
! 1695: }
! 1696:
! 1697: return doprintpeers(pvl, associd, (int)rstatus, dsize, datap,
! 1698: fp, af);
! 1699: }
! 1700:
! 1701:
! 1702: /*
! 1703: * peers - print a peer spreadsheet
! 1704: */
! 1705: static void
! 1706: dopeers(
! 1707: int showall,
! 1708: FILE *fp,
! 1709: int af
! 1710: )
! 1711: {
! 1712: int i;
! 1713: char fullname[LENHOSTNAME];
! 1714: sockaddr_u netnum;
! 1715: char * name_or_num;
! 1716: size_t sl;
! 1717:
! 1718: if (!dogetassoc(fp))
! 1719: return;
! 1720:
! 1721: for (i = 0; i < numhosts; ++i) {
! 1722: if (getnetnum(chosts[i], &netnum, fullname, af)) {
! 1723: name_or_num = nntohost(&netnum);
! 1724: sl = strlen(name_or_num);
! 1725: maxhostlen = max(maxhostlen, (int)sl);
! 1726: }
! 1727: }
! 1728: if (numhosts > 1)
! 1729: fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen,
! 1730: "server (local)");
! 1731: fprintf(fp,
! 1732: " remote refid st t when poll reach delay offset jitter\n");
! 1733: if (numhosts > 1)
! 1734: for (i = 0; i <= maxhostlen; ++i)
! 1735: fprintf(fp, "=");
! 1736: fprintf(fp,
! 1737: "==============================================================================\n");
! 1738:
! 1739: for (i = 0; i < numassoc; i++) {
! 1740: if (!showall &&
! 1741: !(CTL_PEER_STATVAL(assoc_cache[i].status)
! 1742: & (CTL_PST_CONFIG|CTL_PST_REACH)))
! 1743: continue;
! 1744: if (!dogetpeers(peervarlist, (int)assoc_cache[i].assid, fp, af)) {
! 1745: return;
! 1746: }
! 1747: }
! 1748: return;
! 1749: }
! 1750:
! 1751:
! 1752: /*
! 1753: * peers - print a peer spreadsheet
! 1754: */
! 1755: /*ARGSUSED*/
! 1756: static void
! 1757: peers(
! 1758: struct parse *pcmd,
! 1759: FILE *fp
! 1760: )
! 1761: {
! 1762: int af = 0;
! 1763:
! 1764: if (pcmd->nargs == 1) {
! 1765: if (pcmd->argval->ival == 6)
! 1766: af = AF_INET6;
! 1767: else
! 1768: af = AF_INET;
! 1769: }
! 1770: dopeers(0, fp, af);
! 1771: }
! 1772:
! 1773:
! 1774: /*
! 1775: * lpeers - print a peer spreadsheet including all fuzzball peers
! 1776: */
! 1777: /*ARGSUSED*/
! 1778: static void
! 1779: lpeers(
! 1780: struct parse *pcmd,
! 1781: FILE *fp
! 1782: )
! 1783: {
! 1784: int af = 0;
! 1785:
! 1786: if (pcmd->nargs == 1) {
! 1787: if (pcmd->argval->ival == 6)
! 1788: af = AF_INET6;
! 1789: else
! 1790: af = AF_INET;
! 1791: }
! 1792: dopeers(1, fp, af);
! 1793: }
! 1794:
! 1795:
! 1796: /*
! 1797: * opeers - print a peer spreadsheet
! 1798: */
! 1799: static void
! 1800: doopeers(
! 1801: int showall,
! 1802: FILE *fp,
! 1803: int af
! 1804: )
! 1805: {
! 1806: register int i;
! 1807: char fullname[LENHOSTNAME];
! 1808: sockaddr_u netnum;
! 1809:
! 1810: if (!dogetassoc(fp))
! 1811: return;
! 1812:
! 1813: for (i = 0; i < numhosts; ++i) {
! 1814: if (getnetnum(chosts[i], &netnum, fullname, af))
! 1815: if ((int)strlen(fullname) > maxhostlen)
! 1816: maxhostlen = strlen(fullname);
! 1817: }
! 1818: if (numhosts > 1)
! 1819: (void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "server");
! 1820: (void) fprintf(fp,
! 1821: " remote local st t when poll reach delay offset disp\n");
! 1822: if (numhosts > 1)
! 1823: for (i = 0; i <= maxhostlen; ++i)
! 1824: (void) fprintf(fp, "=");
! 1825: (void) fprintf(fp,
! 1826: "==============================================================================\n");
! 1827:
! 1828: for (i = 0; i < numassoc; i++) {
! 1829: if (!showall &&
! 1830: !(CTL_PEER_STATVAL(assoc_cache[i].status)
! 1831: & (CTL_PST_CONFIG|CTL_PST_REACH)))
! 1832: continue;
! 1833: if (!dogetpeers(opeervarlist, (int)assoc_cache[i].assid, fp, af)) {
! 1834: return;
! 1835: }
! 1836: }
! 1837: return;
! 1838: }
! 1839:
! 1840:
! 1841: /*
! 1842: * opeers - print a peer spreadsheet the old way
! 1843: */
! 1844: /*ARGSUSED*/
! 1845: static void
! 1846: opeers(
! 1847: struct parse *pcmd,
! 1848: FILE *fp
! 1849: )
! 1850: {
! 1851: int af = 0;
! 1852:
! 1853: if (pcmd->nargs == 1) {
! 1854: if (pcmd->argval->ival == 6)
! 1855: af = AF_INET6;
! 1856: else
! 1857: af = AF_INET;
! 1858: }
! 1859: doopeers(0, fp, af);
! 1860: }
! 1861:
! 1862:
! 1863: /*
! 1864: * lopeers - print a peer spreadsheet including all fuzzball peers
! 1865: */
! 1866: /*ARGSUSED*/
! 1867: static void
! 1868: lopeers(
! 1869: struct parse *pcmd,
! 1870: FILE *fp
! 1871: )
! 1872: {
! 1873: int af = 0;
! 1874:
! 1875: if (pcmd->nargs == 1) {
! 1876: if (pcmd->argval->ival == 6)
! 1877: af = AF_INET6;
! 1878: else
! 1879: af = AF_INET;
! 1880: }
! 1881: doopeers(1, fp, af);
! 1882: }
! 1883:
! 1884:
! 1885: /*
! 1886: * config - send a configuration command to a remote host
! 1887: */
! 1888: static void
! 1889: config (
! 1890: struct parse *pcmd,
! 1891: FILE *fp
! 1892: )
! 1893: {
! 1894: char *cfgcmd;
! 1895: u_short rstatus;
! 1896: int rsize;
! 1897: const char *rdata;
! 1898: char *resp;
! 1899: int res;
! 1900: int col;
! 1901: int i;
! 1902:
! 1903: cfgcmd = pcmd->argval[0].string;
! 1904:
! 1905: if (debug > 2)
! 1906: fprintf(stderr,
! 1907: "In Config\n"
! 1908: "Keyword = %s\n"
! 1909: "Command = %s\n", pcmd->keyword, cfgcmd);
! 1910:
! 1911: res = doquery(CTL_OP_CONFIGURE, 0, 1, strlen(cfgcmd), cfgcmd,
! 1912: &rstatus, &rsize, &rdata);
! 1913:
! 1914: if (res != 0)
! 1915: return;
! 1916:
! 1917: if (rsize > 0 && '\n' == rdata[rsize - 1])
! 1918: rsize--;
! 1919:
! 1920: resp = emalloc(rsize + 1);
! 1921: memcpy(resp, rdata, rsize);
! 1922: resp[rsize] = '\0';
! 1923:
! 1924: col = -1;
! 1925: if (1 == sscanf(resp, "column %d syntax error", &col)
! 1926: && col >= 0 && (size_t)col <= strlen(cfgcmd) + 1) {
! 1927: if (interactive) {
! 1928: printf("______"); /* "ntpq> " */
! 1929: printf("________"); /* ":config " */
! 1930: } else
! 1931: printf("%s\n", cfgcmd);
! 1932: for (i = 1; i < col; i++)
! 1933: putchar('_');
! 1934: printf("^\n");
! 1935: }
! 1936: printf("%s\n", resp);
! 1937: free(resp);
! 1938: }
! 1939:
! 1940:
! 1941: /*
! 1942: * config_from_file - remotely configure an ntpd daemon using the
! 1943: * specified configuration file
! 1944: * SK: This function is a kludge at best and is full of bad design
! 1945: * bugs:
! 1946: * 1. ntpq uses UDP, which means that there is no guarantee of in-order,
! 1947: * error-free delivery.
! 1948: * 2. The maximum length of a packet is constrained, and as a result, the
! 1949: * maximum length of a line in a configuration file is constrained.
! 1950: * Longer lines will lead to unpredictable results.
! 1951: * 3. Since this function is sending a line at a time, we can't update
! 1952: * the control key through the configuration file (YUCK!!)
! 1953: */
! 1954: static void
! 1955: config_from_file (
! 1956: struct parse *pcmd,
! 1957: FILE *fp
! 1958: )
! 1959: {
! 1960: u_short rstatus;
! 1961: int rsize;
! 1962: const char *rdata;
! 1963: int res;
! 1964: FILE *config_fd;
! 1965: char config_cmd[MAXLINE];
! 1966: size_t config_len;
! 1967: int i;
! 1968: int retry_limit;
! 1969:
! 1970: if (debug > 2)
! 1971: fprintf(stderr,
! 1972: "In Config\n"
! 1973: "Keyword = %s\n"
! 1974: "Filename = %s\n", pcmd->keyword,
! 1975: pcmd->argval[0].string);
! 1976:
! 1977: config_fd = fopen(pcmd->argval[0].string, "r");
! 1978: if (NULL == config_fd) {
! 1979: printf("ERROR!! Couldn't open file: %s\n",
! 1980: pcmd->argval[0].string);
! 1981: return;
! 1982: }
! 1983:
! 1984: printf("Sending configuration file, one line at a time.\n");
! 1985: i = 0;
! 1986: while (fgets(config_cmd, MAXLINE, config_fd) != NULL) {
! 1987: config_len = strlen(config_cmd);
! 1988: /* ensure even the last line has newline, if possible */
! 1989: if (config_len > 0 &&
! 1990: config_len + 2 < sizeof(config_cmd) &&
! 1991: '\n' != config_cmd[config_len - 1])
! 1992: config_cmd[config_len++] = '\n';
! 1993: ++i;
! 1994: retry_limit = 2;
! 1995: do
! 1996: res = doquery(CTL_OP_CONFIGURE, 0, 1,
! 1997: strlen(config_cmd), config_cmd,
! 1998: &rstatus, &rsize, &rdata);
! 1999: while (res != 0 && retry_limit--);
! 2000: if (res != 0) {
! 2001: printf("Line No: %d query failed: %s", i,
! 2002: config_cmd);
! 2003: printf("Subsequent lines not sent.\n");
! 2004: fclose(config_fd);
! 2005: return;
! 2006: }
! 2007:
! 2008: if (rsize > 0 && '\n' == rdata[rsize - 1])
! 2009: rsize--;
! 2010: if (rsize > 0 && '\r' == rdata[rsize - 1])
! 2011: rsize--;
! 2012: printf("Line No: %d %.*s: %s", i, rsize, rdata,
! 2013: config_cmd);
! 2014: }
! 2015: printf("Done sending file\n");
! 2016: fclose(config_fd);
! 2017: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>