diff options
author | Ollivier Robert <roberto@FreeBSD.org> | 2013-12-04 21:33:17 +0000 |
---|---|---|
committer | Ollivier Robert <roberto@FreeBSD.org> | 2013-12-04 21:33:17 +0000 |
commit | 2b45e011ca352ce509bc83ae148230aeee0c7e0d (patch) | |
tree | a618007bb41d13153794a598e3d904ace2976324 /ntpq/ntpq-subs.c | |
parent | 9b5bd0a264b0a21eefac2b929b574c73bd601507 (diff) | |
download | src-5592cd9e3002995d676cc186b0362f891fead9fc.tar.gz src-5592cd9e3002995d676cc186b0362f891fead9fc.zip |
Virgin import of ntpd 4.2.6p5.vendor/ntp/4.2.6p5
When the series of commits is complete, things like
https://cert.litnet.lt/en/docs/ntp-distributed-reflection-dos-attacks
should be fixed.
PR: bin/148836 (except that we import a newer version)
Asked by: Too many
MFC after: 2 weeks
Diffstat (limited to 'ntpq/ntpq-subs.c')
-rw-r--r-- | ntpq/ntpq-subs.c | 881 |
1 files changed, 565 insertions, 316 deletions
diff --git a/ntpq/ntpq-subs.c b/ntpq/ntpq-subs.c index 07f25cecefda..ba235f1575e9 100644 --- a/ntpq/ntpq-subs.c +++ b/ntpq/ntpq-subs.c @@ -7,68 +7,77 @@ #include <sys/types.h> #include <sys/time.h> -#include "ntpq.h" #include "ntp_stdlib.h" +#include "ntpq.h" +#include "ntpq-opts.h" extern char * chosts[]; extern char currenthost[]; +extern int currenthostisnum; 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 *)); +static associd_t checkassocid (u_int32); +static struct varlist *findlistvar (struct varlist *, char *); +static void doaddvlist (struct varlist *, const char *); +static void dormvlist (struct varlist *, const char *); +static void doclearvlist (struct varlist *); +static void makequerydata (struct varlist *, int *, char *); +static int doquerylist (struct varlist *, int, associd_t, int, + u_short *, int *, const char **); +static void doprintvlist (struct varlist *, FILE *); +static void addvars (struct parse *, FILE *); +static void rmvars (struct parse *, FILE *); +static void clearvars (struct parse *, FILE *); +static void showvars (struct parse *, FILE *); +static int dolist (struct varlist *, associd_t, int, int, + FILE *); +static void readlist (struct parse *, FILE *); +static void writelist (struct parse *, FILE *); +static void readvar (struct parse *, FILE *); +static void writevar (struct parse *, FILE *); +static void clocklist (struct parse *, FILE *); +static void clockvar (struct parse *, FILE *); +static int findassidrange (u_int32, u_int32, int *, int *); +static void mreadlist (struct parse *, FILE *); +static void mreadvar (struct parse *, FILE *); +static int dogetassoc (FILE *); +static void printassoc (int, FILE *); +static void associations (struct parse *, FILE *); +static void lassociations (struct parse *, FILE *); +static void passociations (struct parse *, FILE *); +static void lpassociations (struct parse *, FILE *); #ifdef UNUSED -static void radiostatus P((struct parse *, FILE *)); +static void radiostatus (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 *)); +static void pstatus (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); +static int dogetpeers (struct varlist *, associd_t, FILE *, int); +static void dopeers (int, FILE *, int); +static void peers (struct parse *, FILE *); +static void lpeers (struct parse *, FILE *); +static void doopeers (int, FILE *, int); +static void opeers (struct parse *, FILE *); +static void lopeers (struct parse *, FILE *); +static void config (struct parse *, FILE *); +static void saveconfig (struct parse *, FILE *); +static void config_from_file(struct parse *, FILE *); /* * Commands we understand. Ntpdc imports this. */ struct xcmd opcmds[] = { + { "saveconfig", saveconfig, { NTP_STR, NO, NO, NO }, + { "filename", "", "", ""}, + "save ntpd configuration to file, . for current config file"}, { "associations", associations, { NO, NO, NO, NO }, { "", "", "", "" }, "print list of association ID's and statuses for the server's peers" }, @@ -150,6 +159,12 @@ struct xcmd opcmds[] = { { "lopeers", lopeers, { OPT|IP_VERSION, NO, NO, NO }, { "-4|-6", "", "", "" }, "obtain and print a list of all peers and clients showing dstadr [IP version]" }, + { ":config", config, { NTP_STR, NO, NO, NO }, + { "<configuration command line>", "", "", "" }, + "send a remote configuration command to ntpd" }, + { "config-from-file", config_from_file, { NTP_STR, NO, NO, NO }, + { "<configuration filename>", "", "", "" }, + "configure ntpd using the configuration filename" }, { 0, 0, { NO, NO, NO, NO }, { "-4|-6", "", "", "" }, "" } }; @@ -158,30 +173,31 @@ struct xcmd opcmds[] = { /* * Variable list data space */ +#define MAXLINE 512 /* maximum length of a line */ #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_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_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 } }; +} g_varlist[MAXLIST] = { { 0, 0 } }; /* * Imported from ntpq.c @@ -203,39 +219,24 @@ extern struct ctl_var peer_var[]; /* * checkassocid - return the association ID, checking to see if it is valid */ -static int +static associd_t checkassocid( u_int32 value ) { - if (value == 0 || value >= 65536) { - (void) fprintf(stderr, "***Invalid association ID specified\n"); + associd_t associd; + u_long ulvalue; + + associd = (associd_t)value; + if (0 == associd || value != associd) { + ulvalue = value; + fprintf(stderr, + "***Invalid association ID %lu specified\n", + ulvalue); 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); + return associd; } @@ -265,7 +266,7 @@ findlistvar( static void doaddvlist( struct varlist *vlist, - char *vars + const char *vars ) { register struct varlist *vl; @@ -282,14 +283,14 @@ doaddvlist( } if (vl->name == 0) { - vl->name = strsave(name); + vl->name = estrdup(name); } else if (vl->value != 0) { free(vl->value); vl->value = 0; } if (value != 0) - vl->value = strsave(value); + vl->value = estrdup(value); } } @@ -300,7 +301,7 @@ doaddvlist( static void dormvlist( struct varlist *vlist, - char *vars + const char *vars ) { register struct varlist *vl; @@ -318,7 +319,7 @@ dormvlist( free((void *)vl->name); if (vl->value != 0) free(vl->value); - for ( ; (vl+1) < (varlist+MAXLIST) + for ( ; (vl+1) < (g_varlist + MAXLIST) && (vl+1)->name != 0; vl++) { vl->name = (vl+1)->name; vl->value = (vl+1)->value; @@ -399,11 +400,11 @@ static int doquerylist( struct varlist *vlist, int op, - int associd, + associd_t associd, int auth, u_short *rstatus, int *dsize, - char **datap + const char **datap ) { char data[CTL_MAX_DATA_LEN]; @@ -442,7 +443,6 @@ doprintvlist( } } - /* * addvars - add variables to the variable list */ @@ -453,7 +453,7 @@ addvars( FILE *fp ) { - doaddvlist(varlist, pcmd->argval[0].string); + doaddvlist(g_varlist, pcmd->argval[0].string); } @@ -467,7 +467,7 @@ rmvars( FILE *fp ) { - dormvlist(varlist, pcmd->argval[0].string); + dormvlist(g_varlist, pcmd->argval[0].string); } @@ -481,7 +481,7 @@ clearvars( FILE *fp ) { - doclearvlist(varlist); + doclearvlist(g_varlist); } @@ -495,7 +495,7 @@ showvars( FILE *fp ) { - doprintvlist(varlist, fp); + doprintvlist(g_varlist, fp); } @@ -505,16 +505,26 @@ showvars( static int dolist( struct varlist *vlist, - int associd, + associd_t associd, int op, int type, FILE *fp ) { - char *datap; + const char *datap; int res; int dsize; u_short rstatus; + int quiet; + + /* + * if we're asking for specific variables don't include the + * status header line in the output. + */ + if (old_rv) + quiet = 0; + else + quiet = (vlist->name != NULL); res = doquerylist(vlist, op, associd, 0, &rstatus, &dsize, &datap); @@ -534,8 +544,9 @@ dolist( return 1; } - (void) fprintf(fp,"assID=%d ",associd); - printvars(dsize, datap, (int)rstatus, type, fp); + if (!quiet) + fprintf(fp,"associd=%d ",associd); + printvars(dsize, datap, (int)rstatus, type, quiet, fp); return 1; } @@ -549,7 +560,8 @@ readlist( FILE *fp ) { - int associd; + associd_t associd; + int type; if (pcmd->nargs == 0) { associd = 0; @@ -561,8 +573,10 @@ readlist( return; } - (void) dolist(varlist, associd, CTL_OP_READVAR, - (associd == 0) ? TYPE_SYS : TYPE_PEER, fp); + type = (0 == associd) + ? TYPE_SYS + : TYPE_PEER; + dolist(g_varlist, associd, CTL_OP_READVAR, type, fp); } @@ -575,9 +589,9 @@ writelist( FILE *fp ) { - char *datap; + const char *datap; int res; - int associd; + associd_t associd; int dsize; u_short rstatus; @@ -591,7 +605,7 @@ writelist( return; } - res = doquerylist(varlist, CTL_OP_WRITEVAR, associd, 1, &rstatus, + res = doquerylist(g_varlist, CTL_OP_WRITEVAR, associd, 1, &rstatus, &dsize, &datap); if (res != 0) @@ -602,9 +616,9 @@ writelist( if (dsize == 0) (void) fprintf(fp, "done! (no data returned)\n"); else { - (void) fprintf(fp,"assID=%d ",associd); + (void) fprintf(fp,"associd=%d ",associd); printvars(dsize, datap, (int)rstatus, - (associd != 0) ? TYPE_PEER : TYPE_SYS, fp); + (associd != 0) ? TYPE_PEER : TYPE_SYS, 0, fp); } return; } @@ -619,8 +633,10 @@ readvar( FILE *fp ) { - int associd; - struct varlist tmplist[MAXLIST]; + associd_t associd; + int type; + struct varlist tmplist[MAXLIST]; + /* HMS: uval? */ if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0) @@ -628,12 +644,14 @@ readvar( else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0) return; - memset((char *)tmplist, 0, sizeof(tmplist)); + memset(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); + type = (0 == associd) + ? TYPE_SYS + : TYPE_PEER; + dolist(tmplist, associd, CTL_OP_READVAR, type, fp); doclearvlist(tmplist); } @@ -648,9 +666,10 @@ writevar( FILE *fp ) { - char *datap; + const char *datap; int res; - int associd; + associd_t associd; + int type; int dsize; u_short rstatus; struct varlist tmplist[MAXLIST]; @@ -673,13 +692,15 @@ writevar( return; if (numhosts > 1) - (void) fprintf(fp, "server=%s ", currenthost); + fprintf(fp, "server=%s ", currenthost); if (dsize == 0) - (void) fprintf(fp, "done! (no data returned)\n"); + 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); + fprintf(fp,"associd=%d ",associd); + type = (0 == associd) + ? TYPE_SYS + : TYPE_PEER; + printvars(dsize, datap, (int)rstatus, type, 0, fp); } return; } @@ -694,7 +715,7 @@ clocklist( FILE *fp ) { - int associd; + associd_t associd; /* HMS: uval? */ if (pcmd->nargs == 0) { @@ -706,7 +727,7 @@ clocklist( return; } - (void) dolist(varlist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp); + dolist(g_varlist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp); } @@ -719,7 +740,7 @@ clockvar( FILE *fp ) { - int associd; + associd_t associd; struct varlist tmplist[MAXLIST]; /* HMS: uval? */ @@ -728,11 +749,11 @@ clockvar( else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0) return; - memset((char *)tmplist, 0, sizeof(tmplist)); + memset(tmplist, 0, sizeof(tmplist)); if (pcmd->nargs >= 2) doaddvlist(tmplist, pcmd->argval[1].string); - (void) dolist(tmplist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp); + dolist(tmplist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp); doclearvlist(tmplist); } @@ -749,48 +770,38 @@ findassidrange( int *to ) { - register int i; - int f, t; + associd_t assids[2]; + int ind[COUNTOF(assids)]; + int i; + size_t a; - if (assid1 == 0 || assid1 > 65535) { - (void) fprintf(stderr, - "***Invalid association ID %lu specified\n", (u_long)assid1); + assids[0] = checkassocid(assid1); + if (0 == assids[0]) return 0; - } - - if (assid2 == 0 || assid2 > 65535) { - (void) fprintf(stderr, - "***Invalid association ID %lu specified\n", (u_long)assid2); + assids[1] = checkassocid(assid2); + if (0 == assids[1]) 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; + for (a = 0; a < COUNTOF(assids); a++) { + ind[a] = -1; + for (i = 0; i < numassoc; i++) + if (assoc_cache[i].assid == assids[a]) + ind[a] = i; } + for (a = 0; a < COUNTOF(assids); a++) + if (-1 == ind[a]) { + fprintf(stderr, + "***Association ID %u not found in list\n", + assids[a]); + return 0; + } - if (f < t) { - *from = f; - *to = t; + if (ind[0] < ind[1]) { + *from = ind[0]; + *to = ind[1]; } else { - *from = t; - *to = f; + *to = ind[0]; + *from = ind[1]; } return 1; } @@ -818,7 +829,7 @@ mreadlist( for (i = from; i <= to; i++) { if (i != from) (void) fprintf(fp, "\n"); - if (!dolist(varlist, (int)assoc_cache[i].assid, + if (!dolist(g_varlist, (int)assoc_cache[i].assid, CTL_OP_READVAR, TYPE_PEER, fp)) return; } @@ -839,21 +850,26 @@ mreadvar( int from; int to; struct varlist tmplist[MAXLIST]; + struct varlist *pvars; /* 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) + if (pcmd->nargs >= 3) { + memset(tmplist, 0, sizeof(tmplist)); doaddvlist(tmplist, pcmd->argval[2].string); + pvars = tmplist; + } else { + pvars = g_varlist; + } 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)) + fprintf(fp, "\n"); + if (!dolist(pvars, (int)assoc_cache[i].assid, + CTL_OP_READVAR, TYPE_PEER, fp)) break; } doclearvlist(tmplist); @@ -869,7 +885,7 @@ dogetassoc( FILE *fp ) { - char *datap; + const char *datap; int res; int dsize; u_short rstatus; @@ -898,9 +914,9 @@ dogetassoc( numassoc = 0; while (dsize > 0) { - assoc_cache[numassoc].assid = ntohs(*((u_short *)datap)); + assoc_cache[numassoc].assid = ntohs(*((const u_short *)datap)); datap += sizeof(u_short); - assoc_cache[numassoc].status = ntohs(*((u_short *)datap)); + assoc_cache[numassoc].status = ntohs(*((const u_short *)datap)); datap += sizeof(u_short); if (++numassoc >= MAXASSOC) break; @@ -942,7 +958,7 @@ printassoc( * Output a header */ (void) fprintf(fp, - "\nind assID status conf reach auth condition last_event cnt\n"); + "\nind assid status conf reach auth condition last_event cnt\n"); (void) fprintf(fp, "===========================================================\n"); for (i = 0; i < numassoc; i++) { @@ -955,112 +971,151 @@ printassoc( conf = "yes"; else conf = "no"; - if (statval & CTL_PST_REACH || 1) { - reach = "yes"; + if (statval & CTL_PST_BCAST) { + reach = "none"; + if (statval & CTL_PST_AUTHENABLE) + auth = "yes"; + else + auth = "none"; + } else { + if (statval & CTL_PST_REACH) + reach = "yes"; + else + reach = "no"; if (statval & CTL_PST_AUTHENABLE) { if (statval & CTL_PST_AUTHENTIC) auth = "ok "; else auth = "bad"; - } else + } else { auth = "none"; + } + } + if (pktversion > NTP_OLDVERSION) { + switch (statval & 0x7) { - 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)) + 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 = "candidate"; + break; + + case CTL_PST_SEL_EXCESS: + condition = "backup"; + 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)) + else if (!(statval & OLD_CTL_PST_DISP)) condition = "hi_disp"; - else + 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; - } + break; - } else { - reach = "no"; - auth = condition = ""; - } + 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; + } + } switch (PEER_EVENT|event) { - case EVNT_PEERIPERR: - last_event = "IP error"; - break; - case EVNT_PEERAUTH: - last_event = "auth fail"; + + case PEVNT_MOBIL: + last_event = "mobilize"; break; - case EVNT_UNREACH: - last_event = "lost reach"; + + case PEVNT_DEMOBIL: + last_event = "demobilize"; break; - case EVNT_REACH: + + case PEVNT_REACH: last_event = "reachable"; break; - case EVNT_PEERCLOCK: - last_event = "clock expt"; + + case PEVNT_UNREACH: + last_event = "unreachable"; break; -#if 0 - case EVNT_PEERSTRAT: - last_event = "stratum chg"; + + case PEVNT_RESTART: + last_event = "restart"; break; -#endif - default: + + case PEVNT_REPLY: + last_event = "no_reply"; + break; + + case PEVNT_RATE: + last_event = "rate_exceeded"; + break; + + case PEVNT_DENY: + last_event = "access_denied"; + break; + + case PEVNT_ARMED: + last_event = "leap_armed"; + break; + + case PEVNT_NEWPEER: + last_event = "sys_peer"; + break; + + case PEVNT_CLOCK: + last_event = "clock_alarm"; + break; + + 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); + cnt = uinttoa(event_count); + snprintf(buf, sizeof(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; + bp[0] = '\0'; + fprintf(fp, "%s\n", buf); } } - /* * associations - get, record and print a list of associations */ @@ -1119,6 +1174,38 @@ lpassociations( } +/* + * saveconfig - dump ntp server configuration to server file + */ +static void +saveconfig( + struct parse *pcmd, + FILE *fp + ) +{ + const char *datap; + int res; + int dsize; + u_short rstatus; + + if (0 == pcmd->nargs) + return; + + res = doquery(CTL_OP_SAVECONFIG, 0, 1, + strlen(pcmd->argval[0].string), + pcmd->argval[0].string, &rstatus, &dsize, + &datap); + + if (res != 0) + return; + + if (0 == dsize) + fprintf(fp, "(no response message, curiously)"); + else + fprintf(fp, "%.*s", dsize, datap); +} + + #ifdef UNUSED /* * radiostatus - print the radio status returned by the server @@ -1161,9 +1248,9 @@ pstatus( FILE *fp ) { - char *datap; + const char *datap; int res; - int associd; + associd_t associd; int dsize; u_short rstatus; @@ -1171,23 +1258,23 @@ pstatus( if ((associd = checkassocid(pcmd->argval[0].uval)) == 0) return; - res = doquery(CTL_OP_READSTAT, associd, 0, 0, (char *)0, &rstatus, - &dsize, &datap); + res = doquery(CTL_OP_READSTAT, associd, 0, 0, NULL, &rstatus, + &dsize, &datap); if (res != 0) return; if (numhosts > 1) - (void) fprintf(fp, "server=%s ", currenthost); + fprintf(fp, "server=%s ", currenthost); if (dsize == 0) { - (void) fprintf(fp, - "No information returned for association %u\n", - associd); + 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); + fprintf(fp, "associd=%u ", associd); + printvars(dsize, datap, (int)rstatus, TYPE_PEER, 0, fp); } @@ -1220,6 +1307,7 @@ when( static char * prettyinterval( char *buf, + size_t cb, long diff ) { @@ -1230,40 +1318,38 @@ prettyinterval( } if (diff <= 2048) { - (void) sprintf(buf, "%ld", (long int)diff); + snprintf(buf, cb, "%ld", diff); return buf; } diff = (diff + 29) / 60; if (diff <= 300) { - (void) sprintf(buf, "%ldm", (long int)diff); + snprintf(buf, cb, "%ldm", diff); return buf; } diff = (diff + 29) / 60; if (diff <= 96) { - (void) sprintf(buf, "%ldh", (long int)diff); + snprintf(buf, cb, "%ldh", diff); return buf; } diff = (diff + 11) / 24; - (void) sprintf(buf, "%ldd", (long int)diff); + snprintf(buf, cb, "%ldd", diff); return buf; } static char decodeaddrtype( - struct sockaddr_storage *sock + sockaddr_u *sock ) { char ch = '-'; u_int32 dummy; - struct sockaddr_in6 *sin6; - switch(sock->ss_family) { + switch(AF(sock)) { case AF_INET: - dummy = ((struct sockaddr_in *)sock)->sin_addr.s_addr; - dummy = ntohl(dummy); + dummy = SRCADR(sock); ch = (char)(((dummy&0xf0000000)==0xe0000000) ? 'm' : ((dummy&0x000000ff)==0x000000ff) ? 'b' : ((dummy&0xffffffff)==0x7f000001) ? 'l' : @@ -1271,8 +1357,7 @@ decodeaddrtype( 'u'); break; case AF_INET6: - sin6 = (struct sockaddr_in6 *)sock; - if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) + if (IN6_IS_ADDR_MULTICAST(PSOCK_ADDR6(sock))) ch = 'm'; else ch = 'u'; @@ -1346,7 +1431,7 @@ doprintpeers( int associd, int rstatus, int datalen, - char *data, + const char *data, FILE *fp, int af ) @@ -1356,10 +1441,13 @@ doprintpeers( int i; int c; - struct sockaddr_storage srcadr; - struct sockaddr_storage dstadr; + sockaddr_u srcadr; + sockaddr_u dstadr; + sockaddr_u refidadr; u_long srcport = 0; char *dstadr_refid = "0.0.0.0"; + char *serverlocal; + size_t drlen; u_long stratum = 0; long ppoll = 0; long hpoll = 0; @@ -1381,8 +1469,8 @@ doprintpeers( 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)); + ZERO_SOCK(&srcadr); + ZERO_SOCK(&dstadr); /* Initialize by zeroing out estimate variables */ memset((char *)&estoffset, 0, sizeof(l_fp)); @@ -1391,23 +1479,24 @@ doprintpeers( memset((char *)&estdisp, 0, sizeof(l_fp)); while (nextvar(&datalen, &data, &name, &value)) { - struct sockaddr_storage dum_store; + sockaddr_u 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)) + if (decodenetnum(value, &srcadr)) { havevar[HAVE_SRCADR] = 1; + } break; case CP_DSTADR: - if (decodenetnum(value, &dum_store)) + if (decodenetnum(value, &dum_store)) { type = decodeaddrtype(&dum_store); - if (pvl == opeervarlist) { - if (decodenetnum(value, &dstadr)) { - havevar[HAVE_DSTADR] = 1; - dstadr_refid = stoa(&dstadr); + havevar[HAVE_DSTADR] = 1; + dstadr = dum_store; + if (pvl == opeervarlist) { + dstadr_refid = trunc_left(stoa(&dstadr), 15); } } break; @@ -1415,24 +1504,23 @@ doprintpeers( if (pvl == peervarlist) { havevar[HAVE_REFID] = 1; if (*value == '\0') { - dstadr_refid = "0.0.0.0"; - } else if ((int)strlen(value) <= 4) { + dstadr_refid = ""; + } else if (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)) + } else if (decodenetnum(value, &refidadr)) { + if (SOCK_UNSPEC(&refidadr)) dstadr_refid = "0.0.0.0"; - else if ((dstadr.ss_family == AF_INET) - && ISREFCLOCKADR(&dstadr)) - dstadr_refid = - refnumtoa(&dstadr); + else if (ISREFCLOCKADR(&refidadr)) + dstadr_refid = + refnumtoa(&refidadr); else dstadr_refid = - stoa(&dstadr); + stoa(&refidadr); } else { havevar[HAVE_REFID] = 0; } @@ -1510,19 +1598,39 @@ doprintpeers( 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)); + if (numhosts > 1) { + if (peervarlist == pvl && havevar[HAVE_DSTADR]) { + serverlocal = nntohost_col(&dstadr, + (size_t)min(LIB_BUFLENGTH - 1, maxhostlen), + TRUE); + } else { + if (currenthostisnum) + serverlocal = trunc_left(currenthost, + maxhostlen); + else + serverlocal = currenthost; + } + fprintf(fp, "%-*s ", maxhostlen, serverlocal); + } + if (AF_UNSPEC == af || AF(&srcadr) == af) { + strncpy(clock_name, nntohost(&srcadr), sizeof(clock_name)); + fprintf(fp, "%c%-15.15s ", c, clock_name); + drlen = strlen(dstadr_refid); + makeascii(drlen, dstadr_refid, fp); + while (drlen++ < 15) + fputc(' ', fp); + fprintf(fp, + " %2ld %c %4.4s %4.4s %3lo %7.7s %8.7s %7.7s\n", + stratum, type, + prettyinterval(whenbuf, sizeof(whenbuf), + when(&ts, &rec, &reftime)), + prettyinterval(pollbuf, sizeof(pollbuf), + (int)poll_sec), + reach, lfptoms(&estdelay, 3), + lfptoms(&estoffset, 3), + (havevar[HAVE_JITTER]) + ? lfptoms(&estjitter, 3) + : lfptoms(&estdisp, 3)); return (1); } else @@ -1553,12 +1661,12 @@ doprintpeers( static int dogetpeers( struct varlist *pvl, - int associd, + associd_t associd, FILE *fp, int af ) { - char *datap; + const char *datap; int res; int dsize; u_short rstatus; @@ -1570,7 +1678,7 @@ dogetpeers( /* * Damn fuzzballs */ - res = doquery(CTL_OP_READVAR, associd, 0, 0, (char *)0, &rstatus, + res = doquery(CTL_OP_READVAR, associd, 0, 0, NULL, &rstatus, &dsize, &datap); #endif @@ -1579,14 +1687,15 @@ dogetpeers( if (dsize == 0) { if (numhosts > 1) - (void) fprintf(stderr, "server=%s ", currenthost); - (void) fprintf(stderr, - "***No information returned for association %d\n", - associd); + fprintf(stderr, "server=%s ", currenthost); + fprintf(stderr, + "***No information returned for association %u\n", + associd); return 0; } - return doprintpeers(pvl, associd, (int)rstatus, dsize, datap, fp, af); + return doprintpeers(pvl, associd, (int)rstatus, dsize, datap, + fp, af); } @@ -1600,27 +1709,32 @@ dopeers( int af ) { - register int i; - char fullname[LENHOSTNAME]; - struct sockaddr_storage netnum; + int i; + char fullname[LENHOSTNAME]; + sockaddr_u netnum; + char * name_or_num; + size_t sl; 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 (getnetnum(chosts[i], &netnum, fullname, af)) { + name_or_num = nntohost(&netnum); + sl = strlen(name_or_num); + maxhostlen = max(maxhostlen, (int)sl); + } } if (numhosts > 1) - (void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "server"); - (void) fprintf(fp, - " remote refid st t when poll reach delay offset jitter\n"); + fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, + "server (local)"); + 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"); + fprintf(fp, "="); + fprintf(fp, + "==============================================================================\n"); for (i = 0; i < numassoc; i++) { if (!showall && @@ -1691,7 +1805,7 @@ doopeers( { register int i; char fullname[LENHOSTNAME]; - struct sockaddr_storage netnum; + sockaddr_u netnum; if (!dogetassoc(fp)) return; @@ -1766,3 +1880,138 @@ lopeers( } doopeers(1, fp, af); } + + +/* + * config - send a configuration command to a remote host + */ +static void +config ( + struct parse *pcmd, + FILE *fp + ) +{ + char *cfgcmd; + u_short rstatus; + int rsize; + const char *rdata; + char *resp; + int res; + int col; + int i; + + cfgcmd = pcmd->argval[0].string; + + if (debug > 2) + fprintf(stderr, + "In Config\n" + "Keyword = %s\n" + "Command = %s\n", pcmd->keyword, cfgcmd); + + res = doquery(CTL_OP_CONFIGURE, 0, 1, strlen(cfgcmd), cfgcmd, + &rstatus, &rsize, &rdata); + + if (res != 0) + return; + + if (rsize > 0 && '\n' == rdata[rsize - 1]) + rsize--; + + resp = emalloc(rsize + 1); + memcpy(resp, rdata, rsize); + resp[rsize] = '\0'; + + col = -1; + if (1 == sscanf(resp, "column %d syntax error", &col) + && col >= 0 && (size_t)col <= strlen(cfgcmd) + 1) { + if (interactive) { + printf("______"); /* "ntpq> " */ + printf("________"); /* ":config " */ + } else + printf("%s\n", cfgcmd); + for (i = 1; i < col; i++) + putchar('_'); + printf("^\n"); + } + printf("%s\n", resp); + free(resp); +} + + +/* + * config_from_file - remotely configure an ntpd daemon using the + * specified configuration file + * SK: This function is a kludge at best and is full of bad design + * bugs: + * 1. ntpq uses UDP, which means that there is no guarantee of in-order, + * error-free delivery. + * 2. The maximum length of a packet is constrained, and as a result, the + * maximum length of a line in a configuration file is constrained. + * Longer lines will lead to unpredictable results. + * 3. Since this function is sending a line at a time, we can't update + * the control key through the configuration file (YUCK!!) + */ +static void +config_from_file ( + struct parse *pcmd, + FILE *fp + ) +{ + u_short rstatus; + int rsize; + const char *rdata; + int res; + FILE *config_fd; + char config_cmd[MAXLINE]; + size_t config_len; + int i; + int retry_limit; + + if (debug > 2) + fprintf(stderr, + "In Config\n" + "Keyword = %s\n" + "Filename = %s\n", pcmd->keyword, + pcmd->argval[0].string); + + config_fd = fopen(pcmd->argval[0].string, "r"); + if (NULL == config_fd) { + printf("ERROR!! Couldn't open file: %s\n", + pcmd->argval[0].string); + return; + } + + printf("Sending configuration file, one line at a time.\n"); + i = 0; + while (fgets(config_cmd, MAXLINE, config_fd) != NULL) { + config_len = strlen(config_cmd); + /* ensure even the last line has newline, if possible */ + if (config_len > 0 && + config_len + 2 < sizeof(config_cmd) && + '\n' != config_cmd[config_len - 1]) + config_cmd[config_len++] = '\n'; + ++i; + retry_limit = 2; + do + res = doquery(CTL_OP_CONFIGURE, 0, 1, + strlen(config_cmd), config_cmd, + &rstatus, &rsize, &rdata); + while (res != 0 && retry_limit--); + if (res != 0) { + printf("Line No: %d query failed: %s", i, + config_cmd); + printf("Subsequent lines not sent.\n"); + fclose(config_fd); + return; + } + + if (rsize > 0 && '\n' == rdata[rsize - 1]) + rsize--; + if (rsize > 0 && '\r' == rdata[rsize - 1]) + rsize--; + printf("Line No: %d %.*s: %s", i, rsize, rdata, + config_cmd); + } + printf("Done sending file\n"); + fclose(config_fd); +} |