From: Dave Hart Date: Fri, 24 Dec 2010 08:05:27 +0000 (+0000) Subject: Add ntpq pstats command similar to ntpdc's. X-Git-Tag: NTP_4_2_7P103~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b0387ecdb014344127993e07304d6cfe09293b1f;p=thirdparty%2Fntp.git Add ntpq pstats command similar to ntpdc's. Remove ntpq pstatus command, rv/readvar does the same and more. bk: 4d145447bIiibiF8F2EJ-Zq08sn6KA --- diff --git a/ChangeLog b/ChangeLog index c2f9589bf..4a66bca85 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,5 @@ +* 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 * Allow ntpq &1 associd use without preceding association-fetching. * Documentation updates from Dave Mills. diff --git a/include/ntp_control.h b/include/ntp_control.h index 63e4155a9..dd02d9bd5 100644 --- a/include/ntp_control.h +++ b/include/ntp_control.h @@ -252,7 +252,15 @@ struct ntp_control { #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) diff --git a/libntp/statestr.c b/libntp/statestr.c index 6edc859fb..0dbf2abc0 100644 --- a/libntp/statestr.c +++ b/libntp/statestr.c @@ -237,7 +237,8 @@ statustoa( 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)); @@ -247,8 +248,7 @@ statustoa( strcat(cb, getcode(CTL_SYS_EVENT(st), sys_codes)); break; - case TYPE_PEER: - + case TYPE_PEER: /* * Handcraft the bits */ @@ -296,7 +296,7 @@ statustoa( } break; - case TYPE_CLOCK: + case TYPE_CLOCK: strcat(cb, ", "); strcat(cb, getevents(CTL_SYS_NEVNT(st))); strcat(cb, ", "); diff --git a/ntpd/ntp_control.c b/ntpd/ntp_control.c index afa989e82..9b64ae11d 100644 --- a/ntpd/ntp_control.c +++ b/ntpd/ntp_control.c @@ -248,12 +248,12 @@ static struct ctl_var peer_var[] = { { 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 */ @@ -262,17 +262,25 @@ static struct ctl_var peer_var[] = { { 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 */ }; @@ -1380,6 +1388,7 @@ ctl_putarray( cq = tag; while (*cq != '\0') *cp++ = *cq++; + *cp++ = '='; i = start; do { if (i == 0) @@ -1389,7 +1398,7 @@ ctl_putarray( 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); } @@ -1928,17 +1937,17 @@ ctl_putpeer( 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: @@ -1979,6 +1988,40 @@ ctl_putpeer( 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) diff --git a/ntpdc/ntpdc_ops.c b/ntpdc/ntpdc_ops.c index 134f82eca..c28928e86 100644 --- a/ntpdc/ntpdc_ops.c +++ b/ntpdc/ntpdc_ops.c @@ -550,49 +550,56 @@ refid_string( 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 diff --git a/ntpq/ntpq-subs.c b/ntpq/ntpq-subs.c index aa8f9cd5e..5049f7376 100644 --- a/ntpq/ntpq-subs.c +++ b/ntpq/ntpq-subs.c @@ -51,7 +51,7 @@ static void lpassociations (struct parse *, FILE *); 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); @@ -143,7 +143,7 @@ struct xcmd opcmds[] = { { "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 }, @@ -292,7 +292,8 @@ typedef struct var_display_collection_tag { 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; @@ -310,7 +311,7 @@ static int qcmp_mru_count(const void *, const void *); 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 @@ -667,7 +668,7 @@ dolist( } if (!quiet) - fprintf(fp,"associd=%d ",associd); + fprintf(fp, "associd=%u ", associd); printvars(dsize, datap, (int)rstatus, type, quiet, fp); return 1; } @@ -738,7 +739,7 @@ writelist( 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); } @@ -823,7 +824,7 @@ writevar( 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; @@ -1374,45 +1375,6 @@ radiostatus( } #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 */ @@ -3240,11 +3202,14 @@ ifstats( */ 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; @@ -3252,14 +3217,26 @@ collect_display_vdc( 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 */ @@ -3269,21 +3246,66 @@ collect_display_vdc( * 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; } } } @@ -3314,7 +3336,7 @@ sysstats( { NULL, NULL, 0 } }; - collect_display_vdc(sysstats_vdc, fp); + collect_display_vdc(0, sysstats_vdc, fp); } @@ -3339,5 +3361,41 @@ monstats( { 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); +} + diff --git a/ntpq/ntpq.c b/ntpq/ntpq.c index bab61722f..6c1eebfaa 100644 --- a/ntpq/ntpq.c +++ b/ntpq/ntpq.c @@ -26,6 +26,7 @@ #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 @@ -1840,6 +1841,29 @@ nntohost( } +/* + * 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 */ diff --git a/ntpq/ntpq.h b/ntpq/ntpq.h index f3afecac5..93b0e10ab 100644 --- a/ntpq/ntpq.h +++ b/ntpq/ntpq.h @@ -125,6 +125,7 @@ extern int doquery (int, associd_t, int, int, const char *, 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 **);