Remove ntpq pstatus command, rv/readvar does the same and more.
bk: 4d145447bIiibiF8F2EJ-Zq08sn6KA
+* Add ntpq pstats command similar to ntpdc's.
+* Remove ntpq pstatus command, rv/readvar does the same and more.
(4.2.7p102) 2010/12/23 Released by Harlan Stenn <stenn@ntp.org>
* Allow ntpq &1 associd use without preceding association-fetching.
* Documentation updates from Dave Mills.
#define CP_RATE 40
#define CP_BIAS 41
#define CP_SRCHOST 42
-#define CP_MAX_NOAUTOKEY CP_SRCHOST
+#define CP_TIMEREC 43
+#define CP_TIMEREACH 44
+#define CP_BADAUTH 45
+#define CP_BOGUSORG 46
+#define CP_OLDPKT 47
+#define CP_SELDISP 48
+#define CP_SELBROKEN 49
+#define CP_CANDIDATE 50
+#define CP_MAX_NOAUTOKEY CP_CANDIDATE
#ifdef AUTOKEY
#define CP_FLAGS (1 + CP_MAX_NOAUTOKEY)
#define CP_HOST (2 + CP_MAX_NOAUTOKEY)
LIB_GETBUF(cb);
switch (type) {
- case TYPE_SYS:
+
+ case TYPE_SYS:
strcpy(cb, getcode(CTL_SYS_LI(st), leap_codes));
strcat(cb, ", ");
strcat(cb, getcode(CTL_SYS_SOURCE(st), sync_codes));
strcat(cb, getcode(CTL_SYS_EVENT(st), sys_codes));
break;
- case TYPE_PEER:
-
+ case TYPE_PEER:
/*
* Handcraft the bits
*/
}
break;
- case TYPE_CLOCK:
+ case TYPE_CLOCK:
strcat(cb, ", ");
strcat(cb, getevents(CTL_SYS_NEVNT(st)));
strcat(cb, ", ");
{ CP_JITTER, RO, "jitter" }, /* 26 */
{ CP_DISPERSION, RO, "dispersion" }, /* 27 */
{ CP_KEYID, RO, "keyid" }, /* 28 */
- { CP_FILTDELAY, RO, "filtdelay=" }, /* 29 */
- { CP_FILTOFFSET, RO, "filtoffset=" }, /* 30 */
+ { CP_FILTDELAY, RO, "filtdelay" }, /* 29 */
+ { CP_FILTOFFSET, RO, "filtoffset" }, /* 30 */
{ CP_PMODE, RO, "pmode" }, /* 31 */
{ CP_RECEIVED, RO, "received"}, /* 32 */
{ CP_SENT, RO, "sent" }, /* 33 */
- { CP_FILTERROR, RO, "filtdisp=" }, /* 34 */
+ { CP_FILTERROR, RO, "filtdisp" }, /* 34 */
{ CP_FLASH, RO, "flash" }, /* 35 */
{ CP_TTL, RO, "ttl" }, /* 36 */
{ CP_VARLIST, RO, "peer_var_list" }, /* 37 */
{ CP_RATE, RO, "headway" }, /* 40 */
{ CP_BIAS, RO, "bias" }, /* 41 */
{ CP_SRCHOST, RO, "srchost" }, /* 42 */
+ { CP_TIMEREC, RO, "timerec" }, /* 43 */
+ { CP_TIMEREACH, RO, "timereach" }, /* 44 */
+ { CP_BADAUTH, RO, "badauth" }, /* 45 */
+ { CP_BOGUSORG, RO, "bogusorg" }, /* 46 */
+ { CP_OLDPKT, RO, "oldpkt" }, /* 47 */
+ { CP_SELDISP, RO, "seldisp" }, /* 48 */
+ { CP_SELBROKEN, RO, "selbroken" }, /* 49 */
+ { CP_CANDIDATE, RO, "candidate" }, /* 50 */
#ifdef AUTOKEY
- { CP_FLAGS, RO, "flags" }, /* 43 */
- { CP_HOST, RO, "host" }, /* 44 */
- { CP_VALID, RO, "valid" }, /* 45 */
- { CP_INITSEQ, RO, "initsequence" }, /* 46 */
- { CP_INITKEY, RO, "initkey" }, /* 47 */
- { CP_INITTSP, RO, "timestamp" }, /* 48 */
- { CP_SIGNATURE, RO, "signature" }, /* 49 */
- { CP_IDENT, RO, "ident" }, /* 44 */
+ { CP_FLAGS, RO, "flags" }, /* 1 + CP_MAX_NOAUTOKEY */
+ { CP_HOST, RO, "host" }, /* 2 + CP_MAX_NOAUTOKEY */
+ { CP_VALID, RO, "valid" }, /* 3 + CP_MAX_NOAUTOKEY */
+ { CP_INITSEQ, RO, "initsequence" }, /* 4 + CP_MAX_NOAUTOKEY */
+ { CP_INITKEY, RO, "initkey" }, /* 5 + CP_MAX_NOAUTOKEY */
+ { CP_INITTSP, RO, "timestamp" }, /* 6 + CP_MAX_NOAUTOKEY */
+ { CP_SIGNATURE, RO, "signature" }, /* 7 + CP_MAX_NOAUTOKEY */
+ { CP_IDENT, RO, "ident" }, /* 8 + CP_MAX_NOAUTOKEY */
#endif /* AUTOKEY */
- { 0, EOV, "" } /* 44/51 */
+ { 0, EOV, "" } /* 50/58 */
};
cq = tag;
while (*cq != '\0')
*cp++ = *cq++;
+ *cp++ = '=';
i = start;
do {
if (i == 0)
snprintf(cp, sizeof(buffer) - (cp - buffer),
" %.2f", arr[i] * 1e3);
cp += strlen(cp);
- } while(i != start);
+ } while (i != start);
ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
}
case CP_FILTDELAY:
ctl_putarray(peer_var[id].text, p->filter_delay,
- (int)p->filter_nextpt);
+ p->filter_nextpt);
break;
case CP_FILTOFFSET:
ctl_putarray(peer_var[id].text, p->filter_offset,
- (int)p->filter_nextpt);
+ p->filter_nextpt);
break;
case CP_FILTERROR:
ctl_putarray(peer_var[id].text, p->filter_disp,
- (int)p->filter_nextpt);
+ p->filter_nextpt);
break;
case CP_PMODE:
ctl_putdata(buf, (u_int)(s - buf), 0);
}
break;
+
+ case CP_TIMEREC:
+ ctl_putuint(peer_var[id].text,
+ current_time - p->timereceived);
+ break;
+
+ case CP_TIMEREACH:
+ ctl_putuint(peer_var[id].text,
+ current_time - p->timereachable);
+ break;
+
+ case CP_BADAUTH:
+ ctl_putuint(peer_var[id].text, p->badauth);
+ break;
+
+ case CP_BOGUSORG:
+ ctl_putuint(peer_var[id].text, p->bogusorg);
+ break;
+
+ case CP_OLDPKT:
+ ctl_putuint(peer_var[id].text, p->oldpkt);
+ break;
+
+ case CP_SELDISP:
+ ctl_putuint(peer_var[id].text, p->seldisptoolarge);
+ break;
+
+ case CP_SELBROKEN:
+ ctl_putuint(peer_var[id].text, p->selbroken);
+ break;
+
+ case CP_CANDIDATE:
+ ctl_putuint(peer_var[id].text, p->status);
+ break;
#ifdef AUTOKEY
case CP_FLAGS:
if (p->crypto)
static void
print_pflag(
- FILE *fp,
- u_int32 flags
- )
+ FILE * fp,
+ u_int32 flags
+ )
{
- const char *str;
+ static const char none[] = "";
+ static const char comma[] = ",";
+ const char *dlim;
- if (flags == 0) {
- (void) fprintf(fp, " none\n");
- } else {
- str = "";
- if (flags & INFO_FLAG_SYSPEER) {
- (void) fprintf(fp, " system_peer");
- str = ",";
- }
- if (flags & INFO_FLAG_CONFIG) {
- (void) fprintf(fp, "%s config", str);
- str = ",";
- }
- if (flags & INFO_FLAG_REFCLOCK) {
- (void) fprintf(fp, "%s refclock", str);
- str = ",";
- }
- if (flags & INFO_FLAG_AUTHENABLE) {
- (void) fprintf(fp, "%s auth", str);
- str = ",";
- }
- if (flags & INFO_FLAG_BCLIENT) {
- (void) fprintf(fp, "%s bclient", str);
- str = ",";
- }
- if (flags & INFO_FLAG_PREFER) {
- (void) fprintf(fp, "%s prefer", str);
- str = ",";
- }
- if (flags & INFO_FLAG_IBURST) {
- (void) fprintf(fp, "%s iburst", str);
- str = ",";
- }
- if (flags & INFO_FLAG_BURST) {
- (void) fprintf(fp, "%s burst", str);
- }
- (void) fprintf(fp, "\n");
+ if (0 == flags) {
+ fprintf(fp, " none\n");
+ return;
+ }
+ dlim = none;
+ if (flags & INFO_FLAG_SYSPEER) {
+ fprintf(fp, " system_peer");
+ dlim = comma;
+ }
+ if (flags & INFO_FLAG_CONFIG) {
+ fprintf(fp, "%s config", dlim);
+ dlim = comma;
+ }
+ if (flags & INFO_FLAG_REFCLOCK) {
+ fprintf(fp, "%s refclock", dlim);
+ dlim = comma;
+ }
+ if (flags & INFO_FLAG_AUTHENABLE) {
+ fprintf(fp, "%s auth", dlim);
+ dlim = comma;
+ }
+ if (flags & INFO_FLAG_PREFER) {
+ fprintf(fp, "%s prefer", dlim);
+ dlim = comma;
}
+ if (flags & INFO_FLAG_IBURST) {
+ fprintf(fp, "%s iburst", dlim);
+ dlim = comma;
+ }
+ if (flags & INFO_FLAG_BURST) {
+ fprintf(fp, "%s burst", dlim);
+ dlim = comma;
+ }
+ if (flags & INFO_FLAG_SEL_CANDIDATE) {
+ fprintf(fp, "%s candidate", dlim);
+ dlim = comma;
+ }
+ if (flags & INFO_FLAG_PREFER) {
+ fprintf(fp, "%s shortlist", dlim);
+ dlim = comma;
+ }
+ fprintf(fp, "\n");
}
/*
* printpeer - print detail information for a peer
static void radiostatus (struct parse *, FILE *);
#endif /* UNUSED */
-static void pstatus (struct parse *, FILE *);
+static void pstats (struct parse *, FILE *);
static long when (l_fp *, l_fp *, l_fp *);
static char * prettyinterval (char *, size_t, long);
static int doprintpeers (struct varlist *, int, int, int, const char *, FILE *, int);
{ "cv", clockvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
{ "assocID", "name=value[,...]", "", "" },
"read clock variables" },
- { "pstatus", pstatus, { NTP_UINT, NO, NO, NO },
+ { "pstats", pstats, { NTP_UINT, NO, NO, NO },
{ "assocID", "", "", "" },
"print status information returned for a peer" },
{ "peers", peers, { OPT|IP_VERSION, NO, NO, NO },
const char * const display; /* descriptive text */
u_char type; /* NTP_STR, etc */
union {
- char *str;
+ char * str;
+ sockaddr_u sau; /* NTP_ADD */
} v; /* retrieved value */
} vdc;
static int qcmp_mru_r_count(const void *, const void *);
static void validate_ifnum(u_int, int, ifstats_row *);
static void another_ifstats_field(int *, ifstats_row *, FILE *);
-static void collect_display_vdc(vdc *vdc_table, FILE *fp);
+static void collect_display_vdc(associd_t as, vdc *table, FILE *fp);
/*
* static globals
}
if (!quiet)
- fprintf(fp,"associd=%d ",associd);
+ fprintf(fp, "associd=%u ", associd);
printvars(dsize, datap, (int)rstatus, type, quiet, fp);
return 1;
}
if (dsize == 0)
(void) fprintf(fp, "done! (no data returned)\n");
else {
- (void) fprintf(fp,"associd=%d ",associd);
+ (void) fprintf(fp,"associd=%u ", associd);
printvars(dsize, datap, (int)rstatus,
(associd != 0) ? TYPE_PEER : TYPE_SYS, 0, fp);
}
if (dsize == 0)
fprintf(fp, "done! (no data returned)\n");
else {
- fprintf(fp,"associd=%d ",associd);
+ fprintf(fp,"associd=%u ", associd);
type = (0 == associd)
? TYPE_SYS
: TYPE_PEER;
}
#endif /* UNUSED */
-/*
- * pstatus - print peer status returned by the server
- */
-static void
-pstatus(
- struct parse *pcmd,
- FILE *fp
- )
-{
- const char *datap;
- int res;
- associd_t associd;
- int dsize;
- u_short rstatus;
-
- /* HMS: uval? */
- if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
- return;
-
- res = doquery(CTL_OP_READSTAT, associd, 0, 0, NULL, &rstatus,
- &dsize, &datap);
-
- if (res != 0)
- return;
-
- if (numhosts > 1)
- fprintf(fp, "server=%s ", currenthost);
- if (dsize == 0) {
- fprintf(fp,
- "No information returned for association %u\n",
- associd);
- return;
- }
-
- fprintf(fp, "associd=%u ", associd);
- printvars(dsize, datap, (int)rstatus, TYPE_PEER, 0, fp);
-}
-
-
/*
* when - print how long its been since his last packet arrived
*/
*/
static void
collect_display_vdc(
- vdc *vdc_table,
- FILE *fp
+ associd_t as,
+ vdc * table,
+ FILE * fp
)
{
+ static const char * const suf[2] = { "adr", "port" };
struct varlist vl[MAXLIST];
+ char tagbuf[32];
vdc *pvdc;
u_short rstatus;
int rsize;
int qres;
char *tag;
char *val;
+ u_int n;
+ size_t taglen;
+ int match;
+ u_long ul;
memset(vl, 0, sizeof(vl));
- for (pvdc = vdc_table; pvdc->tag != NULL; pvdc++) {
+ for (pvdc = table; pvdc->tag != NULL; pvdc++) {
memset(&pvdc->v, 0, sizeof(pvdc->v));
- doaddvlist(vl, pvdc->tag);
+ if (NTP_ADD != pvdc->type) {
+ doaddvlist(vl, pvdc->tag);
+ } else {
+ for (n = 0; n < COUNTOF(suf); n++) {
+ snprintf(tagbuf, sizeof(tagbuf), "%s%s",
+ pvdc->tag, suf[n]);
+ doaddvlist(vl, tagbuf);
+ }
+ }
}
- qres = doquerylist(vl, CTL_OP_READVAR, 0, 0, &rstatus, &rsize,
- &rdata);
+ qres = doquerylist(vl, CTL_OP_READVAR, as, 0, &rstatus, &rsize,
+ &rdata);
doclearvlist(vl);
if (qres)
return; /* error msg already displayed */
* the retrieved values.
*/
while (nextvar(&rsize, &rdata, &tag, &val)) {
- for (pvdc = vdc_table; pvdc->tag != NULL; pvdc++)
- if (!strcmp(tag, pvdc->tag))
+ for (pvdc = table; pvdc->tag != NULL; pvdc++) {
+ taglen = strlen(pvdc->tag);
+ if (strncmp(tag, pvdc->tag, taglen))
+ continue;
+ if (NTP_ADD != pvdc->type) {
+ if ('\0' != tag[taglen])
+ continue;
break;
- if (pvdc->tag != NULL) {
- NTP_INSIST(NTP_STR == pvdc->type);
+ }
+ match = FALSE;
+ for (n = 0; n < COUNTOF(suf); n++) {
+ if (strcmp(tag + taglen, suf[n]))
+ continue;
+ match = TRUE;
+ break;
+ }
+ if (match)
+ break;
+ }
+ if (NULL == pvdc->tag)
+ continue;
+ if (NTP_STR == pvdc->type) {
pvdc->v.str = estrdup(val);
+ } else if (NTP_ADD == pvdc->type) {
+ if (0 == n) { /* adr */
+ decodenetnum(val, &pvdc->v.sau);
+ } else { /* port */
+ if (atouint(val, &ul))
+ SET_PORT(&pvdc->v.sau,
+ (u_short)ul);
+ }
}
}
/* and display */
- for (pvdc = vdc_table; pvdc->tag != NULL; pvdc++) {
- if (pvdc->v.str != NULL) {
+ if (as != 0)
+ fprintf(fp, "associd=%u status=%04x %s,\n", as, rstatus,
+ statustoa(TYPE_PEER, rstatus));
+
+ for (pvdc = table; pvdc->tag != NULL; pvdc++) {
+ switch (pvdc->type) {
+
+ case NTP_STR:
+ if (pvdc->v.str != NULL) {
+ fprintf(fp, "%s %s\n", pvdc->display,
+ pvdc->v.str);
+ free(pvdc->v.str);
+ pvdc->v.str = NULL;
+ }
+ break;
+
+ case NTP_ADD:
fprintf(fp, "%s %s\n", pvdc->display,
- pvdc->v.str);
- free(pvdc->v.str);
+ nntohostp(&pvdc->v.sau));
+ break;
+
+ default:
+ fprintf(stderr, "unexpected vdc type %d for %s\n",
+ pvdc->type, pvdc->tag);
+ break;
}
}
}
{ NULL, NULL, 0 }
};
- collect_display_vdc(sysstats_vdc, fp);
+ collect_display_vdc(0, sysstats_vdc, fp);
}
{ NULL, NULL, 0 }
};
- collect_display_vdc(monstats_vdc, fp);
+ collect_display_vdc(0, monstats_vdc, fp);
}
+
+
+/*
+ * pstats - print peer statistics returned by the server
+ */
+static void
+pstats(
+ struct parse *pcmd,
+ FILE *fp
+ )
+{
+ static vdc pstats_vdc[] = {
+ { "src", "remote host: ", NTP_ADD },
+ { "dst", "local address: ", NTP_ADD },
+ { "timerec", "time last received: ", NTP_STR },
+ { "timer", "time until next send:", NTP_STR },
+ { "timereach", "reachability change: ", NTP_STR },
+ { "sent", "packets sent: ", NTP_STR },
+ { "received", "packets received: ", NTP_STR },
+ { "badauth", "bad authentication: ", NTP_STR },
+ { "bogusorg", "bogus origin: ", NTP_STR },
+ { "oldpkt", "duplicate: ", NTP_STR },
+ { "seldisp", "bad dispersion: ", NTP_STR },
+ { "selbroken", "bad reference time: ", NTP_STR },
+ { "candidate", "candidate order: ", NTP_STR },
+ { NULL, NULL, 0 }
+ };
+ associd_t associd;
+
+ associd = checkassocid(pcmd->argval[0].uval);
+ if (0 == associd)
+ return;
+
+ collect_display_vdc(associd, pstats_vdc, fp);
+}
+
#include "ntp_calendar.h"
#include "ntp_select.h"
#include "ntp_assert.h"
+#include "lib_strbuf.h"
#include "ntp_lineedit.h"
#include "ntp_debug.h"
#ifdef OPENSSL
}
+/*
+ * nntohostp() is the same as nntohost() plus a :port suffix
+ */
+char *
+nntohostp(
+ sockaddr_u *netnum
+ )
+{
+ const char * hostn;
+ char * buf;
+
+ if (!showhostnames || SOCK_UNSPEC(netnum))
+ return sptoa(netnum);
+ else if (ISREFCLOCKADR(netnum))
+ return refnumtoa(netnum);
+
+ hostn = socktohost(netnum);
+ LIB_GETBUF(buf);
+ snprintf(buf, LIB_BUFLENGTH, "%s:%u", hostn, SRCPORT(netnum));
+
+ return buf;
+}
+
/*
* rtdatetolfp - decode an RT-11 date into an l_fp
*/
extern int doqueryex (int, associd_t, int, int, const char *,
u_short *, int *, const char **, int);
extern char * nntohost (sockaddr_u *);
+extern char * nntohostp (sockaddr_u *);
extern int decodets (char *, l_fp *);
extern int decodeuint (char *, u_long *);
extern int nextvar (int *, const char **, char **, char **);