/contrib/ntp/ntpq/ntpq-subs.c
https://bitbucket.org/freebsd/freebsd-head/ · C · 1768 lines · 1381 code · 202 blank · 185 comment · 308 complexity · 7c8e2ff6e32af5485776a9dff2cc41b2 MD5 · raw file
- /*
- * ntpq_ops.c - subroutines which are called to perform operations by ntpq
- */
- #include <stdio.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include "ntpq.h"
- #include "ntp_stdlib.h"
- extern char * chosts[];
- extern char currenthost[];
- extern int numhosts;
- int maxhostlen;
- /*
- * Declarations for command handlers in here
- */
- static int checkassocid P((u_int32));
- static char * strsave P((char *));
- static struct varlist *findlistvar P((struct varlist *, char *));
- static void doaddvlist P((struct varlist *, char *));
- static void dormvlist P((struct varlist *, char *));
- static void doclearvlist P((struct varlist *));
- static void makequerydata P((struct varlist *, int *, char *));
- static int doquerylist P((struct varlist *, int, int, int, u_short *, int *, char **));
- static void doprintvlist P((struct varlist *, FILE *));
- static void addvars P((struct parse *, FILE *));
- static void rmvars P((struct parse *, FILE *));
- static void clearvars P((struct parse *, FILE *));
- static void showvars P((struct parse *, FILE *));
- static int dolist P((struct varlist *, int, int, int, FILE *));
- static void readlist P((struct parse *, FILE *));
- static void writelist P((struct parse *, FILE *));
- static void readvar P((struct parse *, FILE *));
- static void writevar P((struct parse *, FILE *));
- static void clocklist P((struct parse *, FILE *));
- static void clockvar P((struct parse *, FILE *));
- static int findassidrange P((u_int32, u_int32, int *, int *));
- static void mreadlist P((struct parse *, FILE *));
- static void mreadvar P((struct parse *, FILE *));
- static int dogetassoc P((FILE *));
- static void printassoc P((int, FILE *));
- static void associations P((struct parse *, FILE *));
- static void lassociations P((struct parse *, FILE *));
- static void passociations P((struct parse *, FILE *));
- static void lpassociations P((struct parse *, FILE *));
- #ifdef UNUSED
- static void radiostatus P((struct parse *, FILE *));
- #endif /* UNUSED */
- static void pstatus P((struct parse *, FILE *));
- static long when P((l_fp *, l_fp *, l_fp *));
- static char * prettyinterval P((char *, long));
- static int doprintpeers P((struct varlist *, int, int, int, char *, FILE *, int));
- static int dogetpeers P((struct varlist *, int, FILE *, int));
- static void dopeers P((int, FILE *, int));
- static void peers P((struct parse *, FILE *));
- static void lpeers P((struct parse *, FILE *));
- static void doopeers P((int, FILE *, int));
- static void opeers P((struct parse *, FILE *));
- static void lopeers P((struct parse *, FILE *));
- /*
- * Commands we understand. Ntpdc imports this.
- */
- struct xcmd opcmds[] = {
- { "associations", associations, { NO, NO, NO, NO },
- { "", "", "", "" },
- "print list of association ID's and statuses for the server's peers" },
- { "passociations", passociations, { NO, NO, NO, NO },
- { "", "", "", "" },
- "print list of associations returned by last associations command" },
- { "lassociations", lassociations, { NO, NO, NO, NO },
- { "", "", "", "" },
- "print list of associations including all client information" },
- { "lpassociations", lpassociations, { NO, NO, NO, NO },
- { "", "", "", "" },
- "print last obtained list of associations, including client information" },
- { "addvars", addvars, { NTP_STR, NO, NO, NO },
- { "name[=value][,...]", "", "", "" },
- "add variables to the variable list or change their values" },
- { "rmvars", rmvars, { NTP_STR, NO, NO, NO },
- { "name[,...]", "", "", "" },
- "remove variables from the variable list" },
- { "clearvars", clearvars, { NO, NO, NO, NO },
- { "", "", "", "" },
- "remove all variables from the variable list" },
- { "showvars", showvars, { NO, NO, NO, NO },
- { "", "", "", "" },
- "print variables on the variable list" },
- { "readlist", readlist, { OPT|NTP_UINT, NO, NO, NO },
- { "assocID", "", "", "" },
- "read the system or peer variables included in the variable list" },
- { "rl", readlist, { OPT|NTP_UINT, NO, NO, NO },
- { "assocID", "", "", "" },
- "read the system or peer variables included in the variable list" },
- { "writelist", writelist, { OPT|NTP_UINT, NO, NO, NO },
- { "assocID", "", "", "" },
- "write the system or peer variables included in the variable list" },
- { "readvar", readvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
- { "assocID", "name=value[,...]", "", "" },
- "read system or peer variables" },
- { "rv", readvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
- { "assocID", "name=value[,...]", "", "" },
- "read system or peer variables" },
- { "writevar", writevar, { NTP_UINT, NTP_STR, NO, NO },
- { "assocID", "name=value,[...]", "", "" },
- "write system or peer variables" },
- { "mreadlist", mreadlist, { NTP_UINT, NTP_UINT, NO, NO },
- { "assocID", "assocID", "", "" },
- "read the peer variables in the variable list for multiple peers" },
- { "mrl", mreadlist, { NTP_UINT, NTP_UINT, NO, NO },
- { "assocID", "assocID", "", "" },
- "read the peer variables in the variable list for multiple peers" },
- { "mreadvar", mreadvar, { NTP_UINT, NTP_UINT, OPT|NTP_STR, NO },
- { "assocID", "assocID", "name=value[,...]", "" },
- "read peer variables from multiple peers" },
- { "mrv", mreadvar, { NTP_UINT, NTP_UINT, OPT|NTP_STR, NO },
- { "assocID", "assocID", "name=value[,...]", "" },
- "read peer variables from multiple peers" },
- { "clocklist", clocklist, { OPT|NTP_UINT, NO, NO, NO },
- { "assocID", "", "", "" },
- "read the clock variables included in the variable list" },
- { "cl", clocklist, { OPT|NTP_UINT, NO, NO, NO },
- { "assocID", "", "", "" },
- "read the clock variables included in the variable list" },
- { "clockvar", clockvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
- { "assocID", "name=value[,...]", "", "" },
- "read clock variables" },
- { "cv", clockvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
- { "assocID", "name=value[,...]", "", "" },
- "read clock variables" },
- { "pstatus", pstatus, { NTP_UINT, NO, NO, NO },
- { "assocID", "", "", "" },
- "print status information returned for a peer" },
- { "peers", peers, { OPT|IP_VERSION, NO, NO, NO },
- { "-4|-6", "", "", "" },
- "obtain and print a list of the server's peers [IP version]" },
- { "lpeers", lpeers, { OPT|IP_VERSION, NO, NO, NO },
- { "-4|-6", "", "", "" },
- "obtain and print a list of all peers and clients [IP version]" },
- { "opeers", opeers, { OPT|IP_VERSION, NO, NO, NO },
- { "-4|-6", "", "", "" },
- "print peer list the old way, with dstadr shown rather than refid [IP version]" },
- { "lopeers", lopeers, { OPT|IP_VERSION, NO, NO, NO },
- { "-4|-6", "", "", "" },
- "obtain and print a list of all peers and clients showing dstadr [IP version]" },
- { 0, 0, { NO, NO, NO, NO },
- { "-4|-6", "", "", "" }, "" }
- };
- /*
- * Variable list data space
- */
- #define MAXLIST 64 /* maximum number of variables in list */
- #define LENHOSTNAME 256 /* host name is 256 characters long */
- /*
- * Old CTL_PST defines for version 2.
- */
- #define OLD_CTL_PST_CONFIG 0x80
- #define OLD_CTL_PST_AUTHENABLE 0x40
- #define OLD_CTL_PST_AUTHENTIC 0x20
- #define OLD_CTL_PST_REACH 0x10
- #define OLD_CTL_PST_SANE 0x08
- #define OLD_CTL_PST_DISP 0x04
- #define OLD_CTL_PST_SEL_REJECT 0
- #define OLD_CTL_PST_SEL_SELCAND 1
- #define OLD_CTL_PST_SEL_SYNCCAND 2
- #define OLD_CTL_PST_SEL_SYSPEER 3
- char flash2[] = " .+* "; /* flash decode for version 2 */
- char flash3[] = " x.-+#*o"; /* flash decode for peer status version 3 */
- struct varlist {
- char *name;
- char *value;
- } varlist[MAXLIST] = { { 0, 0 } };
- /*
- * Imported from ntpq.c
- */
- extern int showhostnames;
- extern int rawmode;
- extern struct servent *server_entry;
- extern struct association assoc_cache[];
- extern int numassoc;
- extern u_char pktversion;
- extern struct ctl_var peer_var[];
- /*
- * For quick string comparisons
- */
- #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
- /*
- * checkassocid - return the association ID, checking to see if it is valid
- */
- static int
- checkassocid(
- u_int32 value
- )
- {
- if (value == 0 || value >= 65536) {
- (void) fprintf(stderr, "***Invalid association ID specified\n");
- return 0;
- }
- return (int)value;
- }
- /*
- * strsave - save a string
- * XXX - should be in libntp.a
- */
- static char *
- strsave(
- char *str
- )
- {
- char *cp;
- u_int len;
- len = strlen(str) + 1;
- if ((cp = (char *)malloc(len)) == NULL) {
- (void) fprintf(stderr, "Malloc failed!!\n");
- exit(1);
- }
- memmove(cp, str, len);
- return (cp);
- }
- /*
- * findlistvar - look for the named variable in a list and return if found
- */
- static struct varlist *
- findlistvar(
- struct varlist *list,
- char *name
- )
- {
- register struct varlist *vl;
- for (vl = list; vl < list + MAXLIST && vl->name != 0; vl++)
- if (STREQ(name, vl->name))
- return vl;
- if (vl < list + MAXLIST)
- return vl;
- return (struct varlist *)0;
- }
- /*
- * doaddvlist - add variable(s) to the variable list
- */
- static void
- doaddvlist(
- struct varlist *vlist,
- char *vars
- )
- {
- register struct varlist *vl;
- int len;
- char *name;
- char *value;
- len = strlen(vars);
- while (nextvar(&len, &vars, &name, &value)) {
- vl = findlistvar(vlist, name);
- if (vl == 0) {
- (void) fprintf(stderr, "Variable list full\n");
- return;
- }
- if (vl->name == 0) {
- vl->name = strsave(name);
- } else if (vl->value != 0) {
- free(vl->value);
- vl->value = 0;
- }
- if (value != 0)
- vl->value = strsave(value);
- }
- }
- /*
- * dormvlist - remove variable(s) from the variable list
- */
- static void
- dormvlist(
- struct varlist *vlist,
- char *vars
- )
- {
- register struct varlist *vl;
- int len;
- char *name;
- char *value;
- len = strlen(vars);
- while (nextvar(&len, &vars, &name, &value)) {
- vl = findlistvar(vlist, name);
- if (vl == 0 || vl->name == 0) {
- (void) fprintf(stderr, "Variable `%s' not found\n",
- name);
- } else {
- free((void *)vl->name);
- if (vl->value != 0)
- free(vl->value);
- for ( ; (vl+1) < (varlist+MAXLIST)
- && (vl+1)->name != 0; vl++) {
- vl->name = (vl+1)->name;
- vl->value = (vl+1)->value;
- }
- vl->name = vl->value = 0;
- }
- }
- }
- /*
- * doclearvlist - clear a variable list
- */
- static void
- doclearvlist(
- struct varlist *vlist
- )
- {
- register struct varlist *vl;
- for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
- free((void *)vl->name);
- vl->name = 0;
- if (vl->value != 0) {
- free(vl->value);
- vl->value = 0;
- }
- }
- }
- /*
- * makequerydata - form a data buffer to be included with a query
- */
- static void
- makequerydata(
- struct varlist *vlist,
- int *datalen,
- char *data
- )
- {
- register struct varlist *vl;
- register char *cp, *cpend;
- register int namelen, valuelen;
- register int totallen;
- cp = data;
- cpend = data + *datalen;
- for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
- namelen = strlen(vl->name);
- if (vl->value == 0)
- valuelen = 0;
- else
- valuelen = strlen(vl->value);
- totallen = namelen + valuelen + (valuelen != 0) + (cp != data);
- if (cp + totallen > cpend)
- break;
- if (cp != data)
- *cp++ = ',';
- memmove(cp, vl->name, (unsigned)namelen);
- cp += namelen;
- if (valuelen != 0) {
- *cp++ = '=';
- memmove(cp, vl->value, (unsigned)valuelen);
- cp += valuelen;
- }
- }
- *datalen = cp - data;
- }
- /*
- * doquerylist - send a message including variables in a list
- */
- static int
- doquerylist(
- struct varlist *vlist,
- int op,
- int associd,
- int auth,
- u_short *rstatus,
- int *dsize,
- char **datap
- )
- {
- char data[CTL_MAX_DATA_LEN];
- int datalen;
- datalen = sizeof(data);
- makequerydata(vlist, &datalen, data);
- return doquery(op, associd, auth, datalen, data, rstatus,
- dsize, datap);
- }
- /*
- * doprintvlist - print the variables on a list
- */
- static void
- doprintvlist(
- struct varlist *vlist,
- FILE *fp
- )
- {
- register struct varlist *vl;
- if (vlist->name == 0) {
- (void) fprintf(fp, "No variables on list\n");
- } else {
- for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
- if (vl->value == 0) {
- (void) fprintf(fp, "%s\n", vl->name);
- } else {
- (void) fprintf(fp, "%s=%s\n",
- vl->name, vl->value);
- }
- }
- }
- }
- /*
- * addvars - add variables to the variable list
- */
- /*ARGSUSED*/
- static void
- addvars(
- struct parse *pcmd,
- FILE *fp
- )
- {
- doaddvlist(varlist, pcmd->argval[0].string);
- }
- /*
- * rmvars - remove variables from the variable list
- */
- /*ARGSUSED*/
- static void
- rmvars(
- struct parse *pcmd,
- FILE *fp
- )
- {
- dormvlist(varlist, pcmd->argval[0].string);
- }
- /*
- * clearvars - clear the variable list
- */
- /*ARGSUSED*/
- static void
- clearvars(
- struct parse *pcmd,
- FILE *fp
- )
- {
- doclearvlist(varlist);
- }
- /*
- * showvars - show variables on the variable list
- */
- /*ARGSUSED*/
- static void
- showvars(
- struct parse *pcmd,
- FILE *fp
- )
- {
- doprintvlist(varlist, fp);
- }
- /*
- * dolist - send a request with the given list of variables
- */
- static int
- dolist(
- struct varlist *vlist,
- int associd,
- int op,
- int type,
- FILE *fp
- )
- {
- char *datap;
- int res;
- int dsize;
- u_short rstatus;
- res = doquerylist(vlist, op, associd, 0, &rstatus, &dsize, &datap);
- if (res != 0)
- return 0;
- if (numhosts > 1)
- (void) fprintf(fp, "server=%s ", currenthost);
- if (dsize == 0) {
- if (associd == 0)
- (void) fprintf(fp, "No system%s variables returned\n",
- (type == TYPE_CLOCK) ? " clock" : "");
- else
- (void) fprintf(fp,
- "No information returned for%s association %u\n",
- (type == TYPE_CLOCK) ? " clock" : "", associd);
- return 1;
- }
- (void) fprintf(fp,"assID=%d ",associd);
- printvars(dsize, datap, (int)rstatus, type, fp);
- return 1;
- }
- /*
- * readlist - send a read variables request with the variables on the list
- */
- static void
- readlist(
- struct parse *pcmd,
- FILE *fp
- )
- {
- int associd;
- if (pcmd->nargs == 0) {
- associd = 0;
- } else {
- /* HMS: I think we want the u_int32 target here, not the u_long */
- if (pcmd->argval[0].uval == 0)
- associd = 0;
- else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
- return;
- }
- (void) dolist(varlist, associd, CTL_OP_READVAR,
- (associd == 0) ? TYPE_SYS : TYPE_PEER, fp);
- }
- /*
- * writelist - send a write variables request with the variables on the list
- */
- static void
- writelist(
- struct parse *pcmd,
- FILE *fp
- )
- {
- char *datap;
- int res;
- int associd;
- int dsize;
- u_short rstatus;
- if (pcmd->nargs == 0) {
- associd = 0;
- } else {
- /* HMS: Do we really want uval here? */
- if (pcmd->argval[0].uval == 0)
- associd = 0;
- else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
- return;
- }
- res = doquerylist(varlist, CTL_OP_WRITEVAR, associd, 1, &rstatus,
- &dsize, &datap);
- if (res != 0)
- return;
- if (numhosts > 1)
- (void) fprintf(fp, "server=%s ", currenthost);
- if (dsize == 0)
- (void) fprintf(fp, "done! (no data returned)\n");
- else {
- (void) fprintf(fp,"assID=%d ",associd);
- printvars(dsize, datap, (int)rstatus,
- (associd != 0) ? TYPE_PEER : TYPE_SYS, fp);
- }
- return;
- }
- /*
- * readvar - send a read variables request with the specified variables
- */
- static void
- readvar(
- struct parse *pcmd,
- FILE *fp
- )
- {
- int associd;
- struct varlist tmplist[MAXLIST];
- /* HMS: uval? */
- if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
- associd = 0;
- else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
- return;
- memset((char *)tmplist, 0, sizeof(tmplist));
- if (pcmd->nargs >= 2)
- doaddvlist(tmplist, pcmd->argval[1].string);
- (void) dolist(tmplist, associd, CTL_OP_READVAR,
- (associd == 0) ? TYPE_SYS : TYPE_PEER, fp);
- doclearvlist(tmplist);
- }
- /*
- * writevar - send a write variables request with the specified variables
- */
- static void
- writevar(
- struct parse *pcmd,
- FILE *fp
- )
- {
- char *datap;
- int res;
- int associd;
- int dsize;
- u_short rstatus;
- struct varlist tmplist[MAXLIST];
- /* HMS: uval? */
- if (pcmd->argval[0].uval == 0)
- associd = 0;
- else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
- return;
- memset((char *)tmplist, 0, sizeof(tmplist));
- doaddvlist(tmplist, pcmd->argval[1].string);
- res = doquerylist(tmplist, CTL_OP_WRITEVAR, associd, 1, &rstatus,
- &dsize, &datap);
- doclearvlist(tmplist);
- if (res != 0)
- return;
- if (numhosts > 1)
- (void) fprintf(fp, "server=%s ", currenthost);
- if (dsize == 0)
- (void) fprintf(fp, "done! (no data returned)\n");
- else {
- (void) fprintf(fp,"assID=%d ",associd);
- printvars(dsize, datap, (int)rstatus,
- (associd != 0) ? TYPE_PEER : TYPE_SYS, fp);
- }
- return;
- }
- /*
- * clocklist - send a clock variables request with the variables on the list
- */
- static void
- clocklist(
- struct parse *pcmd,
- FILE *fp
- )
- {
- int associd;
- /* HMS: uval? */
- if (pcmd->nargs == 0) {
- associd = 0;
- } else {
- if (pcmd->argval[0].uval == 0)
- associd = 0;
- else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
- return;
- }
- (void) dolist(varlist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
- }
- /*
- * clockvar - send a clock variables request with the specified variables
- */
- static void
- clockvar(
- struct parse *pcmd,
- FILE *fp
- )
- {
- int associd;
- struct varlist tmplist[MAXLIST];
- /* HMS: uval? */
- if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
- associd = 0;
- else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
- return;
- memset((char *)tmplist, 0, sizeof(tmplist));
- if (pcmd->nargs >= 2)
- doaddvlist(tmplist, pcmd->argval[1].string);
- (void) dolist(tmplist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
- doclearvlist(tmplist);
- }
- /*
- * findassidrange - verify a range of association ID's
- */
- static int
- findassidrange(
- u_int32 assid1,
- u_int32 assid2,
- int *from,
- int *to
- )
- {
- register int i;
- int f, t;
- if (assid1 == 0 || assid1 > 65535) {
- (void) fprintf(stderr,
- "***Invalid association ID %lu specified\n", (u_long)assid1);
- return 0;
- }
- if (assid2 == 0 || assid2 > 65535) {
- (void) fprintf(stderr,
- "***Invalid association ID %lu specified\n", (u_long)assid2);
- return 0;
- }
- f = t = -1;
- for (i = 0; i < numassoc; i++) {
- if (assoc_cache[i].assid == assid1) {
- f = i;
- if (t != -1)
- break;
- }
- if (assoc_cache[i].assid == assid2) {
- t = i;
- if (f != -1)
- break;
- }
- }
- if (f == -1 || t == -1) {
- (void) fprintf(stderr,
- "***Association ID %lu not found in list\n",
- (f == -1) ? (u_long)assid1 : (u_long)assid2);
- return 0;
- }
- if (f < t) {
- *from = f;
- *to = t;
- } else {
- *from = t;
- *to = f;
- }
- return 1;
- }
- /*
- * mreadlist - send a read variables request for multiple associations
- */
- static void
- mreadlist(
- struct parse *pcmd,
- FILE *fp
- )
- {
- int i;
- int from;
- int to;
- /* HMS: uval? */
- if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
- &from, &to))
- return;
- for (i = from; i <= to; i++) {
- if (i != from)
- (void) fprintf(fp, "\n");
- if (!dolist(varlist, (int)assoc_cache[i].assid,
- CTL_OP_READVAR, TYPE_PEER, fp))
- return;
- }
- return;
- }
- /*
- * mreadvar - send a read variables request for multiple associations
- */
- static void
- mreadvar(
- struct parse *pcmd,
- FILE *fp
- )
- {
- int i;
- int from;
- int to;
- struct varlist tmplist[MAXLIST];
- /* HMS: uval? */
- if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
- &from, &to))
- return;
- memset((char *)tmplist, 0, sizeof(tmplist));
- if (pcmd->nargs >= 3)
- doaddvlist(tmplist, pcmd->argval[2].string);
- for (i = from; i <= to; i++) {
- if (i != from)
- (void) fprintf(fp, "\n");
- if (!dolist(varlist, (int)assoc_cache[i].assid,
- CTL_OP_READVAR, TYPE_PEER, fp))
- break;
- }
- doclearvlist(tmplist);
- return;
- }
- /*
- * dogetassoc - query the host for its list of associations
- */
- static int
- dogetassoc(
- FILE *fp
- )
- {
- char *datap;
- int res;
- int dsize;
- u_short rstatus;
- res = doquery(CTL_OP_READSTAT, 0, 0, 0, (char *)0, &rstatus,
- &dsize, &datap);
- if (res != 0)
- return 0;
- if (dsize == 0) {
- if (numhosts > 1)
- (void) fprintf(fp, "server=%s ", currenthost);
- (void) fprintf(fp, "No association ID's returned\n");
- return 0;
- }
- if (dsize & 0x3) {
- if (numhosts > 1)
- (void) fprintf(stderr, "server=%s ", currenthost);
- (void) fprintf(stderr,
- "***Server returned %d octets, should be multiple of 4\n",
- dsize);
- return 0;
- }
- numassoc = 0;
- while (dsize > 0) {
- assoc_cache[numassoc].assid = ntohs(*((u_short *)datap));
- datap += sizeof(u_short);
- assoc_cache[numassoc].status = ntohs(*((u_short *)datap));
- datap += sizeof(u_short);
- if (++numassoc >= MAXASSOC)
- break;
- dsize -= sizeof(u_short) + sizeof(u_short);
- }
- sortassoc();
- return 1;
- }
- /*
- * printassoc - print the current list of associations
- */
- static void
- printassoc(
- int showall,
- FILE *fp
- )
- {
- register char *bp;
- int i;
- u_char statval;
- int event;
- u_long event_count;
- const char *conf;
- const char *reach;
- const char *auth;
- const char *condition = "";
- const char *last_event;
- const char *cnt;
- char buf[128];
- if (numassoc == 0) {
- (void) fprintf(fp, "No association ID's in list\n");
- return;
- }
- /*
- * Output a header
- */
- (void) fprintf(fp,
- "\nind assID status conf reach auth condition last_event cnt\n");
- (void) fprintf(fp,
- "===========================================================\n");
- for (i = 0; i < numassoc; i++) {
- statval = (u_char) CTL_PEER_STATVAL(assoc_cache[i].status);
- if (!showall && !(statval & (CTL_PST_CONFIG|CTL_PST_REACH)))
- continue;
- event = CTL_PEER_EVENT(assoc_cache[i].status);
- event_count = CTL_PEER_NEVNT(assoc_cache[i].status);
- if (statval & CTL_PST_CONFIG)
- conf = "yes";
- else
- conf = "no";
- if (statval & CTL_PST_REACH || 1) {
- reach = "yes";
- if (statval & CTL_PST_AUTHENABLE) {
- if (statval & CTL_PST_AUTHENTIC)
- auth = "ok ";
- else
- auth = "bad";
- } else
- auth = "none";
- if (pktversion > NTP_OLDVERSION)
- switch (statval & 0x7) {
- case CTL_PST_SEL_REJECT:
- condition = "reject";
- break;
- case CTL_PST_SEL_SANE:
- condition = "falsetick";
- break;
- case CTL_PST_SEL_CORRECT:
- condition = "excess";
- break;
- case CTL_PST_SEL_SELCAND:
- condition = "outlyer";
- break;
- case CTL_PST_SEL_SYNCCAND:
- condition = "candidat";
- break;
- case CTL_PST_SEL_DISTSYSPEER:
- condition = "selected";
- break;
- case CTL_PST_SEL_SYSPEER:
- condition = "sys.peer";
- break;
- case CTL_PST_SEL_PPS:
- condition = "pps.peer";
- break;
- }
- else
- switch (statval & 0x3) {
- case OLD_CTL_PST_SEL_REJECT:
- if (!(statval & OLD_CTL_PST_SANE))
- condition = "insane";
- else if (!(statval & OLD_CTL_PST_DISP))
- condition = "hi_disp";
- else
- condition = "";
- break;
- case OLD_CTL_PST_SEL_SELCAND:
- condition = "sel_cand";
- break;
- case OLD_CTL_PST_SEL_SYNCCAND:
- condition = "sync_cand";
- break;
- case OLD_CTL_PST_SEL_SYSPEER:
- condition = "sys_peer";
- break;
- }
- } else {
- reach = "no";
- auth = condition = "";
- }
- switch (PEER_EVENT|event) {
- case EVNT_PEERIPERR:
- last_event = "IP error";
- break;
- case EVNT_PEERAUTH:
- last_event = "auth fail";
- break;
- case EVNT_UNREACH:
- last_event = "lost reach";
- break;
- case EVNT_REACH:
- last_event = "reachable";
- break;
- case EVNT_PEERCLOCK:
- last_event = "clock expt";
- break;
- #if 0
- case EVNT_PEERSTRAT:
- last_event = "stratum chg";
- break;
- #endif
- default:
- last_event = "";
- break;
- }
- if (event_count != 0)
- cnt = uinttoa(event_count);
- else
- cnt = "";
- (void) sprintf(buf,
- "%3d %5u %04x %3.3s %4s %4.4s %9.9s %11s %2s",
- i+1, assoc_cache[i].assid, assoc_cache[i].status,
- conf, reach, auth, condition, last_event, cnt);
- bp = &buf[strlen(buf)];
- while (bp > buf && *(bp-1) == ' ')
- *(--bp) = '\0';
- (void) fprintf(fp, "%s\n", buf);
- }
- }
- /*
- * associations - get, record and print a list of associations
- */
- /*ARGSUSED*/
- static void
- associations(
- struct parse *pcmd,
- FILE *fp
- )
- {
- if (dogetassoc(fp))
- printassoc(0, fp);
- }
- /*
- * lassociations - get, record and print a long list of associations
- */
- /*ARGSUSED*/
- static void
- lassociations(
- struct parse *pcmd,
- FILE *fp
- )
- {
- if (dogetassoc(fp))
- printassoc(1, fp);
- }
- /*
- * passociations - print the association list
- */
- /*ARGSUSED*/
- static void
- passociations(
- struct parse *pcmd,
- FILE *fp
- )
- {
- printassoc(0, fp);
- }
- /*
- * lpassociations - print the long association list
- */
- /*ARGSUSED*/
- static void
- lpassociations(
- struct parse *pcmd,
- FILE *fp
- )
- {
- printassoc(1, fp);
- }
- #ifdef UNUSED
- /*
- * radiostatus - print the radio status returned by the server
- */
- /*ARGSUSED*/
- static void
- radiostatus(
- struct parse *pcmd,
- FILE *fp
- )
- {
- char *datap;
- int res;
- int dsize;
- u_short rstatus;
- res = doquery(CTL_OP_READCLOCK, 0, 0, 0, (char *)0, &rstatus,
- &dsize, &datap);
- if (res != 0)
- return;
- if (numhosts > 1)
- (void) fprintf(fp, "server=%s ", currenthost);
- if (dsize == 0) {
- (void) fprintf(fp, "No radio status string returned\n");
- return;
- }
- asciize(dsize, datap, fp);
- }
- #endif /* UNUSED */
- /*
- * pstatus - print peer status returned by the server
- */
- static void
- pstatus(
- struct parse *pcmd,
- FILE *fp
- )
- {
- char *datap;
- int res;
- int 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, (char *)0, &rstatus,
- &dsize, &datap);
- if (res != 0)
- return;
- if (numhosts > 1)
- (void) fprintf(fp, "server=%s ", currenthost);
- if (dsize == 0) {
- (void) fprintf(fp,
- "No information returned for association %u\n",
- associd);
- return;
- }
- (void) fprintf(fp,"assID=%d ",associd);
- printvars(dsize, datap, (int)rstatus, TYPE_PEER, fp);
- }
- /*
- * when - print how long its been since his last packet arrived
- */
- static long
- when(
- l_fp *ts,
- l_fp *rec,
- l_fp *reftime
- )
- {
- l_fp *lasttime;
- if (rec->l_ui != 0)
- lasttime = rec;
- else if (reftime->l_ui != 0)
- lasttime = reftime;
- else
- return 0;
- return (ts->l_ui - lasttime->l_ui);
- }
- /*
- * Pretty-print an interval into the given buffer, in a human-friendly format.
- */
- static char *
- prettyinterval(
- char *buf,
- long diff
- )
- {
- if (diff <= 0) {
- buf[0] = '-';
- buf[1] = 0;
- return buf;
- }
- if (diff <= 2048) {
- (void) sprintf(buf, "%ld", (long int)diff);
- return buf;
- }
- diff = (diff + 29) / 60;
- if (diff <= 300) {
- (void) sprintf(buf, "%ldm", (long int)diff);
- return buf;
- }
- diff = (diff + 29) / 60;
- if (diff <= 96) {
- (void) sprintf(buf, "%ldh", (long int)diff);
- return buf;
- }
- diff = (diff + 11) / 24;
- (void) sprintf(buf, "%ldd", (long int)diff);
- return buf;
- }
- static char
- decodeaddrtype(
- struct sockaddr_storage *sock
- )
- {
- char ch = '-';
- u_int32 dummy;
- struct sockaddr_in6 *sin6;
- switch(sock->ss_family) {
- case AF_INET:
- dummy = ((struct sockaddr_in *)sock)->sin_addr.s_addr;
- dummy = ntohl(dummy);
- ch = (char)(((dummy&0xf0000000)==0xe0000000) ? 'm' :
- ((dummy&0x000000ff)==0x000000ff) ? 'b' :
- ((dummy&0xffffffff)==0x7f000001) ? 'l' :
- ((dummy&0xffffffe0)==0x00000000) ? '-' :
- 'u');
- break;
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *)sock;
- if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
- ch = 'm';
- else
- ch = 'u';
- break;
- default:
- ch = '-';
- break;
- }
- return ch;
- }
- /*
- * A list of variables required by the peers command
- */
- struct varlist opeervarlist[] = {
- { "srcadr", 0 }, /* 0 */
- { "dstadr", 0 }, /* 1 */
- { "stratum", 0 }, /* 2 */
- { "hpoll", 0 }, /* 3 */
- { "ppoll", 0 }, /* 4 */
- { "reach", 0 }, /* 5 */
- { "delay", 0 }, /* 6 */
- { "offset", 0 }, /* 7 */
- { "jitter", 0 }, /* 8 */
- { "dispersion", 0 }, /* 9 */
- { "rec", 0 }, /* 10 */
- { "reftime", 0 }, /* 11 */
- { "srcport", 0 }, /* 12 */
- { 0, 0 }
- };
- struct varlist peervarlist[] = {
- { "srcadr", 0 }, /* 0 */
- { "refid", 0 }, /* 1 */
- { "stratum", 0 }, /* 2 */
- { "hpoll", 0 }, /* 3 */
- { "ppoll", 0 }, /* 4 */
- { "reach", 0 }, /* 5 */
- { "delay", 0 }, /* 6 */
- { "offset", 0 }, /* 7 */
- { "jitter", 0 }, /* 8 */
- { "dispersion", 0 }, /* 9 */
- { "rec", 0 }, /* 10 */
- { "reftime", 0 }, /* 11 */
- { "srcport", 0 }, /* 12 */
- { 0, 0 }
- };
- #define HAVE_SRCADR 0
- #define HAVE_DSTADR 1
- #define HAVE_REFID 1
- #define HAVE_STRATUM 2
- #define HAVE_HPOLL 3
- #define HAVE_PPOLL 4
- #define HAVE_REACH 5
- #define HAVE_DELAY 6
- #define HAVE_OFFSET 7
- #define HAVE_JITTER 8
- #define HAVE_DISPERSION 9
- #define HAVE_REC 10
- #define HAVE_REFTIME 11
- #define HAVE_SRCPORT 12
- #define MAXHAVE 13
- /*
- * Decode an incoming data buffer and print a line in the peer list
- */
- static int
- doprintpeers(
- struct varlist *pvl,
- int associd,
- int rstatus,
- int datalen,
- char *data,
- FILE *fp,
- int af
- )
- {
- char *name;
- char *value = NULL;
- int i;
- int c;
- struct sockaddr_storage srcadr;
- struct sockaddr_storage dstadr;
- u_long srcport = 0;
- char *dstadr_refid = "0.0.0.0";
- u_long stratum = 0;
- long ppoll = 0;
- long hpoll = 0;
- u_long reach = 0;
- l_fp estoffset;
- l_fp estdelay;
- l_fp estjitter;
- l_fp estdisp;
- l_fp reftime;
- l_fp rec;
- l_fp ts;
- u_char havevar[MAXHAVE];
- u_long poll_sec;
- char type = '?';
- char refid_string[10];
- char whenbuf[8], pollbuf[8];
- char clock_name[LENHOSTNAME];
- memset((char *)havevar, 0, sizeof(havevar));
- get_systime(&ts);
-
- memset((char *)&srcadr, 0, sizeof(struct sockaddr_storage));
- memset((char *)&dstadr, 0, sizeof(struct sockaddr_storage));
- /* Initialize by zeroing out estimate variables */
- memset((char *)&estoffset, 0, sizeof(l_fp));
- memset((char *)&estdelay, 0, sizeof(l_fp));
- memset((char *)&estjitter, 0, sizeof(l_fp));
- memset((char *)&estdisp, 0, sizeof(l_fp));
- while (nextvar(&datalen, &data, &name, &value)) {
- struct sockaddr_storage dum_store;
- i = findvar(name, peer_var, 1);
- if (i == 0)
- continue; /* don't know this one */
- switch (i) {
- case CP_SRCADR:
- if (decodenetnum(value, &srcadr))
- havevar[HAVE_SRCADR] = 1;
- break;
- case CP_DSTADR:
- if (decodenetnum(value, &dum_store))
- type = decodeaddrtype(&dum_store);
- if (pvl == opeervarlist) {
- if (decodenetnum(value, &dstadr)) {
- havevar[HAVE_DSTADR] = 1;
- dstadr_refid = stoa(&dstadr);
- }
- }
- break;
- case CP_REFID:
- if (pvl == peervarlist) {
- havevar[HAVE_REFID] = 1;
- if (*value == '\0') {
- dstadr_refid = "0.0.0.0";
- } else if ((int)strlen(value) <= 4) {
- refid_string[0] = '.';
- (void) strcpy(&refid_string[1], value);
- i = strlen(refid_string);
- refid_string[i] = '.';
- refid_string[i+1] = '\0';
- dstadr_refid = refid_string;
- } else if (decodenetnum(value, &dstadr)) {
- if (SOCKNUL(&dstadr))
- dstadr_refid = "0.0.0.0";
- else if ((dstadr.ss_family == AF_INET)
- && ISREFCLOCKADR(&dstadr))
- dstadr_refid =
- refnumtoa(&dstadr);
- else
- dstadr_refid =
- stoa(&dstadr);
- } else {
- havevar[HAVE_REFID] = 0;
- }
- }
- break;
- case CP_STRATUM:
- if (decodeuint(value, &stratum))
- havevar[HAVE_STRATUM] = 1;
- break;
- case CP_HPOLL:
- if (decodeint(value, &hpoll)) {
- havevar[HAVE_HPOLL] = 1;
- if (hpoll < 0)
- hpoll = NTP_MINPOLL;
- }
- break;
- case CP_PPOLL:
- if (decodeint(value, &ppoll)) {
- havevar[HAVE_PPOLL] = 1;
- if (ppoll < 0)
- ppoll = NTP_MINPOLL;
- }
- break;
- case CP_REACH:
- if (decodeuint(value, &reach))
- havevar[HAVE_REACH] = 1;
- break;
- case CP_DELAY:
- if (decodetime(value, &estdelay))
- havevar[HAVE_DELAY] = 1;
- break;
- case CP_OFFSET:
- if (decodetime(value, &estoffset))
- havevar[HAVE_OFFSET] = 1;
- break;
- case CP_JITTER:
- if (pvl == peervarlist)
- if (decodetime(value, &estjitter))
- havevar[HAVE_JITTER] = 1;
- break;
- case CP_DISPERSION:
- if (decodetime(value, &estdisp))
- havevar[HAVE_DISPERSION] = 1;
- break;
- case CP_REC:
- if (decodets(value, &rec))
- havevar[HAVE_REC] = 1;
- break;
- case CP_SRCPORT:
- if (decodeuint(value, &srcport))
- havevar[HAVE_SRCPORT] = 1;
- break;
- case CP_REFTIME:
- havevar[HAVE_REFTIME] = 1;
- if (!decodets(value, &reftime))
- L_CLR(&reftime);
- break;
- default:
- break;
- }
- }
- /*
- * Check to see if the srcport is NTP's port. If not this probably
- * isn't a valid peer association.
- */
- if (havevar[HAVE_SRCPORT] && srcport != NTP_PORT)
- return (1);
- /*
- * Got everything, format the line
- */
- poll_sec = 1<<max(min3(ppoll, hpoll, NTP_MAXPOLL), NTP_MINPOLL);
- if (pktversion > NTP_OLDVERSION)
- c = flash3[CTL_PEER_STATVAL(rstatus) & 0x7];
- else
- c = flash2[CTL_PEER_STATVAL(rstatus) & 0x3];
- if (numhosts > 1)
- (void) fprintf(fp, "%-*s ", maxhostlen, currenthost);
- if (af == 0 || srcadr.ss_family == af){
- strcpy(clock_name, nntohost(&srcadr));
-
- (void) fprintf(fp,
- "%c%-15.15s %-15.15s %2ld %c %4.4s %4.4s %3lo %7.7s %8.7s %7.7s\n",
- c, clock_name, dstadr_refid, stratum, type,
- prettyinterval(whenbuf, when(&ts, &rec, &reftime)),
- prettyinterval(pollbuf, (int)poll_sec), reach,
- lfptoms(&estdelay, 3), lfptoms(&estoffset, 3),
- havevar[HAVE_JITTER] ? lfptoms(&estjitter, 3) :
- lfptoms(&estdisp, 3));
- return (1);
- }
- else
- return(1);
- }
- #undef HAVE_SRCADR
- #undef HAVE_DSTADR
- #undef HAVE_STRATUM
- #undef HAVE_PPOLL
- #undef HAVE_HPOLL
- #undef HAVE_REACH
- #undef HAVE_ESTDELAY
- #undef HAVE_ESTOFFSET
- #undef HAVE_JITTER
- #undef HAVE_ESTDISP
- #undef HAVE_REFID
- #undef HAVE_REC
- #undef HAVE_SRCPORT
- #undef HAVE_REFTIME
- #undef MAXHAVE
- /*
- * dogetpeers - given an association ID, read and print the spreadsheet
- * peer variables.
- */
- static int
- dogetpeers(
- struct varlist *pvl,
- int associd,
- FILE *fp,
- int af
- )
- {
- char *datap;
- int res;
- int dsize;
- u_short rstatus;
- #ifdef notdef
- res = doquerylist(pvl, CTL_OP_READVAR, associd, 0, &rstatus,
- &dsize, &datap);
- #else
- /*
- * Damn fuzzballs
- */
- res = doquery(CTL_OP_READVAR, associd, 0, 0, (char *)0, &rstatus,
- &dsize, &datap);
- #endif
- if (res != 0)
- return 0;
- if (dsize == 0) {
- if (numhosts > 1)
- (void) fprintf(stderr, "server=%s ", currenthost);
- (void) fprintf(stderr,
- "***No information returned for association %d\n",
- associd);
- return 0;
- }
- return doprintpeers(pvl, associd, (int)rstatus, dsize, datap, fp, af);
- }
- /*
- * peers - print a peer spreadsheet
- */
- static void
- dopeers(
- int showall,
- FILE *fp,
- int af
- )
- {
- register int i;
- char fullname[LENHOSTNAME];
- struct sockaddr_storage netnum;
- if (!dogetassoc(fp))
- return;
- for (i = 0; i < numhosts; ++i) {
- if (getnetnum(chosts[i], &netnum, fullname, af))
- if ((int)strlen(fullname) > maxhostlen)
- maxhostlen = strlen(fullname);
- }
- if (numhosts > 1)
- (void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "server");
- (void) fprintf(fp,
- " remote refid st t when poll reach delay offset jitter\n");
- if (numhosts > 1)
- for (i = 0; i <= maxhostlen; ++i)
- (void) fprintf(fp, "=");
- (void) fprintf(fp,
- "==============================================================================\n");
- for (i = 0; i < numassoc; i++) {
- if (!showall &&
- !(CTL_PEER_STATVAL(assoc_cache[i].status)
- & (CTL_PST_CONFIG|CTL_PST_REACH)))
- continue;
- if (!dogetpeers(peervarlist, (int)assoc_cache[i].assid, fp, af)) {
- return;
- }
- }
- return;
- }
- /*
- * peers - print a peer spreadsheet
- */
- /*ARGSUSED*/
- static void
- peers(
- struct parse *pcmd,
- FILE *fp
- )
- {
- int af = 0;
- if (pcmd->nargs == 1) {
- if (pcmd->argval->ival == 6)
- af = AF_INET6;
- else
- af = AF_INET;
- }
- dopeers(0, fp, af);
- }
- /*
- * lpeers - print a peer spreadsheet including all fuzzball peers
- */
- /*ARGSUSED*/
- static void
- lpeers(
- struct parse *pcmd,
- FILE *fp
- )
- {
- int af = 0;
- if (pcmd->nargs == 1) {
- if (pcmd->argval->ival == 6)
- af = AF_INET6;
- else
- af = AF_INET;
- }
- dopeers(1, fp, af);
- }
- /*
- * opeers - print a peer spreadsheet
- */
- static void
- doopeers(
- int showall,
- FILE *fp,
- int af
- )
- {
- register int i;
- char fullname[LENHOSTNAME];
- struct sockaddr_storage netnum;
- if (!dogetassoc(fp))
- return;
- for (i = 0; i < numhosts; ++i) {
- if (getnetnum(chosts[i], &netnum, fullname, af))
- if ((int)strlen(fullname) > maxhostlen)
- maxhostlen = strlen(fullname);
- }
- if (numhosts > 1)
- (void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "server");
- (void) fprintf(fp,
- " remote local st t when poll reach delay offset disp\n");
- if (numhosts > 1)
- for (i = 0; i <= maxhostlen; ++i)
- (void) fprintf(fp, "=");
- (void) fprintf(fp,
- "==============================================================================\n");
- for (i = 0; i < numassoc; i++) {
- if (!showall &&
- !(CTL_PEER_STATVAL(assoc_cache[i].status)
- & (CTL_PST_CONFIG|CTL_PST_REACH)))
- continue;
- if (!dogetpeers(opeervarlist, (int)assoc_cache[i].assid, fp, af)) {
- return;
- }
- }
- return;
- }
- /*
- * opeers - print a peer spreadsheet the old way
- */
- /*ARGSUSED*/
- static void
- opeers(
- struct parse *pcmd,
- FILE *fp
- )
- {
- int af = 0;
- if (pcmd->nargs == 1) {
- if (pcmd->argval->ival == 6)
- af = AF_INET6;
- else
- af = AF_INET;
- }
- doopeers(0, fp, af);
- }
- /*
- * lopeers - print a peer spreadsheet including all fuzzball peers
- */
- /*ARGSUSED*/
- static void
- lopeers(
- struct parse *pcmd,
- FILE *fp
- )
- {
- int af = 0;
- if (pcmd->nargs == 1) {
- if (pcmd->argval->ival == 6)
- af = AF_INET6;
- else
- af = AF_INET;
- }
- doopeers(1, fp, af);
- }