2 * ntpq_ops.c - subroutines which are called to perform operations by ntpq
11 #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 *, int));
59 static int dogetpeers P((struct varlist *, int, FILE *, int));
60 static void dopeers P((int, FILE *, int));
61 static void peers P((struct parse *, FILE *));
62 static void lpeers P((struct parse *, FILE *));
63 static void doopeers P((int, FILE *, int));
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, { NTP_STR, NO, NO, NO },
85 { "name[=value][,...]", "", "", "" },
86 "add variables to the variable list or change their values" },
87 { "rmvars", rmvars, { NTP_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|NTP_UINT, NO, NO, NO },
97 { "assocID", "", "", "" },
98 "read the system or peer variables included in the variable list" },
99 { "rl", readlist, { OPT|NTP_UINT, NO, NO, NO },
100 { "assocID", "", "", "" },
101 "read the system or peer variables included in the variable list" },
102 { "writelist", writelist, { OPT|NTP_UINT, NO, NO, NO },
103 { "assocID", "", "", "" },
104 "write the system or peer variables included in the variable list" },
105 { "readvar", readvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
106 { "assocID", "name=value[,...]", "", "" },
107 "read system or peer variables" },
108 { "rv", readvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
109 { "assocID", "name=value[,...]", "", "" },
110 "read system or peer variables" },
111 { "writevar", writevar, { NTP_UINT, NTP_STR, NO, NO },
112 { "assocID", "name=value,[...]", "", "" },
113 "write system or peer variables" },
114 { "mreadlist", mreadlist, { NTP_UINT, NTP_UINT, NO, NO },
115 { "assocID", "assocID", "", "" },
116 "read the peer variables in the variable list for multiple peers" },
117 { "mrl", mreadlist, { NTP_UINT, NTP_UINT, NO, NO },
118 { "assocID", "assocID", "", "" },
119 "read the peer variables in the variable list for multiple peers" },
120 { "mreadvar", mreadvar, { NTP_UINT, NTP_UINT, OPT|NTP_STR, NO },
121 { "assocID", "assocID", "name=value[,...]", "" },
122 "read peer variables from multiple peers" },
123 { "mrv", mreadvar, { NTP_UINT, NTP_UINT, OPT|NTP_STR, NO },
124 { "assocID", "assocID", "name=value[,...]", "" },
125 "read peer variables from multiple peers" },
126 { "clocklist", clocklist, { OPT|NTP_UINT, NO, NO, NO },
127 { "assocID", "", "", "" },
128 "read the clock variables included in the variable list" },
129 { "cl", clocklist, { OPT|NTP_UINT, NO, NO, NO },
130 { "assocID", "", "", "" },
131 "read the clock variables included in the variable list" },
132 { "clockvar", clockvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
133 { "assocID", "name=value[,...]", "", "" },
134 "read clock variables" },
135 { "cv", clockvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
136 { "assocID", "name=value[,...]", "", "" },
137 "read clock variables" },
138 { "pstatus", pstatus, { NTP_UINT, NO, NO, NO },
139 { "assocID", "", "", "" },
140 "print status information returned for a peer" },
141 { "peers", peers, { OPT|IP_VERSION, NO, NO, NO },
142 { "-4|-6", "", "", "" },
143 "obtain and print a list of the server's peers [IP version]" },
144 { "lpeers", lpeers, { OPT|IP_VERSION, NO, NO, NO },
145 { "-4|-6", "", "", "" },
146 "obtain and print a list of all peers and clients [IP version]" },
147 { "opeers", opeers, { OPT|IP_VERSION, NO, NO, NO },
148 { "-4|-6", "", "", "" },
149 "print peer list the old way, with dstadr shown rather than refid [IP version]" },
150 { "lopeers", lopeers, { OPT|IP_VERSION, NO, NO, NO },
151 { "-4|-6", "", "", "" },
152 "obtain and print a list of all peers and clients showing dstadr [IP version]" },
153 { 0, 0, { NO, NO, NO, NO },
154 { "-4|-6", "", "", "" }, "" }
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);
525 (void) fprintf(fp, "server=%s ", currenthost);
528 (void) fprintf(fp, "No system%s variables returned\n",
529 (type == TYPE_CLOCK) ? " clock" : "");
532 "No information returned for%s association %u\n",
533 (type == TYPE_CLOCK) ? " clock" : "", associd);
537 (void) fprintf(fp,"assID=%d ",associd);
538 printvars(dsize, datap, (int)rstatus, type, fp);
544 * readlist - send a read variables request with the variables on the list
554 if (pcmd->nargs == 0) {
557 /* HMS: I think we want the u_int32 target here, not the u_long */
558 if (pcmd->argval[0].uval == 0)
560 else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
564 (void) dolist(varlist, associd, CTL_OP_READVAR,
565 (associd == 0) ? TYPE_SYS : TYPE_PEER, fp);
570 * writelist - send a write variables request with the variables on the list
584 if (pcmd->nargs == 0) {
587 /* HMS: Do we really want uval here? */
588 if (pcmd->argval[0].uval == 0)
590 else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
594 res = doquerylist(varlist, CTL_OP_WRITEVAR, associd, 1, &rstatus,
601 (void) fprintf(fp, "server=%s ", currenthost);
603 (void) fprintf(fp, "done! (no data returned)\n");
605 (void) fprintf(fp,"assID=%d ",associd);
606 printvars(dsize, datap, (int)rstatus,
607 (associd != 0) ? TYPE_PEER : TYPE_SYS, fp);
614 * readvar - send a read variables request with the specified variables
623 struct varlist tmplist[MAXLIST];
626 if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
628 else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
631 memset((char *)tmplist, 0, sizeof(tmplist));
632 if (pcmd->nargs >= 2)
633 doaddvlist(tmplist, pcmd->argval[1].string);
635 (void) dolist(tmplist, associd, CTL_OP_READVAR,
636 (associd == 0) ? TYPE_SYS : TYPE_PEER, fp);
638 doclearvlist(tmplist);
643 * writevar - send a write variables request with the specified variables
656 struct varlist tmplist[MAXLIST];
659 if (pcmd->argval[0].uval == 0)
661 else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
664 memset((char *)tmplist, 0, sizeof(tmplist));
665 doaddvlist(tmplist, pcmd->argval[1].string);
667 res = doquerylist(tmplist, CTL_OP_WRITEVAR, associd, 1, &rstatus,
670 doclearvlist(tmplist);
676 (void) fprintf(fp, "server=%s ", currenthost);
678 (void) fprintf(fp, "done! (no data returned)\n");
680 (void) fprintf(fp,"assID=%d ",associd);
681 printvars(dsize, datap, (int)rstatus,
682 (associd != 0) ? TYPE_PEER : TYPE_SYS, fp);
689 * clocklist - send a clock variables request with the variables on the list
700 if (pcmd->nargs == 0) {
703 if (pcmd->argval[0].uval == 0)
705 else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
709 (void) dolist(varlist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
714 * clockvar - send a clock variables request with the specified variables
723 struct varlist tmplist[MAXLIST];
726 if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
728 else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
731 memset((char *)tmplist, 0, sizeof(tmplist));
732 if (pcmd->nargs >= 2)
733 doaddvlist(tmplist, pcmd->argval[1].string);
735 (void) dolist(tmplist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
737 doclearvlist(tmplist);
742 * findassidrange - verify a range of association ID's
755 if (assid1 == 0 || assid1 > 65535) {
756 (void) fprintf(stderr,
757 "***Invalid association ID %lu specified\n", (u_long)assid1);
761 if (assid2 == 0 || assid2 > 65535) {
762 (void) fprintf(stderr,
763 "***Invalid association ID %lu specified\n", (u_long)assid2);
768 for (i = 0; i < numassoc; i++) {
769 if (assoc_cache[i].assid == assid1) {
774 if (assoc_cache[i].assid == assid2) {
781 if (f == -1 || t == -1) {
782 (void) fprintf(stderr,
783 "***Association ID %lu not found in list\n",
784 (f == -1) ? (u_long)assid1 : (u_long)assid2);
801 * mreadlist - send a read variables request for multiple associations
814 if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
818 for (i = from; i <= to; i++) {
820 (void) fprintf(fp, "\n");
821 if (!dolist(varlist, (int)assoc_cache[i].assid,
822 CTL_OP_READVAR, TYPE_PEER, fp))
830 * mreadvar - send a read variables request for multiple associations
841 struct varlist tmplist[MAXLIST];
844 if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
848 memset((char *)tmplist, 0, sizeof(tmplist));
849 if (pcmd->nargs >= 3)
850 doaddvlist(tmplist, pcmd->argval[2].string);
852 for (i = from; i <= to; i++) {
854 (void) fprintf(fp, "\n");
855 if (!dolist(varlist, (int)assoc_cache[i].assid,
856 CTL_OP_READVAR, TYPE_PEER, fp))
859 doclearvlist(tmplist);
865 * dogetassoc - query the host for its list of associations
877 res = doquery(CTL_OP_READSTAT, 0, 0, 0, (char *)0, &rstatus,
885 (void) fprintf(fp, "server=%s ", currenthost);
886 (void) fprintf(fp, "No association ID's returned\n");
892 (void) fprintf(stderr, "server=%s ", currenthost);
893 (void) fprintf(stderr,
894 "***Server returned %d octets, should be multiple of 4\n",
901 assoc_cache[numassoc].assid = ntohs(*((u_short *)datap));
902 datap += sizeof(u_short);
903 assoc_cache[numassoc].status = ntohs(*((u_short *)datap));
904 datap += sizeof(u_short);
905 if (++numassoc >= MAXASSOC)
907 dsize -= sizeof(u_short) + sizeof(u_short);
915 * printassoc - print the current list of associations
931 const char *condition = "";
932 const char *last_event;
937 (void) fprintf(fp, "No association ID's in list\n");
945 "\nind assID status conf reach auth condition last_event cnt\n");
947 "===========================================================\n");
948 for (i = 0; i < numassoc; i++) {
949 statval = (u_char) CTL_PEER_STATVAL(assoc_cache[i].status);
950 if (!showall && !(statval & (CTL_PST_CONFIG|CTL_PST_REACH)))
952 event = CTL_PEER_EVENT(assoc_cache[i].status);
953 event_count = CTL_PEER_NEVNT(assoc_cache[i].status);
954 if (statval & CTL_PST_CONFIG)
958 if (statval & CTL_PST_REACH || 1) {
960 if (statval & CTL_PST_AUTHENABLE) {
961 if (statval & CTL_PST_AUTHENTIC)
968 if (pktversion > NTP_OLDVERSION)
969 switch (statval & 0x7) {
970 case CTL_PST_SEL_REJECT:
971 condition = "reject";
973 case CTL_PST_SEL_SANE:
974 condition = "falsetick";
976 case CTL_PST_SEL_CORRECT:
977 condition = "excess";
979 case CTL_PST_SEL_SELCAND:
980 condition = "outlyer";
982 case CTL_PST_SEL_SYNCCAND:
983 condition = "candidat";
985 case CTL_PST_SEL_DISTSYSPEER:
986 condition = "selected";
988 case CTL_PST_SEL_SYSPEER:
989 condition = "sys.peer";
991 case CTL_PST_SEL_PPS:
992 condition = "pps.peer";
996 switch (statval & 0x3) {
997 case OLD_CTL_PST_SEL_REJECT:
998 if (!(statval & OLD_CTL_PST_SANE))
999 condition = "insane";
1000 else if (!(statval & OLD_CTL_PST_DISP))
1001 condition = "hi_disp";
1005 case OLD_CTL_PST_SEL_SELCAND:
1006 condition = "sel_cand";
1008 case OLD_CTL_PST_SEL_SYNCCAND:
1009 condition = "sync_cand";
1011 case OLD_CTL_PST_SEL_SYSPEER:
1012 condition = "sys_peer";
1018 auth = condition = "";
1021 switch (PEER_EVENT|event) {
1022 case EVNT_PEERIPERR:
1023 last_event = "IP error";
1026 last_event = "auth fail";
1029 last_event = "lost reach";
1032 last_event = "reachable";
1034 case EVNT_PEERCLOCK:
1035 last_event = "clock expt";
1038 case EVNT_PEERSTRAT:
1039 last_event = "stratum chg";
1047 if (event_count != 0)
1048 cnt = uinttoa(event_count);
1052 "%3d %5u %04x %3.3s %4s %4.4s %9.9s %11s %2s",
1053 i+1, assoc_cache[i].assid, assoc_cache[i].status,
1054 conf, reach, auth, condition, last_event, cnt);
1055 bp = &buf[strlen(buf)];
1056 while (bp > buf && *(bp-1) == ' ')
1058 (void) fprintf(fp, "%s\n", buf);
1065 * associations - get, record and print a list of associations
1080 * lassociations - get, record and print a long list of associations
1095 * passociations - print the association list
1109 * lpassociations - print the long association list
1124 * radiostatus - print the radio status returned by the server
1138 res = doquery(CTL_OP_READCLOCK, 0, 0, 0, (char *)0, &rstatus,
1145 (void) fprintf(fp, "server=%s ", currenthost);
1147 (void) fprintf(fp, "No radio status string returned\n");
1151 asciize(dsize, datap, fp);
1156 * pstatus - print peer status returned by the server
1171 if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
1174 res = doquery(CTL_OP_READSTAT, associd, 0, 0, (char *)0, &rstatus,
1181 (void) fprintf(fp, "server=%s ", currenthost);
1184 "No information returned for association %u\n",
1189 (void) fprintf(fp,"assID=%d ",associd);
1190 printvars(dsize, datap, (int)rstatus, TYPE_PEER, fp);
1195 * when - print how long its been since his last packet arrived
1208 else if (reftime->l_ui != 0)
1213 return (ts->l_ui - lasttime->l_ui);
1218 * Pretty-print an interval into the given buffer, in a human-friendly format.
1233 (void) sprintf(buf, "%ld", (long int)diff);
1237 diff = (diff + 29) / 60;
1239 (void) sprintf(buf, "%ldm", (long int)diff);
1243 diff = (diff + 29) / 60;
1245 (void) sprintf(buf, "%ldh", (long int)diff);
1249 diff = (diff + 11) / 24;
1250 (void) sprintf(buf, "%ldd", (long int)diff);
1256 struct sockaddr_storage *sock
1261 struct sockaddr_in6 *sin6;
1263 switch(sock->ss_family) {
1265 dummy = ((struct sockaddr_in *)sock)->sin_addr.s_addr;
1266 dummy = ntohl(dummy);
1267 ch = (char)(((dummy&0xf0000000)==0xe0000000) ? 'm' :
1268 ((dummy&0x000000ff)==0x000000ff) ? 'b' :
1269 ((dummy&0xffffffff)==0x7f000001) ? 'l' :
1270 ((dummy&0xffffffe0)==0x00000000) ? '-' :
1274 sin6 = (struct sockaddr_in6 *)sock;
1275 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
1288 * A list of variables required by the peers command
1290 struct varlist opeervarlist[] = {
1291 { "srcadr", 0 }, /* 0 */
1292 { "dstadr", 0 }, /* 1 */
1293 { "stratum", 0 }, /* 2 */
1294 { "hpoll", 0 }, /* 3 */
1295 { "ppoll", 0 }, /* 4 */
1296 { "reach", 0 }, /* 5 */
1297 { "delay", 0 }, /* 6 */
1298 { "offset", 0 }, /* 7 */
1299 { "jitter", 0 }, /* 8 */
1300 { "dispersion", 0 }, /* 9 */
1301 { "rec", 0 }, /* 10 */
1302 { "reftime", 0 }, /* 11 */
1303 { "srcport", 0 }, /* 12 */
1307 struct varlist peervarlist[] = {
1308 { "srcadr", 0 }, /* 0 */
1309 { "refid", 0 }, /* 1 */
1310 { "stratum", 0 }, /* 2 */
1311 { "hpoll", 0 }, /* 3 */
1312 { "ppoll", 0 }, /* 4 */
1313 { "reach", 0 }, /* 5 */
1314 { "delay", 0 }, /* 6 */
1315 { "offset", 0 }, /* 7 */
1316 { "jitter", 0 }, /* 8 */
1317 { "dispersion", 0 }, /* 9 */
1318 { "rec", 0 }, /* 10 */
1319 { "reftime", 0 }, /* 11 */
1320 { "srcport", 0 }, /* 12 */
1324 #define HAVE_SRCADR 0
1325 #define HAVE_DSTADR 1
1326 #define HAVE_REFID 1
1327 #define HAVE_STRATUM 2
1328 #define HAVE_HPOLL 3
1329 #define HAVE_PPOLL 4
1330 #define HAVE_REACH 5
1331 #define HAVE_DELAY 6
1332 #define HAVE_OFFSET 7
1333 #define HAVE_JITTER 8
1334 #define HAVE_DISPERSION 9
1336 #define HAVE_REFTIME 11
1337 #define HAVE_SRCPORT 12
1341 * Decode an incoming data buffer and print a line in the peer list
1345 struct varlist *pvl,
1359 struct sockaddr_storage srcadr;
1360 struct sockaddr_storage dstadr;
1362 char *dstadr_refid = "0.0.0.0";
1374 u_char havevar[MAXHAVE];
1377 char refid_string[10];
1378 char whenbuf[8], pollbuf[8];
1379 char clock_name[LENHOSTNAME];
1381 memset((char *)havevar, 0, sizeof(havevar));
1384 memset((char *)&srcadr, 0, sizeof(struct sockaddr_storage));
1385 memset((char *)&dstadr, 0, sizeof(struct sockaddr_storage));
1387 /* Initialize by zeroing out estimate variables */
1388 memset((char *)&estoffset, 0, sizeof(l_fp));
1389 memset((char *)&estdelay, 0, sizeof(l_fp));
1390 memset((char *)&estjitter, 0, sizeof(l_fp));
1391 memset((char *)&estdisp, 0, sizeof(l_fp));
1393 while (nextvar(&datalen, &data, &name, &value)) {
1394 struct sockaddr_storage dum_store;
1396 i = findvar(name, peer_var, 1);
1398 continue; /* don't know this one */
1401 if (decodenetnum(value, &srcadr))
1402 havevar[HAVE_SRCADR] = 1;
1405 if (decodenetnum(value, &dum_store))
1406 type = decodeaddrtype(&dum_store);
1407 if (pvl == opeervarlist) {
1408 if (decodenetnum(value, &dstadr)) {
1409 havevar[HAVE_DSTADR] = 1;
1410 dstadr_refid = stoa(&dstadr);
1415 if (pvl == peervarlist) {
1416 havevar[HAVE_REFID] = 1;
1417 if (*value == '\0') {
1418 dstadr_refid = "0.0.0.0";
1419 } else if ((int)strlen(value) <= 4) {
1420 refid_string[0] = '.';
1421 (void) strcpy(&refid_string[1], value);
1422 i = strlen(refid_string);
1423 refid_string[i] = '.';
1424 refid_string[i+1] = '\0';
1425 dstadr_refid = refid_string;
1426 } else if (decodenetnum(value, &dstadr)) {
1427 if (SOCKNUL(&dstadr))
1428 dstadr_refid = "0.0.0.0";
1429 else if ((dstadr.ss_family == AF_INET)
1430 && ISREFCLOCKADR(&dstadr))
1437 havevar[HAVE_REFID] = 0;
1442 if (decodeuint(value, &stratum))
1443 havevar[HAVE_STRATUM] = 1;
1446 if (decodeint(value, &hpoll)) {
1447 havevar[HAVE_HPOLL] = 1;
1449 hpoll = NTP_MINPOLL;
1453 if (decodeint(value, &ppoll)) {
1454 havevar[HAVE_PPOLL] = 1;
1456 ppoll = NTP_MINPOLL;
1460 if (decodeuint(value, &reach))
1461 havevar[HAVE_REACH] = 1;
1464 if (decodetime(value, &estdelay))
1465 havevar[HAVE_DELAY] = 1;
1468 if (decodetime(value, &estoffset))
1469 havevar[HAVE_OFFSET] = 1;
1472 if (pvl == peervarlist)
1473 if (decodetime(value, &estjitter))
1474 havevar[HAVE_JITTER] = 1;
1477 if (decodetime(value, &estdisp))
1478 havevar[HAVE_DISPERSION] = 1;
1481 if (decodets(value, &rec))
1482 havevar[HAVE_REC] = 1;
1485 if (decodeuint(value, &srcport))
1486 havevar[HAVE_SRCPORT] = 1;
1489 havevar[HAVE_REFTIME] = 1;
1490 if (!decodets(value, &reftime))
1499 * Check to see if the srcport is NTP's port. If not this probably
1500 * isn't a valid peer association.
1502 if (havevar[HAVE_SRCPORT] && srcport != NTP_PORT)
1506 * Got everything, format the line
1508 poll_sec = 1<<max(min3(ppoll, hpoll, NTP_MAXPOLL), NTP_MINPOLL);
1509 if (pktversion > NTP_OLDVERSION)
1510 c = flash3[CTL_PEER_STATVAL(rstatus) & 0x7];
1512 c = flash2[CTL_PEER_STATVAL(rstatus) & 0x3];
1514 (void) fprintf(fp, "%-*s ", maxhostlen, currenthost);
1515 if (af == 0 || srcadr.ss_family == af){
1516 strcpy(clock_name, nntohost(&srcadr));
1519 "%c%-15.15s %-15.15s %2ld %c %4.4s %4.4s %3lo %7.7s %8.7s %7.7s\n",
1520 c, clock_name, dstadr_refid, stratum, type,
1521 prettyinterval(whenbuf, when(&ts, &rec, &reftime)),
1522 prettyinterval(pollbuf, (int)poll_sec), reach,
1523 lfptoms(&estdelay, 3), lfptoms(&estoffset, 3),
1524 havevar[HAVE_JITTER] ? lfptoms(&estjitter, 3) :
1525 lfptoms(&estdisp, 3));
1538 #undef HAVE_ESTDELAY
1539 #undef HAVE_ESTOFFSET
1550 * dogetpeers - given an association ID, read and print the spreadsheet
1555 struct varlist *pvl,
1567 res = doquerylist(pvl, CTL_OP_READVAR, associd, 0, &rstatus,
1573 res = doquery(CTL_OP_READVAR, associd, 0, 0, (char *)0, &rstatus,
1582 (void) fprintf(stderr, "server=%s ", currenthost);
1583 (void) fprintf(stderr,
1584 "***No information returned for association %d\n",
1589 return doprintpeers(pvl, associd, (int)rstatus, dsize, datap, fp, af);
1594 * peers - print a peer spreadsheet
1604 char fullname[LENHOSTNAME];
1605 struct sockaddr_storage netnum;
1607 if (!dogetassoc(fp))
1610 for (i = 0; i < numhosts; ++i) {
1611 if (getnetnum(chosts[i], &netnum, fullname, af))
1612 if ((int)strlen(fullname) > maxhostlen)
1613 maxhostlen = strlen(fullname);
1616 (void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "server");
1618 " remote refid st t when poll reach delay offset jitter\n");
1620 for (i = 0; i <= maxhostlen; ++i)
1621 (void) fprintf(fp, "=");
1623 "==============================================================================\n");
1625 for (i = 0; i < numassoc; i++) {
1627 !(CTL_PEER_STATVAL(assoc_cache[i].status)
1628 & (CTL_PST_CONFIG|CTL_PST_REACH)))
1630 if (!dogetpeers(peervarlist, (int)assoc_cache[i].assid, fp, af)) {
1639 * peers - print a peer spreadsheet
1650 if (pcmd->nargs == 1) {
1651 if (pcmd->argval->ival == 6)
1661 * lpeers - print a peer spreadsheet including all fuzzball peers
1672 if (pcmd->nargs == 1) {
1673 if (pcmd->argval->ival == 6)
1683 * opeers - print a peer spreadsheet
1693 char fullname[LENHOSTNAME];
1694 struct sockaddr_storage netnum;
1696 if (!dogetassoc(fp))
1699 for (i = 0; i < numhosts; ++i) {
1700 if (getnetnum(chosts[i], &netnum, fullname, af))
1701 if ((int)strlen(fullname) > maxhostlen)
1702 maxhostlen = strlen(fullname);
1705 (void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "server");
1707 " remote local st t when poll reach delay offset disp\n");
1709 for (i = 0; i <= maxhostlen; ++i)
1710 (void) fprintf(fp, "=");
1712 "==============================================================================\n");
1714 for (i = 0; i < numassoc; i++) {
1716 !(CTL_PEER_STATVAL(assoc_cache[i].status)
1717 & (CTL_PST_CONFIG|CTL_PST_REACH)))
1719 if (!dogetpeers(opeervarlist, (int)assoc_cache[i].assid, fp, af)) {
1728 * opeers - print a peer spreadsheet the old way
1739 if (pcmd->nargs == 1) {
1740 if (pcmd->argval->ival == 6)
1745 doopeers(0, fp, af);
1750 * lopeers - print a peer spreadsheet including all fuzzball peers
1761 if (pcmd->nargs == 1) {
1762 if (pcmd->argval->ival == 6)
1767 doopeers(1, fp, af);