ntpq_ops.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* Copyright (c) 1996 by Sun Microsystems, Inc.
* All Rights Reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* ntpdc_ops.c - subroutines which are called to perform operations by xntpdc
*/
#include <stdio.h>
#include <ctype.h>
#include <netdb.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 void doaddvlist P((struct varlist *, char *));
static void doclearvlist P((struct varlist *));
static void makequerydata P((struct varlist *, int *, char *));
static int dogetassoc P((FILE *));
static void printassoc P((int, FILE *));
#ifdef UNUSED
#endif /* UNUSED */
static char * fixup P((int, char *));
static char * prettyinterval P((char *, long));
/*
* Commands we understand. Ntpdc imports this.
*/
{ "", "", "", "" },
"print list of association ID's and statuses for the server's peers" },
{ "", "", "", "" },
"print list of associations returned by last associations command" },
{ "", "", "", "" },
"print list of associations including all client information" },
{ "", "", "", "" },
"print last obtained list of associations, including client information" },
{ "name[=value][,...]", "", "", "" },
"add variables to the variable list or change their values" },
{ "name[,...]", "", "", "" },
"remove variables from the variable list" },
{ "", "", "", "" },
"remove all variables from the variable list" },
{ "", "", "", "" },
"print variables on the variable list" },
{ "assocID", "", "", "" },
"read the system or peer variables included in the variable list" },
{ "assocID", "", "", "" },
"read the system or peer variables included in the variable list" },
{ "assocID", "", "", "" },
"write the system or peer variables included in the variable list" },
{ "assocID", "name=value[,...]", "", "" },
"read system or peer variables" },
{ "assocID", "name=value[,...]", "", "" },
"read system or peer variables" },
{ "assocID", "name=value,[...]", "", "" },
"write system or peer variables" },
{ "assocID", "assocID", "", "" },
"read the peer variables in the variable list for multiple peers" },
{ "assocID", "assocID", "", "" },
"read the peer variables in the variable list for multiple peers" },
{ "assocID", "assocID", "name=value[,...]", "" },
"read peer variables from multiple peers" },
{ "assocID", "assocID", "name=value[,...]", "" },
"read peer variables from multiple peers" },
{ "assocID", "", "", "" },
"read the clock variables included in the variable list" },
{ "assocID", "", "", "" },
"read the clock variables included in the variable list" },
{ "assocID", "name=value[,...]", "", "" },
"read clock variables" },
{ "assocID", "name=value[,...]", "", "" },
"read clock variables" },
{ "assocID", "", "", "" },
"print status information returned for a peer" },
{ "", "", "", "" },
"obtain and print a list of the server's peers" },
{ "", "", "", "" },
"obtain and print a list of all peers and clients" },
{ "", "", "", "" },
"print peer list the old way, with dstadr shown rather than refid" },
{ "", "", "", "" },
"obtain and print a list of all peers and clients showing dstadr" },
{ "", "", "", "" }, "" }
};
/*
* Variable list data space
*/
/*
* 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
struct varlist {
char *name;
char *value;
/*
* Imported from ntpq.c
*/
extern int showhostnames;
extern int rawmode;
extern int debug;
extern struct servent *server_entry;
extern struct association assoc_cache[];
extern int numassoc;
extern u_char pktversion;
/*
* For quick string comparisons
*/
/*
* checkassocid - return the association ID, checking to see if it is valid
*/
static int
{
return 0;
}
return (int)value;
}
/*
* strsave - save a string
* XXX - should be in libntp.a
*/
static char *
char *str;
{
char *cp;
exit(1);
}
return (cp);
}
/*
* findlistvar - look for the named variable in a list and return if found
*/
static struct varlist *
char *name;
{
return vl;
return vl;
return (struct varlist *)0;
}
/*
* doaddvlist - add variable(s) to the variable list
*/
static void
char *vars;
{
int len;
char *name;
char *value;
if (vl == 0) {
return;
}
}
if (value != 0)
}
}
/*
* dormvlist - remove variable(s) from the variable list
*/
static void
char *vars;
{
int len;
char *name;
char *value;
name);
} else {
}
}
}
}
/*
* doclearvlist - clear a variable list
*/
static void
{
}
}
}
/*
* makequerydata - form a data buffer to be included with a query
*/
static void
int *datalen;
char *data;
{
register int totallen;
valuelen = 0;
else
break;
*cp++ = ',';
if (valuelen != 0) {
*cp++ = '=';
}
}
}
/*
* doquerylist - send a message including variables in a list
*/
static int
int op;
int associd;
int auth;
int *dsize;
char **datap;
{
char data[CTL_MAX_DATA_LEN];
int datalen;
}
/*
* doprintvlist - print the variables on a list
*/
static void
{
} else {
} else {
}
}
}
}
/*
* addvars - add variables to the variable list
*/
/*ARGSUSED*/
static void
{
}
/*
* rmvars - remove variables from the variable list
*/
/*ARGSUSED*/
static void
{
}
/*
* clearvars - clear the variable list
*/
/*ARGSUSED*/
static void
{
}
/*
* showvars - show variables on the variable list
*/
/*ARGSUSED*/
static void
{
}
/*
* dolist - send a request with the given list of variables
*/
static int
int associd;
int op;
int type;
{
char *datap;
int res;
int dsize;
if (res != 0)
return 0;
if (dsize == 0) {
if (associd == 0)
else
"No information returned for%s association %u\n",
return 1;
}
return 1;
}
/*
* readlist - send a read variables request with the variables on the list
*/
static void
{
int associd;
associd = 0;
} else {
/* HMS: I think we want the u_int32 target here, not the u_long */
associd = 0;
return;
}
}
/*
* writelist - send a write variables request with the variables on the list
*/
static void
{
char *datap;
int res;
int associd;
int dsize;
associd = 0;
} else {
/* HMS: Do we really want uval here? */
associd = 0;
return;
}
if (res != 0)
return;
if (dsize == 0)
else
return;
}
/*
* readvar - send a read variables request with the specified variables
*/
static void
{
int associd;
/* HMS: uval? */
associd = 0;
return;
}
/*
* writevar - send a write variables request with the specified variables
*/
static void
{
char *datap;
int res;
int associd;
int dsize;
/* HMS: uval? */
associd = 0;
return;
if (res != 0)
return;
if (dsize == 0)
else
return;
}
/*
* clocklist - send a clock variables request with the variables on the list
*/
static void
{
int associd;
/* HMS: uval? */
associd = 0;
} else {
associd = 0;
return;
}
}
/*
* clockvar - send a clock variables request with the specified variables
*/
static void
{
int associd;
/* HMS: uval? */
associd = 0;
return;
}
/*
* findassidrange - verify a range of association ID's
*/
static int
int *from;
int *to;
{
register int i;
int f, t;
return 0;
}
return 0;
}
f = t = -1;
for (i = 0; i < numassoc; i++) {
f = i;
if (t != -1)
break;
}
t = i;
if (f != -1)
break;
}
}
if (f == -1 || t == -1) {
"***Association ID %lu not found in list\n",
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
{
int i;
int from;
int to;
/* HMS: uval? */
return;
if (i != from)
return;
}
return;
}
/*
* mreadvar - send a read variables request for multiple associations
*/
static void
{
int i;
int from;
int to;
/* HMS: uval? */
return;
if (i != from)
break;
}
return;
}
/*
* dogetassoc - query the host for its list of associations
*/
static int
{
int res;
int dsize;
if (res != 0)
return 0;
if (dsize == 0) {
return 0;
}
if (dsize & 0x3) {
"***Server returned %d octets, should be multiple of 4\n",
dsize);
return 0;
}
numassoc = 0;
while (dsize > 0) {
datap++;
datap++;
break;
}
sortassoc();
return 1;
}
/*
* printassoc - print the current list of associations
*/
static void
int showall;
{
register char *bp;
int i;
int event;
const char *conf;
char *reach;
const char *auth;
const char *condition = "";
const char *last_event;
char *cnt;
char buf[128];
if (numassoc == 0) {
return;
}
/*
* Output a header
*/
"ind assID status conf reach auth condition last_event cnt\n");
"===========================================================\n");
for (i = 0; i < numassoc; i++) {
continue;
if (statval & CTL_PST_CONFIG)
conf = "yes";
else
conf = "no";
if (statval & CTL_PST_REACH) {
reach = "yes";
if (statval & CTL_PST_AUTHENABLE) {
if (statval & CTL_PST_AUTHENTIC)
auth = "ok ";
else
auth = "bad";
} else
auth = "none";
if (pktversion == NTP_VERSION)
switch (statval & 0x7) {
case CTL_PST_SEL_REJECT:
condition = "insane";
break;
case CTL_PST_SEL_SANE:
condition = "falsetick";
break;
case CTL_PST_SEL_CORRECT:
condition = "eliminate";
break;
case CTL_PST_SEL_SELCAND:
condition = "outlyer";
break;
case CTL_PST_SEL_SYNCCAND:
condition = "synchr.";
break;
case CTL_PST_SEL_DISTSYSPEER:
condition = "dist.peer";
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";
}
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)
else
cnt = "";
"%3d %5u %04x %3.3s %4s %4.4s %9.9s %11s %2s",
*(--bp) = '\0';
}
}
/*
* associations - get, record and print a list of associations
*/
/*ARGSUSED*/
static void
{
if (dogetassoc(fp))
printassoc(0, fp);
}
/*
* lassociations - get, record and print a long list of associations
*/
/*ARGSUSED*/
static void
{
if (dogetassoc(fp))
}
/*
* passociations - print the association list
*/
/*ARGSUSED*/
static void
{
printassoc(0, fp);
}
/*
* lpassociations - print the long association list
*/
/*ARGSUSED*/
static void
{
}
#ifdef UNUSED
/*
* radiostatus - print the radio status returned by the server
*/
/*ARGSUSED*/
static void
{
char *datap;
int res;
int dsize;
if (res != 0)
return;
if (dsize == 0) {
return;
}
}
#endif /* UNUSED */
/*
* pstatus - print peer status returned by the server
*/
static void
{
char *datap;
int res;
int associd;
int dsize;
/* HMS: uval? */
return;
if (res != 0)
return;
if (dsize == 0) {
"No information returned for association %u\n",
associd);
return;
}
}
/*
* fixup - fix up a string so we don't get a hanging decimal after it
*/
static char *
int width;
char *str;
{
return str;
}
/*
* when - print how long its been since his last packet arrived
*/
static long
{
else
return 0;
}
/*
* Pretty-print an interval into the given buffer, in a human-friendly format.
*/
static char *
char *buf;
long diff;
{
if (diff <= 0) {
buf[0] = '-';
buf[1] = 0;
return buf;
}
if (diff <= 2048) {
return buf;
}
if (diff <= 300) {
return buf;
}
if (diff <= 96) {
return buf;
}
return buf;
}
/*
* 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 */
{ "dispersion", 0 }, /* 8 */
{ "rec", 0 }, /* 9 */
{ "reftime", 0 }, /* 10 */
{ "srcport", 0 }, /* 11 */
{ 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 */
{ "dispersion", 0 }, /* 8 */
{ "rec", 0 }, /* 9 */
{ "reftime", 0 }, /* 10 */
{ "srcport", 0 }, /* 11 */
{ 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_DISPERSION 8
#define HAVE_REC 9
#define HAVE_REFTIME 10
#define HAVE_SRCPORT 11
#define MAXHAVE 12
/*
* Decode an incoming data buffer and print a line in the peer list
*/
static int
int associd;
int rstatus;
int datalen;
char *data;
{
char *name;
char *value;
int i;
int c;
const char *dstadr_refid = "0.0.0.0";
long ppoll;
long hpoll;
char type = '?';
char refid_string[10];
get_systime(&ts);
if (i == 0)
continue; /* don't know this one */
switch (i) {
case CP_SRCADR:
break;
case CP_DSTADR:
'u';
}
if (pvl == opeervarlist) {
}
}
break;
case CP_REFID:
if (pvl == peervarlist) {
if (*value == '\0') {
dstadr_refid = "0.0.0.0";
if (dstadr == 0)
dstadr_refid = "0.0.0.0";
else
refid_string[0] = '.';
i = strlen(refid_string);
refid_string[i] = '.';
} else {
havevar[HAVE_REFID] = 0;
}
}
break;
case CP_STRATUM:
break;
case CP_HPOLL:
if (hpoll < 0)
hpoll = NTP_MINPOLL;
}
break;
case CP_PPOLL:
if (ppoll < 0)
ppoll = NTP_MINPOLL;
}
break;
case CP_REACH:
break;
case CP_DELAY:
break;
case CP_OFFSET:
break;
case CP_DISPERSION:
break;
case CP_REC:
break;
case CP_SRCPORT:
break;
case CP_REFTIME:
break;
default:
break;
}
}
/*
* Check to see if the srcport is NTP's port. If not this probably
* isn't a valid peer association.
*/
return 1;
/*
* Check to see if we got all of them. If not, return an
* error.
*/
for (i = 0; i < MAXHAVE; i++)
if (!havevar[i]) {
"***Remote host didn't return peer.%s for association %d\n",
return 0;
}
/*
* Got everything, format the line
*/
if (pktversion == NTP_VERSION)
else
if (numhosts > 1)
"%c%-15.15s %-15.15s %2ld %c %4.4s %4.4s %3lo %7.7s %8.7s %7.7s\n",
return 1;
}
/*
* dogetpeers - given an association ID, read and print the spreadsheet
* peer variables.
*/
static int
int associd;
{
char *datap;
int res;
int dsize;
#ifdef notdef
#else
/*
* Damn fuzzballs
*/
#endif
if (res != 0)
return 0;
if (dsize == 0) {
"***No information returned for association %d\n",
associd);
return 0;
}
}
/*
* peers - print a peer spreadsheet
*/
static void
int showall;
{
register int i;
char fullname[LENHOSTNAME];
if (!dogetassoc(fp))
return;
for (i = 0; i < numhosts; ++i)
}
if (numhosts > 1)
" remote refid st t when poll reach delay offset disp\n");
if (numhosts > 1)
for (i = 0; i <= maxhostlen; ++i)
"==============================================================================\n");
for (i = 0; i < numassoc; i++) {
if (!showall &&
& (CTL_PST_CONFIG|CTL_PST_REACH)))
continue;
return;
}
}
return;
}
/*
* peers - print a peer spreadsheet
*/
/*ARGSUSED*/
static void
{
}
/*
* lpeers - print a peer spreadsheet including all fuzzball peers
*/
/*ARGSUSED*/
static void
{
}
/*
* opeers - print a peer spreadsheet
*/
static void
int showall;
{
register int i;
if (!dogetassoc(fp))
return;
" remote local st t when poll reach delay offset disp\n");
"===========================================================================\n");
for (i = 0; i < numassoc; i++) {
if (!showall &&
& (CTL_PST_CONFIG|CTL_PST_REACH)))
continue;
return;
}
}
return;
}
/*
* opeers - print a peer spreadsheet the old way
*/
/*ARGSUSED*/
static void
{
}
/*
* lopeers - print a peer spreadsheet including all fuzzball peers
*/
/*ARGSUSED*/
static void
{
}