aboutsummaryrefslogtreecommitdiff
path: root/ntpq/ntpq-subs.c
diff options
context:
space:
mode:
authorOllivier Robert <roberto@FreeBSD.org>2013-12-04 21:33:17 +0000
committerOllivier Robert <roberto@FreeBSD.org>2013-12-04 21:33:17 +0000
commit2b45e011ca352ce509bc83ae148230aeee0c7e0d (patch)
treea618007bb41d13153794a598e3d904ace2976324 /ntpq/ntpq-subs.c
parent9b5bd0a264b0a21eefac2b929b574c73bd601507 (diff)
downloadsrc-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.c881
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);
+}