2 * ntpdc_ops.c - subroutines which are called to perform operations by ntpdc
8 #include "ntp_stdlib.h"
13 extern char * chosts[];
14 extern char currenthost[];
19 * Declarations for command handlers in here
21 static int checkassocid P((u_int32));
22 static char * strsave P((char *));
23 static struct varlist *findlistvar P((struct varlist *, char *));
24 static void doaddvlist P((struct varlist *, char *));
25 static void dormvlist P((struct varlist *, char *));
26 static void doclearvlist P((struct varlist *));
27 static void makequerydata P((struct varlist *, int *, char *));
28 static int doquerylist P((struct varlist *, int, int, int, u_short *, int *, char **));
29 static void doprintvlist P((struct varlist *, FILE *));
30 static void addvars P((struct parse *, FILE *));
31 static void rmvars P((struct parse *, FILE *));
32 static void clearvars P((struct parse *, FILE *));
33 static void showvars P((struct parse *, FILE *));
34 static int dolist P((struct varlist *, int, int, int, FILE *));
35 static void readlist P((struct parse *, FILE *));
36 static void writelist P((struct parse *, FILE *));
37 static void readvar P((struct parse *, FILE *));
38 static void writevar P((struct parse *, FILE *));
39 static void clocklist P((struct parse *, FILE *));
40 static void clockvar P((struct parse *, FILE *));
41 static int findassidrange P((u_int32, u_int32, int *, int *));
42 static void mreadlist P((struct parse *, FILE *));
43 static void mreadvar P((struct parse *, FILE *));
44 static int dogetassoc P((FILE *));
45 static void printassoc P((int, FILE *));
46 static void associations P((struct parse *, FILE *));
47 static void lassociations P((struct parse *, FILE *));
48 static void passociations P((struct parse *, FILE *));
49 static void lpassociations P((struct parse *, FILE *));
52 static void radiostatus P((struct parse *, FILE *));
55 static void pstatus P((struct parse *, FILE *));
56 static long when P((l_fp *, l_fp *, l_fp *));
57 static char * prettyinterval P((char *, long));
58 static int doprintpeers P((struct varlist *, int, int, int, char *, FILE *));
59 static int dogetpeers P((struct varlist *, int, FILE *));
60 static void dopeers P((int, FILE *));
61 static void peers P((struct parse *, FILE *));
62 static void lpeers P((struct parse *, FILE *));
63 static void doopeers P((int, FILE *));
64 static void opeers P((struct parse *, FILE *));
65 static void lopeers P((struct parse *, FILE *));
69 * Commands we understand. Ntpdc imports this.
71 struct xcmd opcmds[] = {
72 { "associations", associations, { NO, NO, NO, NO },
74 "print list of association ID's and statuses for the server's peers" },
75 { "passociations", passociations, { NO, NO, NO, NO },
77 "print list of associations returned by last associations command" },
78 { "lassociations", lassociations, { NO, NO, NO, NO },
80 "print list of associations including all client information" },
81 { "lpassociations", lpassociations, { NO, NO, NO, NO },
83 "print last obtained list of associations, including client information" },
84 { "addvars", addvars, { STR, NO, NO, NO },
85 { "name[=value][,...]", "", "", "" },
86 "add variables to the variable list or change their values" },
87 { "rmvars", rmvars, { STR, NO, NO, NO },
88 { "name[,...]", "", "", "" },
89 "remove variables from the variable list" },
90 { "clearvars", clearvars, { NO, NO, NO, NO },
92 "remove all variables from the variable list" },
93 { "showvars", showvars, { NO, NO, NO, NO },
95 "print variables on the variable list" },
96 { "readlist", readlist, { OPT|UINT, NO, NO, NO },
97 { "assocID", "", "", "" },
98 "read the system or peer variables included in the variable list" },
99 { "rl", readlist, { OPT|UINT, NO, NO, NO },
100 { "assocID", "", "", "" },
101 "read the system or peer variables included in the variable list" },
102 { "writelist", writelist, { OPT|UINT, NO, NO, NO },
103 { "assocID", "", "", "" },
104 "write the system or peer variables included in the variable list" },
105 { "readvar", readvar, { OPT|UINT, OPT|STR, NO, NO },
106 { "assocID", "name=value[,...]", "", "" },
107 "read system or peer variables" },
108 { "rv", readvar, { OPT|UINT, OPT|STR, NO, NO },
109 { "assocID", "name=value[,...]", "", "" },
110 "read system or peer variables" },
111 { "writevar", writevar, { UINT, STR, NO, NO },
112 { "assocID", "name=value,[...]", "", "" },
113 "write system or peer variables" },
114 { "mreadlist", mreadlist, { UINT, UINT, NO, NO },
115 { "assocID", "assocID", "", "" },
116 "read the peer variables in the variable list for multiple peers" },
117 { "mrl", mreadlist, { UINT, UINT, NO, NO },
118 { "assocID", "assocID", "", "" },
119 "read the peer variables in the variable list for multiple peers" },
120 { "mreadvar", mreadvar, { UINT, UINT, OPT|STR, NO },
121 { "assocID", "assocID", "name=value[,...]", "" },
122 "read peer variables from multiple peers" },
123 { "mrv", mreadvar, { UINT, UINT, OPT|STR, NO },
124 { "assocID", "assocID", "name=value[,...]", "" },
125 "read peer variables from multiple peers" },
126 { "clocklist", clocklist, { OPT|UINT, NO, NO, NO },
127 { "assocID", "", "", "" },
128 "read the clock variables included in the variable list" },
129 { "cl", clocklist, { OPT|UINT, NO, NO, NO },
130 { "assocID", "", "", "" },
131 "read the clock variables included in the variable list" },
132 { "clockvar", clockvar, { OPT|UINT, OPT|STR, NO, NO },
133 { "assocID", "name=value[,...]", "", "" },
134 "read clock variables" },
135 { "cv", clockvar, { OPT|UINT, OPT|STR, NO, NO },
136 { "assocID", "name=value[,...]", "", "" },
137 "read clock variables" },
138 { "pstatus", pstatus, { UINT, NO, NO, NO },
139 { "assocID", "", "", "" },
140 "print status information returned for a peer" },
141 { "peers", peers, { NO, NO, NO, NO },
143 "obtain and print a list of the server's peers" },
144 { "lpeers", lpeers, { NO, NO, NO, NO },
146 "obtain and print a list of all peers and clients" },
147 { "opeers", opeers, { NO, NO, NO, NO },
149 "print peer list the old way, with dstadr shown rather than refid" },
150 { "lopeers", lopeers, { NO, NO, NO, NO },
152 "obtain and print a list of all peers and clients showing dstadr" },
153 { 0, 0, { NO, NO, NO, NO },
154 { "", "", "", "" }, "" }
159 * Variable list data space
161 #define MAXLIST 64 /* maximum number of variables in list */
162 #define LENHOSTNAME 256 /* host name is 256 characters long */
164 * Old CTL_PST defines for version 2.
166 #define OLD_CTL_PST_CONFIG 0x80
167 #define OLD_CTL_PST_AUTHENABLE 0x40
168 #define OLD_CTL_PST_AUTHENTIC 0x20
169 #define OLD_CTL_PST_REACH 0x10
170 #define OLD_CTL_PST_SANE 0x08
171 #define OLD_CTL_PST_DISP 0x04
172 #define OLD_CTL_PST_SEL_REJECT 0
173 #define OLD_CTL_PST_SEL_SELCAND 1
174 #define OLD_CTL_PST_SEL_SYNCCAND 2
175 #define OLD_CTL_PST_SEL_SYSPEER 3
178 char flash2[] = " .+* "; /* flash decode for version 2 */
179 char flash3[] = " x.-+#*o"; /* flash decode for peer status version 3 */
184 } varlist[MAXLIST] = { { 0, 0 } };
187 * Imported from ntpq.c
189 extern int showhostnames;
191 extern struct servent *server_entry;
192 extern struct association assoc_cache[];
194 extern u_char pktversion;
195 extern struct ctl_var peer_var[];
198 * For quick string comparisons
200 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
204 * checkassocid - return the association ID, checking to see if it is valid
211 if (value == 0 || value >= 65536) {
212 (void) fprintf(stderr, "***Invalid association ID specified\n");
220 * strsave - save a string
221 * XXX - should be in libntp.a
231 len = strlen(str) + 1;
232 if ((cp = (char *)malloc(len)) == NULL) {
233 (void) fprintf(stderr, "Malloc failed!!\n");
237 memmove(cp, str, len);
243 * findlistvar - look for the named variable in a list and return if found
245 static struct varlist *
247 struct varlist *list,
251 register struct varlist *vl;
253 for (vl = list; vl < list + MAXLIST && vl->name != 0; vl++)
254 if (STREQ(name, vl->name))
256 if (vl < list + MAXLIST)
258 return (struct varlist *)0;
263 * doaddvlist - add variable(s) to the variable list
267 struct varlist *vlist,
271 register struct varlist *vl;
277 while (nextvar(&len, &vars, &name, &value)) {
278 vl = findlistvar(vlist, name);
280 (void) fprintf(stderr, "Variable list full\n");
285 vl->name = strsave(name);
286 } else if (vl->value != 0) {
292 vl->value = strsave(value);
298 * dormvlist - remove variable(s) from the variable list
302 struct varlist *vlist,
306 register struct varlist *vl;
312 while (nextvar(&len, &vars, &name, &value)) {
313 vl = findlistvar(vlist, name);
314 if (vl == 0 || vl->name == 0) {
315 (void) fprintf(stderr, "Variable `%s' not found\n",
318 free((void *)vl->name);
321 for ( ; (vl+1) < (varlist+MAXLIST)
322 && (vl+1)->name != 0; vl++) {
323 vl->name = (vl+1)->name;
324 vl->value = (vl+1)->value;
326 vl->name = vl->value = 0;
333 * doclearvlist - clear a variable list
337 struct varlist *vlist
340 register struct varlist *vl;
342 for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
343 free((void *)vl->name);
345 if (vl->value != 0) {
354 * makequerydata - form a data buffer to be included with a query
358 struct varlist *vlist,
363 register struct varlist *vl;
364 register char *cp, *cpend;
365 register int namelen, valuelen;
366 register int totallen;
369 cpend = data + *datalen;
371 for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
372 namelen = strlen(vl->name);
376 valuelen = strlen(vl->value);
377 totallen = namelen + valuelen + (valuelen != 0) + (cp != data);
378 if (cp + totallen > cpend)
383 memmove(cp, vl->name, (unsigned)namelen);
387 memmove(cp, vl->value, (unsigned)valuelen);
391 *datalen = cp - data;
396 * doquerylist - send a message including variables in a list
400 struct varlist *vlist,
409 char data[CTL_MAX_DATA_LEN];
412 datalen = sizeof(data);
413 makequerydata(vlist, &datalen, data);
415 return doquery(op, associd, auth, datalen, data, rstatus,
421 * doprintvlist - print the variables on a list
425 struct varlist *vlist,
429 register struct varlist *vl;
431 if (vlist->name == 0) {
432 (void) fprintf(fp, "No variables on list\n");
434 for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
435 if (vl->value == 0) {
436 (void) fprintf(fp, "%s\n", vl->name);
438 (void) fprintf(fp, "%s=%s\n",
439 vl->name, vl->value);
447 * addvars - add variables to the variable list
456 doaddvlist(varlist, pcmd->argval[0].string);
461 * rmvars - remove variables from the variable list
470 dormvlist(varlist, pcmd->argval[0].string);
475 * clearvars - clear the variable list
484 doclearvlist(varlist);
489 * showvars - show variables on the variable list
498 doprintvlist(varlist, fp);
503 * dolist - send a request with the given list of variables
507 struct varlist *vlist,
519 res = doquerylist(vlist, op, associd, 0, &rstatus, &dsize, &datap);
526 (void) fprintf(fp, "No system%s variables returned\n",
527 (type == TYPE_CLOCK) ? " clock" : "");
530 "No information returned for%s association %u\n",
531 (type == TYPE_CLOCK) ? " clock" : "", associd);
535 printvars(dsize, datap, (int)rstatus, type, fp);
541 * readlist - send a read variables request with the variables on the list
551 if (pcmd->nargs == 0) {
554 /* HMS: I think we want the u_int32 target here, not the u_long */
555 if (pcmd->argval[0].uval == 0)
557 else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
561 (void) dolist(varlist, associd, CTL_OP_READVAR,
562 (associd == 0) ? TYPE_SYS : TYPE_PEER, fp);
567 * writelist - send a write variables request with the variables on the list
581 if (pcmd->nargs == 0) {
584 /* HMS: Do we really want uval here? */
585 if (pcmd->argval[0].uval == 0)
587 else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
591 res = doquerylist(varlist, CTL_OP_WRITEVAR, associd, 1, &rstatus,
598 (void) fprintf(fp, "done! (no data returned)\n");
600 printvars(dsize, datap, (int)rstatus,
601 (associd != 0) ? TYPE_PEER : TYPE_SYS, fp);
607 * readvar - send a read variables request with the specified variables
616 struct varlist tmplist[MAXLIST];
619 if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
621 else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
624 memset((char *)tmplist, 0, sizeof(tmplist));
625 if (pcmd->nargs >= 2)
626 doaddvlist(tmplist, pcmd->argval[1].string);
628 (void) dolist(tmplist, associd, CTL_OP_READVAR,
629 (associd == 0) ? TYPE_SYS : TYPE_PEER, fp);
631 doclearvlist(tmplist);
636 * writevar - send a write variables request with the specified variables
649 struct varlist tmplist[MAXLIST];
652 if (pcmd->argval[0].uval == 0)
654 else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
657 memset((char *)tmplist, 0, sizeof(tmplist));
658 doaddvlist(tmplist, pcmd->argval[1].string);
660 res = doquerylist(tmplist, CTL_OP_WRITEVAR, associd, 1, &rstatus,
663 doclearvlist(tmplist);
669 (void) fprintf(fp, "done! (no data returned)\n");
671 printvars(dsize, datap, (int)rstatus,
672 (associd != 0) ? TYPE_PEER : TYPE_SYS, fp);
678 * clocklist - send a clock variables request with the variables on the list
689 if (pcmd->nargs == 0) {
692 if (pcmd->argval[0].uval == 0)
694 else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
698 (void) dolist(varlist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
703 * clockvar - send a clock variables request with the specified variables
712 struct varlist tmplist[MAXLIST];
715 if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
717 else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
720 memset((char *)tmplist, 0, sizeof(tmplist));
721 if (pcmd->nargs >= 2)
722 doaddvlist(tmplist, pcmd->argval[1].string);
724 (void) dolist(tmplist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
726 doclearvlist(tmplist);
731 * findassidrange - verify a range of association ID's
744 if (assid1 == 0 || assid1 > 65535) {
745 (void) fprintf(stderr,
746 "***Invalid association ID %lu specified\n", (u_long)assid1);
750 if (assid2 == 0 || assid2 > 65535) {
751 (void) fprintf(stderr,
752 "***Invalid association ID %lu specified\n", (u_long)assid2);
757 for (i = 0; i < numassoc; i++) {
758 if (assoc_cache[i].assid == assid1) {
763 if (assoc_cache[i].assid == assid2) {
770 if (f == -1 || t == -1) {
771 (void) fprintf(stderr,
772 "***Association ID %lu not found in list\n",
773 (f == -1) ? (u_long)assid1 : (u_long)assid2);
790 * mreadlist - send a read variables request for multiple associations
803 if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
807 for (i = from; i <= to; i++) {
809 (void) fprintf(fp, "\n");
810 if (!dolist(varlist, (int)assoc_cache[i].assid,
811 CTL_OP_READVAR, TYPE_PEER, fp))
819 * mreadvar - send a read variables request for multiple associations
830 struct varlist tmplist[MAXLIST];
833 if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
837 memset((char *)tmplist, 0, sizeof(tmplist));
838 if (pcmd->nargs >= 3)
839 doaddvlist(tmplist, pcmd->argval[2].string);
841 for (i = from; i <= to; i++) {
843 (void) fprintf(fp, "\n");
844 if (!dolist(varlist, (int)assoc_cache[i].assid,
845 CTL_OP_READVAR, TYPE_PEER, fp))
848 doclearvlist(tmplist);
854 * dogetassoc - query the host for its list of associations
866 res = doquery(CTL_OP_READSTAT, 0, 0, 0, (char *)0, &rstatus,
867 &dsize, (char **)&datap);
873 (void) fprintf(fp, "No association ID's returned\n");
878 (void) fprintf(stderr,
879 "***Server returned %d octets, should be multiple of 4\n",
886 assoc_cache[numassoc].assid = ntohs(*datap);
888 assoc_cache[numassoc].status = ntohs(*datap);
890 if (++numassoc >= MAXASSOC)
892 dsize -= sizeof(u_short) + sizeof(u_short);
900 * printassoc - print the current list of associations
916 const char *condition = "";
917 const char *last_event;
922 (void) fprintf(fp, "No association ID's in list\n");
930 "ind assID status conf reach auth condition last_event cnt\n");
932 "===========================================================\n");
933 for (i = 0; i < numassoc; i++) {
934 statval = CTL_PEER_STATVAL(assoc_cache[i].status);
935 if (!showall && !(statval & (CTL_PST_CONFIG|CTL_PST_REACH)))
937 event = CTL_PEER_EVENT(assoc_cache[i].status);
938 event_count = CTL_PEER_NEVNT(assoc_cache[i].status);
939 if (statval & CTL_PST_CONFIG)
943 if (statval & CTL_PST_REACH || 1) {
945 if (statval & CTL_PST_AUTHENABLE) {
946 if (statval & CTL_PST_AUTHENTIC)
953 if (pktversion > NTP_OLDVERSION)
954 switch (statval & 0x7) {
955 case CTL_PST_SEL_REJECT:
956 condition = "reject";
958 case CTL_PST_SEL_SANE:
959 condition = "falsetick";
961 case CTL_PST_SEL_CORRECT:
962 condition = "excess";
964 case CTL_PST_SEL_SELCAND:
965 condition = "outlyer";
967 case CTL_PST_SEL_SYNCCAND:
968 condition = "candidat";
970 case CTL_PST_SEL_DISTSYSPEER:
971 condition = "selected";
973 case CTL_PST_SEL_SYSPEER:
974 condition = "sys.peer";
976 case CTL_PST_SEL_PPS:
977 condition = "pps.peer";
981 switch (statval & 0x3) {
982 case OLD_CTL_PST_SEL_REJECT:
983 if (!(statval & OLD_CTL_PST_SANE))
984 condition = "insane";
985 else if (!(statval & OLD_CTL_PST_DISP))
986 condition = "hi_disp";
990 case OLD_CTL_PST_SEL_SELCAND:
991 condition = "sel_cand";
993 case OLD_CTL_PST_SEL_SYNCCAND:
994 condition = "sync_cand";
996 case OLD_CTL_PST_SEL_SYSPEER:
997 condition = "sys_peer";
1003 auth = condition = "";
1006 switch (PEER_EVENT|event) {
1007 case EVNT_PEERIPERR:
1008 last_event = "IP error";
1011 last_event = "auth fail";
1014 last_event = "lost reach";
1017 last_event = "reachable";
1019 case EVNT_PEERCLOCK:
1020 last_event = "clock expt";
1023 case EVNT_PEERSTRAT:
1024 last_event = "stratum chg";
1032 if (event_count != 0)
1033 cnt = uinttoa(event_count);
1037 "%3d %5u %04x %3.3s %4s %4.4s %9.9s %11s %2s",
1038 i+1, assoc_cache[i].assid, assoc_cache[i].status,
1039 conf, reach, auth, condition, last_event, cnt);
1040 bp = &buf[strlen(buf)];
1041 while (bp > buf && *(bp-1) == ' ')
1043 (void) fprintf(fp, "%s\n", buf);
1050 * associations - get, record and print a list of associations
1065 * lassociations - get, record and print a long list of associations
1080 * passociations - print the association list
1094 * lpassociations - print the long association list
1109 * radiostatus - print the radio status returned by the server
1123 res = doquery(CTL_OP_READCLOCK, 0, 0, 0, (char *)0, &rstatus,
1130 (void) fprintf(fp, "No radio status string returned\n");
1134 asciize(dsize, datap, fp);
1139 * pstatus - print peer status returned by the server
1154 if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
1157 res = doquery(CTL_OP_READSTAT, associd, 0, 0, (char *)0, &rstatus,
1165 "No information returned for association %u\n",
1170 printvars(dsize, datap, (int)rstatus, TYPE_PEER, fp);
1175 * when - print how long its been since his last packet arrived
1188 else if (reftime->l_ui != 0)
1193 return (ts->l_ui - lasttime->l_ui);
1198 * Pretty-print an interval into the given buffer, in a human-friendly format.
1213 (void) sprintf(buf, "%ld", (long int)diff);
1217 diff = (diff + 29) / 60;
1219 (void) sprintf(buf, "%ldm", (long int)diff);
1223 diff = (diff + 29) / 60;
1225 (void) sprintf(buf, "%ldh", (long int)diff);
1229 diff = (diff + 11) / 24;
1230 (void) sprintf(buf, "%ldd", (long int)diff);
1236 * A list of variables required by the peers command
1238 struct varlist opeervarlist[] = {
1239 { "srcadr", 0 }, /* 0 */
1240 { "dstadr", 0 }, /* 1 */
1241 { "stratum", 0 }, /* 2 */
1242 { "hpoll", 0 }, /* 3 */
1243 { "ppoll", 0 }, /* 4 */
1244 { "reach", 0 }, /* 5 */
1245 { "delay", 0 }, /* 6 */
1246 { "offset", 0 }, /* 7 */
1247 { "jitter", 0 }, /* 8 */
1248 { "dispersion", 0 }, /* 9 */
1249 { "rec", 0 }, /* 10 */
1250 { "reftime", 0 }, /* 11 */
1251 { "srcport", 0 }, /* 12 */
1255 struct varlist peervarlist[] = {
1256 { "srcadr", 0 }, /* 0 */
1257 { "refid", 0 }, /* 1 */
1258 { "stratum", 0 }, /* 2 */
1259 { "hpoll", 0 }, /* 3 */
1260 { "ppoll", 0 }, /* 4 */
1261 { "reach", 0 }, /* 5 */
1262 { "delay", 0 }, /* 6 */
1263 { "offset", 0 }, /* 7 */
1264 { "jitter", 0 }, /* 8 */
1265 { "dispersion", 0 }, /* 9 */
1266 { "rec", 0 }, /* 10 */
1267 { "reftime", 0 }, /* 11 */
1268 { "srcport", 0 }, /* 12 */
1272 #define HAVE_SRCADR 0
1273 #define HAVE_DSTADR 1
1274 #define HAVE_REFID 1
1275 #define HAVE_STRATUM 2
1276 #define HAVE_HPOLL 3
1277 #define HAVE_PPOLL 4
1278 #define HAVE_REACH 5
1279 #define HAVE_DELAY 6
1280 #define HAVE_OFFSET 7
1281 #define HAVE_JITTER 8
1282 #define HAVE_DISPERSION 9
1284 #define HAVE_REFTIME 11
1285 #define HAVE_SRCPORT 12
1289 * Decode an incoming data buffer and print a line in the peer list
1293 struct varlist *pvl,
1309 const char *dstadr_refid = "0.0.0.0";
1321 u_char havevar[MAXHAVE];
1324 char refid_string[10];
1325 char whenbuf[8], pollbuf[8];
1327 memset((char *)havevar, 0, sizeof(havevar));
1330 while (nextvar(&datalen, &data, &name, &value)) {
1333 i = findvar(name, peer_var);
1335 continue; /* don't know this one */
1338 if (decodenetnum(value, &srcadr))
1339 havevar[HAVE_SRCADR] = 1;
1342 if (decodenetnum(value, &dummy)) {
1343 dummy = ntohl(dummy);
1344 type = ((dummy&0xf0000000)==0xe0000000) ? 'm' :
1345 ((dummy&0x000000ff)==0x000000ff) ? 'b' :
1346 ((dummy&0xffffffff)==0x7f000001) ? 'l' :
1347 ((dummy&0xffffffe0)==0x00000000) ? '-' :
1350 if (pvl == opeervarlist) {
1351 if (decodenetnum(value, &dstadr)) {
1352 havevar[HAVE_DSTADR] = 1;
1353 dstadr_refid = numtoa(dstadr);
1358 if (pvl == peervarlist) {
1359 havevar[HAVE_REFID] = 1;
1360 if (*value == '\0') {
1361 dstadr_refid = "0.0.0.0";
1362 } else if (decodenetnum(value, &dstadr)) {
1364 dstadr_refid = "0.0.0.0";
1366 dstadr_refid = nntohost(dstadr);
1367 } else if ((int)strlen(value) <= 4) {
1368 refid_string[0] = '.';
1369 (void) strcpy(&refid_string[1], value);
1370 i = strlen(refid_string);
1371 refid_string[i] = '.';
1372 refid_string[i+1] = '\0';
1373 dstadr_refid = refid_string;
1375 havevar[HAVE_REFID] = 0;
1380 if (decodeuint(value, &stratum))
1381 havevar[HAVE_STRATUM] = 1;
1384 if (decodeint(value, &hpoll)) {
1385 havevar[HAVE_HPOLL] = 1;
1387 hpoll = NTP_MINPOLL;
1391 if (decodeint(value, &ppoll)) {
1392 havevar[HAVE_PPOLL] = 1;
1394 ppoll = NTP_MINPOLL;
1398 if (decodeuint(value, &reach))
1399 havevar[HAVE_REACH] = 1;
1402 if (decodetime(value, &estdelay))
1403 havevar[HAVE_DELAY] = 1;
1406 if (decodetime(value, &estoffset))
1407 havevar[HAVE_OFFSET] = 1;
1410 if (decodetime(value, &estjitter))
1411 havevar[HAVE_JITTER] = 1;
1414 if (decodetime(value, &estdisp))
1415 havevar[HAVE_DISPERSION] = 1;
1418 if (decodets(value, &rec))
1419 havevar[HAVE_REC] = 1;
1422 if (decodeuint(value, &srcport))
1423 havevar[HAVE_SRCPORT] = 1;
1426 havevar[HAVE_REFTIME] = 1;
1427 if (!decodets(value, &reftime))
1436 * Check to see if the srcport is NTP's port. If not this probably
1437 * isn't a valid peer association.
1439 if (havevar[HAVE_SRCPORT] && srcport != NTP_PORT)
1443 * Got everything, format the line
1445 poll_sec = 1<<max(min3(ppoll, hpoll, NTP_MAXPOLL), NTP_MINPOLL);
1446 if (pktversion > NTP_OLDVERSION)
1447 c = flash3[CTL_PEER_STATVAL(rstatus) & 0x7];
1449 c = flash2[CTL_PEER_STATVAL(rstatus) & 0x3];
1451 (void) fprintf(fp, "%-*s ", maxhostlen, currenthost);
1453 "%c%-15.15s %-15.15s %2ld %c %4.4s %4.4s %3lo %7.7s %8.7s %7.7s\n",
1454 c, nntohost(srcadr), dstadr_refid, stratum, type,
1455 prettyinterval(whenbuf, when(&ts, &rec, &reftime)),
1456 prettyinterval(pollbuf, (int)poll_sec), reach,
1457 lfptoms(&estdelay, 3), lfptoms(&estoffset, 3),
1458 havevar[HAVE_JITTER] ? lfptoms(&estjitter, 3) :
1459 lfptoms(&estdisp, 3));
1469 #undef HAVE_ESTDELAY
1470 #undef HAVE_ESTOFFSET
1481 * dogetpeers - given an association ID, read and print the spreadsheet
1486 struct varlist *pvl,
1497 res = doquerylist(pvl, CTL_OP_READVAR, associd, 0, &rstatus,
1503 res = doquery(CTL_OP_READVAR, associd, 0, 0, (char *)0, &rstatus,
1511 (void) fprintf(stderr,
1512 "***No information returned for association %d\n",
1518 return doprintpeers(pvl, associd, (int)rstatus, dsize, datap, fp);
1523 * peers - print a peer spreadsheet
1532 char fullname[LENHOSTNAME];
1535 if (!dogetassoc(fp))
1540 for (i = 0; i < numhosts; ++i)
1541 { if(getnetnum(chosts[i],&netnum,fullname))
1542 if ((int)strlen(fullname) > maxhostlen)
1543 maxhostlen = strlen(fullname);
1545 (void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "host");
1548 " remote refid st t when poll reach delay offset jitter\n");
1550 for (i = 0; i <= maxhostlen; ++i)
1551 (void) fprintf(fp, "=");
1553 "==============================================================================\n");
1555 for (i = 0; i < numassoc; i++) {
1557 !(CTL_PEER_STATVAL(assoc_cache[i].status)
1558 & (CTL_PST_CONFIG|CTL_PST_REACH)))
1560 if (!dogetpeers(peervarlist, (int)assoc_cache[i].assid, fp)) {
1569 * peers - print a peer spreadsheet
1583 * lpeers - print a peer spreadsheet including all fuzzball peers
1597 * opeers - print a peer spreadsheet
1607 if (!dogetassoc(fp))
1611 " remote local st t when poll reach delay offset disp\n");
1613 " (s) (s) (ms) (ms) (ms)\n");
1615 "==============================================================================\n");
1617 for (i = 0; i < numassoc; i++) {
1619 !(CTL_PEER_STATVAL(assoc_cache[i].status)
1620 & (CTL_PST_CONFIG|CTL_PST_REACH)))
1622 if (!dogetpeers(opeervarlist, (int)assoc_cache[i].assid, fp)) {
1631 * opeers - print a peer spreadsheet the old way
1645 * lopeers - print a peer spreadsheet including all fuzzball peers