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);