ntpq-subs.c revision 316722
1215976Sjmallett/* 2215976Sjmallett * ntpq-subs.c - subroutines which are called to perform ntpq commands. 3215976Sjmallett */ 4215976Sjmallett#include <config.h> 5215976Sjmallett#include <stdio.h> 6215976Sjmallett#include <ctype.h> 7215976Sjmallett#include <sys/types.h> 8215976Sjmallett#include <sys/time.h> 9215976Sjmallett 10215976Sjmallett#include "ntpq.h" 11215976Sjmallett#include "ntpq-opts.h" 12215976Sjmallett 13215976Sjmallettextern char currenthost[]; 14215976Sjmallettextern int currenthostisnum; 15215976Sjmallettsize_t maxhostlen; 16215976Sjmallett 17215976Sjmallett/* 18215976Sjmallett * Declarations for command handlers in here 19215976Sjmallett */ 20215976Sjmallettstatic associd_t checkassocid (u_int32); 21215976Sjmallettstatic struct varlist *findlistvar (struct varlist *, char *); 22215976Sjmallettstatic void doaddvlist (struct varlist *, const char *); 23215976Sjmallettstatic void dormvlist (struct varlist *, const char *); 24215976Sjmallettstatic void doclearvlist (struct varlist *); 25215976Sjmallettstatic void makequerydata (struct varlist *, size_t *, char *); 26215976Sjmallettstatic int doquerylist (struct varlist *, int, associd_t, int, 27215976Sjmallett u_short *, size_t *, const char **); 28215976Sjmallettstatic void doprintvlist (struct varlist *, FILE *); 29215976Sjmallettstatic void addvars (struct parse *, FILE *); 30215976Sjmallettstatic void rmvars (struct parse *, FILE *); 31215976Sjmallettstatic void clearvars (struct parse *, FILE *); 32215976Sjmallettstatic void showvars (struct parse *, FILE *); 33215976Sjmallettstatic int dolist (struct varlist *, associd_t, int, int, 34215976Sjmallett FILE *); 35215976Sjmallettstatic void readlist (struct parse *, FILE *); 36215976Sjmallettstatic void writelist (struct parse *, FILE *); 37215976Sjmallettstatic void readvar (struct parse *, FILE *); 38215976Sjmallettstatic void writevar (struct parse *, FILE *); 39215976Sjmallettstatic void clocklist (struct parse *, FILE *); 40215976Sjmallettstatic void clockvar (struct parse *, FILE *); 41215976Sjmallettstatic int findassidrange (u_int32, u_int32, int *, int *, 42215976Sjmallett FILE *); 43215976Sjmallettstatic void mreadlist (struct parse *, FILE *); 44215976Sjmallettstatic void mreadvar (struct parse *, FILE *); 45215976Sjmallettstatic void printassoc (int, FILE *); 46215976Sjmallettstatic void associations (struct parse *, FILE *); 47215976Sjmallettstatic void lassociations (struct parse *, FILE *); 48215976Sjmallettstatic void passociations (struct parse *, FILE *); 49215976Sjmallettstatic void lpassociations (struct parse *, FILE *); 50215976Sjmallett 51215976Sjmallett#ifdef UNUSED 52215976Sjmallettstatic void radiostatus (struct parse *, FILE *); 53215976Sjmallett#endif /* UNUSED */ 54215976Sjmallett 55215976Sjmallettstatic void authinfo (struct parse *, FILE *); 56215976Sjmallettstatic void pstats (struct parse *, FILE *); 57215976Sjmallettstatic long when (l_fp *, l_fp *, l_fp *); 58215976Sjmallettstatic char * prettyinterval (char *, size_t, long); 59215976Sjmallettstatic int doprintpeers (struct varlist *, int, int, size_t, const char *, FILE *, int); 60215976Sjmallettstatic int dogetpeers (struct varlist *, associd_t, FILE *, int); 61215976Sjmallettstatic void dopeers (int, FILE *, int); 62215976Sjmallettstatic void peers (struct parse *, FILE *); 63215976Sjmallettstatic void doapeers (int, FILE *, int); 64215976Sjmallettstatic void apeers (struct parse *, FILE *); 65215976Sjmallettstatic void lpeers (struct parse *, FILE *); 66215976Sjmallettstatic void doopeers (int, FILE *, int); 67215976Sjmallettstatic void opeers (struct parse *, FILE *); 68215976Sjmallettstatic void lopeers (struct parse *, FILE *); 69215976Sjmallettstatic void config (struct parse *, FILE *); 70215976Sjmallettstatic void saveconfig (struct parse *, FILE *); 71215976Sjmallettstatic void config_from_file(struct parse *, FILE *); 72215976Sjmallettstatic void mrulist (struct parse *, FILE *); 73215976Sjmallettstatic void ifstats (struct parse *, FILE *); 74215976Sjmallettstatic void reslist (struct parse *, FILE *); 75215976Sjmallettstatic void sysstats (struct parse *, FILE *); 76215976Sjmallettstatic void sysinfo (struct parse *, FILE *); 77215976Sjmallettstatic void kerninfo (struct parse *, FILE *); 78215976Sjmallettstatic void monstats (struct parse *, FILE *); 79215976Sjmallettstatic void iostats (struct parse *, FILE *); 80215976Sjmallettstatic void timerstats (struct parse *, FILE *); 81215976Sjmallett 82215976Sjmallett/* 83215976Sjmallett * Commands we understand. Ntpdc imports this. 84215976Sjmallett */ 85215976Sjmallettstruct xcmd opcmds[] = { 86215976Sjmallett { "saveconfig", saveconfig, { NTP_STR, NO, NO, NO }, 87215976Sjmallett { "filename", "", "", ""}, 88215976Sjmallett "save ntpd configuration to file, . for current config file"}, 89215976Sjmallett { "associations", associations, { NO, NO, NO, NO }, 90215976Sjmallett { "", "", "", "" }, 91215976Sjmallett "print list of association ID's and statuses for the server's peers" }, 92215976Sjmallett { "passociations", passociations, { NO, NO, NO, NO }, 93215976Sjmallett { "", "", "", "" }, 94215976Sjmallett "print list of associations returned by last associations command" }, 95215976Sjmallett { "lassociations", lassociations, { NO, NO, NO, NO }, 96215976Sjmallett { "", "", "", "" }, 97215976Sjmallett "print list of associations including all client information" }, 98215976Sjmallett { "lpassociations", lpassociations, { NO, NO, NO, NO }, 99215976Sjmallett { "", "", "", "" }, 100215976Sjmallett "print last obtained list of associations, including client information" }, 101215976Sjmallett { "addvars", addvars, { NTP_STR, NO, NO, NO }, 102215976Sjmallett { "name[=value][,...]", "", "", "" }, 103215976Sjmallett "add variables to the variable list or change their values" }, 104215976Sjmallett { "rmvars", rmvars, { NTP_STR, NO, NO, NO }, 105215976Sjmallett { "name[,...]", "", "", "" }, 106215976Sjmallett "remove variables from the variable list" }, 107215976Sjmallett { "clearvars", clearvars, { NO, NO, NO, NO }, 108215976Sjmallett { "", "", "", "" }, 109215976Sjmallett "remove all variables from the variable list" }, 110215976Sjmallett { "showvars", showvars, { NO, NO, NO, NO }, 111215976Sjmallett { "", "", "", "" }, 112215976Sjmallett "print variables on the variable list" }, 113215976Sjmallett { "readlist", readlist, { OPT|NTP_UINT, NO, NO, NO }, 114215976Sjmallett { "assocID", "", "", "" }, 115215976Sjmallett "read the system or peer variables included in the variable list" }, 116215976Sjmallett { "rl", readlist, { OPT|NTP_UINT, NO, NO, NO }, 117215976Sjmallett { "assocID", "", "", "" }, 118215976Sjmallett "read the system or peer variables included in the variable list" }, 119215976Sjmallett { "writelist", writelist, { OPT|NTP_UINT, NO, NO, NO }, 120215976Sjmallett { "assocID", "", "", "" }, 121215976Sjmallett "write the system or peer variables included in the variable list" }, 122215976Sjmallett { "readvar", readvar, { OPT|NTP_UINT, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR, }, 123215976Sjmallett { "assocID", "varname1", "varname2", "varname3" }, 124215976Sjmallett "read system or peer variables" }, 125215976Sjmallett { "rv", readvar, { OPT|NTP_UINT, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR, }, 126215976Sjmallett { "assocID", "varname1", "varname2", "varname3" }, 127215976Sjmallett "read system or peer variables" }, 128215976Sjmallett { "writevar", writevar, { NTP_UINT, NTP_STR, NO, NO }, 129215976Sjmallett { "assocID", "name=value,[...]", "", "" }, 130215976Sjmallett "write system or peer variables" }, 131215976Sjmallett { "mreadlist", mreadlist, { NTP_UINT, NTP_UINT, NO, NO }, 132215976Sjmallett { "assocIDlow", "assocIDhigh", "", "" }, 133215976Sjmallett "read the peer variables in the variable list for multiple peers" }, 134215976Sjmallett { "mrl", mreadlist, { NTP_UINT, NTP_UINT, NO, NO }, 135215976Sjmallett { "assocIDlow", "assocIDhigh", "", "" }, 136215976Sjmallett "read the peer variables in the variable list for multiple peers" }, 137215976Sjmallett { "mreadvar", mreadvar, { NTP_UINT, NTP_UINT, OPT|NTP_STR, NO }, 138215976Sjmallett { "assocIDlow", "assocIDhigh", "name=value[,...]", "" }, 139215976Sjmallett "read peer variables from multiple peers" }, 140215976Sjmallett { "mrv", mreadvar, { NTP_UINT, NTP_UINT, OPT|NTP_STR, NO }, 141215976Sjmallett { "assocIDlow", "assocIDhigh", "name=value[,...]", "" }, 142215976Sjmallett "read peer variables from multiple peers" }, 143215976Sjmallett { "clocklist", clocklist, { OPT|NTP_UINT, NO, NO, NO }, 144215976Sjmallett { "assocID", "", "", "" }, 145215976Sjmallett "read the clock variables included in the variable list" }, 146215976Sjmallett { "cl", clocklist, { OPT|NTP_UINT, NO, NO, NO }, 147215976Sjmallett { "assocID", "", "", "" }, 148215976Sjmallett "read the clock variables included in the variable list" }, 149215976Sjmallett { "clockvar", clockvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO }, 150215976Sjmallett { "assocID", "name=value[,...]", "", "" }, 151215976Sjmallett "read clock variables" }, 152215976Sjmallett { "cv", clockvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO }, 153215976Sjmallett { "assocID", "name=value[,...]", "", "" }, 154215976Sjmallett "read clock variables" }, 155215976Sjmallett { "pstats", pstats, { NTP_UINT, NO, NO, NO }, 156215976Sjmallett { "assocID", "", "", "" }, 157215976Sjmallett "show statistics for a peer" }, 158215990Sjmallett { "peers", peers, { OPT|IP_VERSION, NO, NO, NO }, 159215990Sjmallett { "-4|-6", "", "", "" }, 160215976Sjmallett "obtain and print a list of the server's peers [IP version]" }, 161215976Sjmallett { "apeers", apeers, { OPT|IP_VERSION, NO, NO, NO }, 162215976Sjmallett { "-4|-6", "", "", "" }, 163215976Sjmallett "obtain and print a list of the server's peers and their assocIDs [IP version]" }, 164215976Sjmallett { "lpeers", lpeers, { OPT|IP_VERSION, NO, NO, NO }, 165215976Sjmallett { "-4|-6", "", "", "" }, 166215976Sjmallett "obtain and print a list of all peers and clients [IP version]" }, 167215976Sjmallett { "opeers", opeers, { OPT|IP_VERSION, NO, NO, NO }, 168215976Sjmallett { "-4|-6", "", "", "" }, 169215976Sjmallett "print peer list the old way, with dstadr shown rather than refid [IP version]" }, 170215976Sjmallett { "lopeers", lopeers, { OPT|IP_VERSION, NO, NO, NO }, 171215976Sjmallett { "-4|-6", "", "", "" }, 172215976Sjmallett "obtain and print a list of all peers and clients showing dstadr [IP version]" }, 173215976Sjmallett { ":config", config, { NTP_STR, NO, NO, NO }, 174215976Sjmallett { "<configuration command line>", "", "", "" }, 175215976Sjmallett "send a remote configuration command to ntpd" }, 176215976Sjmallett { "config-from-file", config_from_file, { NTP_STR, NO, NO, NO }, 177215976Sjmallett { "<configuration filename>", "", "", "" }, 178215976Sjmallett "configure ntpd using the configuration filename" }, 179215976Sjmallett { "mrulist", mrulist, { OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 180215976Sjmallett { "tag=value", "tag=value", "tag=value", "tag=value" }, 181215976Sjmallett "display the list of most recently seen source addresses, tags mincount=... resall=0x... resany=0x..." }, 182215976Sjmallett { "ifstats", ifstats, { NO, NO, NO, NO }, 183215976Sjmallett { "", "", "", "" }, 184215976Sjmallett "show statistics for each local address ntpd is using" }, 185215976Sjmallett { "reslist", reslist, { NO, NO, NO, NO }, 186215976Sjmallett { "", "", "", "" }, 187215976Sjmallett "show ntpd access control list" }, 188215976Sjmallett { "sysinfo", sysinfo, { NO, NO, NO, NO }, 189215976Sjmallett { "", "", "", "" }, 190215976Sjmallett "display system summary" }, 191215976Sjmallett { "kerninfo", kerninfo, { NO, NO, NO, NO }, 192215976Sjmallett { "", "", "", "" }, 193215976Sjmallett "display kernel loop and PPS statistics" }, 194215976Sjmallett { "sysstats", sysstats, { NO, NO, NO, NO }, 195215976Sjmallett { "", "", "", "" }, 196215976Sjmallett "display system uptime and packet counts" }, 197215976Sjmallett { "monstats", monstats, { NO, NO, NO, NO }, 198215976Sjmallett { "", "", "", "" }, 199215976Sjmallett "display monitor (mrulist) counters and limits" }, 200215976Sjmallett { "authinfo", authinfo, { NO, NO, NO, NO }, 201215976Sjmallett { "", "", "", "" }, 202215976Sjmallett "display symmetric authentication counters" }, 203215976Sjmallett { "iostats", iostats, { NO, NO, NO, NO }, 204215976Sjmallett { "", "", "", "" }, 205215976Sjmallett "display network input and output counters" }, 206215976Sjmallett { "timerstats", timerstats, { NO, NO, NO, NO }, 207215976Sjmallett { "", "", "", "" }, 208215976Sjmallett "display interval timer counters" }, 209215976Sjmallett { 0, 0, { NO, NO, NO, NO }, 210215976Sjmallett { "-4|-6", "", "", "" }, "" } 211215976Sjmallett}; 212215976Sjmallett 213215976Sjmallett 214215976Sjmallett/* 215215976Sjmallett * Variable list data space 216215976Sjmallett */ 217215976Sjmallett#define MAXLINE 512 /* maximum length of a line */ 218215976Sjmallett#define MAXLIST 128 /* maximum variables in list */ 219215976Sjmallett#define LENHOSTNAME 256 /* host name limit */ 220215976Sjmallett 221215976Sjmallett#define MRU_GOT_COUNT 0x1 222215976Sjmallett#define MRU_GOT_LAST 0x2 223215976Sjmallett#define MRU_GOT_FIRST 0x4 224215976Sjmallett#define MRU_GOT_MV 0x8 225215976Sjmallett#define MRU_GOT_RS 0x10 226215976Sjmallett#define MRU_GOT_ADDR 0x20 227215976Sjmallett#define MRU_GOT_ALL (MRU_GOT_COUNT | MRU_GOT_LAST | MRU_GOT_FIRST \ 228215976Sjmallett | MRU_GOT_MV | MRU_GOT_RS | MRU_GOT_ADDR) 229215976Sjmallett 230215976Sjmallett/* 231215976Sjmallett * mrulist() depends on MRUSORT_DEF and MRUSORT_RDEF being the first two 232215976Sjmallett */ 233215976Sjmalletttypedef enum mru_sort_order_tag { 234215976Sjmallett MRUSORT_DEF = 0, /* lstint ascending */ 235215976Sjmallett MRUSORT_R_DEF, /* lstint descending */ 236215976Sjmallett MRUSORT_AVGINT, /* avgint ascending */ 237215976Sjmallett MRUSORT_R_AVGINT, /* avgint descending */ 238215976Sjmallett MRUSORT_ADDR, /* IPv4 asc. then IPv6 asc. */ 239215976Sjmallett MRUSORT_R_ADDR, /* IPv6 desc. then IPv4 desc. */ 240215976Sjmallett MRUSORT_COUNT, /* hit count ascending */ 241215976Sjmallett MRUSORT_R_COUNT, /* hit count descending */ 242215976Sjmallett MRUSORT_MAX, /* special: count of this enum */ 243215976Sjmallett} mru_sort_order; 244215976Sjmallett 245215976Sjmallettconst char * const mru_sort_keywords[MRUSORT_MAX] = { 246215976Sjmallett "lstint", /* MRUSORT_DEF */ 247215976Sjmallett "-lstint", /* MRUSORT_R_DEF */ 248215976Sjmallett "avgint", /* MRUSORT_AVGINT */ 249215976Sjmallett "-avgint", /* MRUSORT_R_AVGINT */ 250215976Sjmallett "addr", /* MRUSORT_ADDR */ 251215976Sjmallett "-addr", /* MRUSORT_R_ADDR */ 252215976Sjmallett "count", /* MRUSORT_COUNT */ 253215976Sjmallett "-count", /* MRUSORT_R_COUNT */ 254215976Sjmallett}; 255215976Sjmallett 256215976Sjmalletttypedef int (*qsort_cmp)(const void *, const void *); 257215976Sjmallett 258215976Sjmallett/* 259215976Sjmallett * Old CTL_PST defines for version 2. 260215976Sjmallett */ 261215976Sjmallett#define OLD_CTL_PST_CONFIG 0x80 262215976Sjmallett#define OLD_CTL_PST_AUTHENABLE 0x40 263215976Sjmallett#define OLD_CTL_PST_AUTHENTIC 0x20 264215976Sjmallett#define OLD_CTL_PST_REACH 0x10 265215976Sjmallett#define OLD_CTL_PST_SANE 0x08 266215976Sjmallett#define OLD_CTL_PST_DISP 0x04 267215976Sjmallett 268215976Sjmallett#define OLD_CTL_PST_SEL_REJECT 0 269215976Sjmallett#define OLD_CTL_PST_SEL_SELCAND 1 270215976Sjmallett#define OLD_CTL_PST_SEL_SYNCCAND 2 271215976Sjmallett#define OLD_CTL_PST_SEL_SYSPEER 3 272215976Sjmallett 273215976Sjmallettchar flash2[] = " .+* "; /* flash decode for version 2 */ 274215976Sjmallettchar flash3[] = " x.-+#*o"; /* flash decode for peer status version 3 */ 275215976Sjmallett 276215976Sjmallettstruct varlist { 277215976Sjmallett const char *name; 278215976Sjmallett char *value; 279215976Sjmallett} g_varlist[MAXLIST] = { { 0, 0 } }; 280215976Sjmallett 281215976Sjmallett/* 282215976Sjmallett * Imported from ntpq.c 283215976Sjmallett */ 284215976Sjmallettextern int showhostnames; 285215976Sjmallettextern int wideremote; 286215976Sjmallettextern int rawmode; 287215976Sjmallettextern struct servent *server_entry; 288215976Sjmallettextern struct association *assoc_cache; 289215976Sjmallettextern u_char pktversion; 290215976Sjmallett 291215976Sjmalletttypedef struct mru_tag mru; 292215976Sjmallettstruct mru_tag { 293215976Sjmallett mru * hlink; /* next in hash table bucket */ 294215976Sjmallett DECL_DLIST_LINK(mru, mlink); 295215976Sjmallett int count; 296215976Sjmallett l_fp last; 297215976Sjmallett l_fp first; 298215976Sjmallett u_char mode; 299215976Sjmallett u_char ver; 300215976Sjmallett u_short rs; 301215976Sjmallett sockaddr_u addr; 302215976Sjmallett}; 303215976Sjmallett 304215976Sjmalletttypedef struct ifstats_row_tag { 305215976Sjmallett u_int ifnum; 306215976Sjmallett sockaddr_u addr; 307215976Sjmallett sockaddr_u bcast; 308215976Sjmallett int enabled; 309215976Sjmallett u_int flags; 310215976Sjmallett int mcast_count; 311215976Sjmallett char name[32]; 312215976Sjmallett int peer_count; 313215976Sjmallett int received; 314215976Sjmallett int sent; 315215976Sjmallett int send_errors; 316215976Sjmallett u_int ttl; 317215976Sjmallett u_int uptime; 318215976Sjmallett} ifstats_row; 319215976Sjmallett 320215976Sjmalletttypedef struct reslist_row_tag { 321215976Sjmallett u_int idx; 322215976Sjmallett sockaddr_u addr; 323215976Sjmallett sockaddr_u mask; 324215976Sjmallett u_long hits; 325215976Sjmallett char flagstr[128]; 326215976Sjmallett} reslist_row; 327215976Sjmallett 328215976Sjmalletttypedef struct var_display_collection_tag { 329215976Sjmallett const char * const tag; /* system variable */ 330215976Sjmallett const char * const display; /* descriptive text */ 331215976Sjmallett u_char type; /* NTP_STR, etc */ 332215976Sjmallett union { 333215976Sjmallett char * str; 334215976Sjmallett sockaddr_u sau; /* NTP_ADD */ 335215976Sjmallett l_fp lfp; /* NTP_LFP */ 336215976Sjmallett } v; /* retrieved value */ 337215976Sjmallett} vdc; 338215976Sjmallett#if !defined(MISSING_C99_STRUCT_INIT) 339215976Sjmallett# define VDC_INIT(a, b, c) { .tag = a, .display = b, .type = c } 340215976Sjmallett#else 341215976Sjmallett# define VDC_INIT(a, b, c) { a, b, c } 342215976Sjmallett#endif 343215976Sjmallett/* 344215976Sjmallett * other local function prototypes 345215976Sjmallett */ 346215976Sjmallettstatic int mrulist_ctrl_c_hook(void); 347215976Sjmallettstatic mru * add_mru(mru *); 348215976Sjmallettstatic int collect_mru_list(const char *, l_fp *); 349215976Sjmallettstatic int fetch_nonce(char *, size_t); 350215976Sjmallettstatic int qcmp_mru_avgint(const void *, const void *); 351215976Sjmallettstatic int qcmp_mru_r_avgint(const void *, const void *); 352215976Sjmallettstatic int qcmp_mru_addr(const void *, const void *); 353215976Sjmallettstatic int qcmp_mru_r_addr(const void *, const void *); 354215976Sjmallettstatic int qcmp_mru_count(const void *, const void *); 355215976Sjmallettstatic int qcmp_mru_r_count(const void *, const void *); 356215976Sjmallettstatic void validate_ifnum(FILE *, u_int, int *, ifstats_row *); 357215976Sjmallettstatic void another_ifstats_field(int *, ifstats_row *, FILE *); 358215976Sjmallettstatic void collect_display_vdc(associd_t as, vdc *table, 359215976Sjmallett int decodestatus, FILE *fp); 360215976Sjmallett 361215976Sjmallett/* 362215976Sjmallett * static globals 363215976Sjmallett */ 364215976Sjmallettstatic u_int mru_count; 365215976Sjmallettstatic u_int mru_dupes; 366215976Sjmallettvolatile int mrulist_interrupted; 367215976Sjmallettstatic mru mru_list; /* listhead */ 368215976Sjmallettstatic mru ** hash_table; 369215976Sjmallett 370215976Sjmallett/* 371215976Sjmallett * qsort comparison function table for mrulist(). The first two 372215976Sjmallett * entries are NULL because they are handled without qsort(). 373215976Sjmallett */ 374215976Sjmallettstatic const qsort_cmp mru_qcmp_table[MRUSORT_MAX] = { 375215976Sjmallett NULL, /* MRUSORT_DEF unused */ 376215976Sjmallett NULL, /* MRUSORT_R_DEF unused */ 377215976Sjmallett &qcmp_mru_avgint, /* MRUSORT_AVGINT */ 378215976Sjmallett &qcmp_mru_r_avgint, /* MRUSORT_R_AVGINT */ 379215976Sjmallett &qcmp_mru_addr, /* MRUSORT_ADDR */ 380215976Sjmallett &qcmp_mru_r_addr, /* MRUSORT_R_ADDR */ 381215976Sjmallett &qcmp_mru_count, /* MRUSORT_COUNT */ 382215976Sjmallett &qcmp_mru_r_count, /* MRUSORT_R_COUNT */ 383215976Sjmallett}; 384215976Sjmallett 385215976Sjmallett/* 386215976Sjmallett * checkassocid - return the association ID, checking to see if it is valid 387215976Sjmallett */ 388215976Sjmallettstatic associd_t 389215976Sjmallettcheckassocid( 390215976Sjmallett u_int32 value 391215976Sjmallett ) 392215976Sjmallett{ 393215976Sjmallett associd_t associd; 394215976Sjmallett u_long ulvalue; 395215976Sjmallett 396215976Sjmallett associd = (associd_t)value; 397215976Sjmallett if (0 == associd || value != associd) { 398215976Sjmallett ulvalue = value; 399215976Sjmallett fprintf(stderr, 400215976Sjmallett "***Invalid association ID %lu specified\n", 401215976Sjmallett ulvalue); 402215976Sjmallett return 0; 403215976Sjmallett } 404215976Sjmallett 405215976Sjmallett return associd; 406215976Sjmallett} 407215976Sjmallett 408215976Sjmallett 409215976Sjmallett/* 410215976Sjmallett * findlistvar - Look for the named variable in a varlist. If found, 411215976Sjmallett * return a pointer to it. Otherwise, if the list has 412215976Sjmallett * slots available, return the pointer to the first free 413215976Sjmallett * slot, or NULL if it's full. 414215976Sjmallett */ 415215976Sjmallettstatic struct varlist * 416215976Sjmallettfindlistvar( 417215976Sjmallett struct varlist *list, 418215976Sjmallett char *name 419215976Sjmallett ) 420215976Sjmallett{ 421215976Sjmallett struct varlist *vl; 422215976Sjmallett 423215976Sjmallett for (vl = list; vl < list + MAXLIST && vl->name != NULL; vl++) 424215976Sjmallett if (!strcmp(name, vl->name)) 425215976Sjmallett return vl; 426215976Sjmallett if (vl < list + MAXLIST) 427215976Sjmallett return vl; 428215976Sjmallett 429215976Sjmallett return NULL; 430215976Sjmallett} 431215976Sjmallett 432215976Sjmallett 433215976Sjmallett/* 434215976Sjmallett * doaddvlist - add variable(s) to the variable list 435215976Sjmallett */ 436215976Sjmallettstatic void 437215976Sjmallettdoaddvlist( 438215976Sjmallett struct varlist *vlist, 439215976Sjmallett const char *vars 440215976Sjmallett ) 441215976Sjmallett{ 442215976Sjmallett struct varlist *vl; 443215976Sjmallett size_t len; 444215976Sjmallett char *name; 445215976Sjmallett char *value; 446215976Sjmallett 447215976Sjmallett len = strlen(vars); 448215976Sjmallett while (nextvar(&len, &vars, &name, &value)) { 449215976Sjmallett vl = findlistvar(vlist, name); 450215976Sjmallett if (NULL == vl) { 451215976Sjmallett fprintf(stderr, "Variable list full\n"); 452215976Sjmallett return; 453215976Sjmallett } 454215976Sjmallett 455215976Sjmallett if (NULL == vl->name) { 456215976Sjmallett vl->name = estrdup(name); 457215976Sjmallett } else if (vl->value != NULL) { 458215976Sjmallett free(vl->value); 459215976Sjmallett vl->value = NULL; 460215976Sjmallett } 461215976Sjmallett 462215976Sjmallett if (value != NULL) 463215976Sjmallett vl->value = estrdup(value); 464215976Sjmallett } 465215976Sjmallett} 466215976Sjmallett 467215976Sjmallett 468215976Sjmallett/* 469215976Sjmallett * dormvlist - remove variable(s) from the variable list 470215976Sjmallett */ 471215976Sjmallettstatic void 472215976Sjmallettdormvlist( 473215976Sjmallett struct varlist *vlist, 474215976Sjmallett const char *vars 475215976Sjmallett ) 476215976Sjmallett{ 477215976Sjmallett struct varlist *vl; 478215976Sjmallett size_t len; 479215976Sjmallett char *name; 480215976Sjmallett char *value; 481215976Sjmallett 482215976Sjmallett len = strlen(vars); 483215976Sjmallett while (nextvar(&len, &vars, &name, &value)) { 484215976Sjmallett vl = findlistvar(vlist, name); 485215976Sjmallett if (vl == 0 || vl->name == 0) { 486215976Sjmallett (void) fprintf(stderr, "Variable `%s' not found\n", 487215976Sjmallett name); 488215976Sjmallett } else { 489215976Sjmallett free((void *)(intptr_t)vl->name); 490215976Sjmallett if (vl->value != 0) 491215976Sjmallett free(vl->value); 492215976Sjmallett for ( ; (vl+1) < (g_varlist + MAXLIST) 493215976Sjmallett && (vl+1)->name != 0; vl++) { 494215976Sjmallett vl->name = (vl+1)->name; 495215976Sjmallett vl->value = (vl+1)->value; 496215976Sjmallett } 497215976Sjmallett vl->name = vl->value = 0; 498215976Sjmallett } 499215976Sjmallett } 500215976Sjmallett} 501215976Sjmallett 502215976Sjmallett 503215976Sjmallett/* 504215976Sjmallett * doclearvlist - clear a variable list 505215976Sjmallett */ 506215976Sjmallettstatic void 507215976Sjmallettdoclearvlist( 508215976Sjmallett struct varlist *vlist 509215976Sjmallett ) 510215976Sjmallett{ 511215976Sjmallett register struct varlist *vl; 512215976Sjmallett 513215976Sjmallett for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) { 514215976Sjmallett free((void *)(intptr_t)vl->name); 515215976Sjmallett vl->name = 0; 516215976Sjmallett if (vl->value != 0) { 517215976Sjmallett free(vl->value); 518215976Sjmallett vl->value = 0; 519215976Sjmallett } 520215976Sjmallett } 521215976Sjmallett} 522215976Sjmallett 523215976Sjmallett 524215976Sjmallett/* 525215976Sjmallett * makequerydata - form a data buffer to be included with a query 526215976Sjmallett */ 527215976Sjmallettstatic void 528215976Sjmallettmakequerydata( 529215976Sjmallett struct varlist *vlist, 530215976Sjmallett size_t *datalen, 531215976Sjmallett char *data 532215976Sjmallett ) 533215976Sjmallett{ 534215976Sjmallett register struct varlist *vl; 535215976Sjmallett register char *cp, *cpend; 536215976Sjmallett register size_t namelen, valuelen; 537215976Sjmallett register size_t totallen; 538215976Sjmallett 539215976Sjmallett cp = data; 540215976Sjmallett cpend = data + *datalen; 541215976Sjmallett 542215976Sjmallett for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) { 543215976Sjmallett namelen = strlen(vl->name); 544215976Sjmallett if (vl->value == 0) 545215976Sjmallett valuelen = 0; 546215976Sjmallett else 547215976Sjmallett valuelen = strlen(vl->value); 548215976Sjmallett totallen = namelen + valuelen + (valuelen != 0) + (cp != data); 549215976Sjmallett if (cp + totallen > cpend) { 550215976Sjmallett fprintf(stderr, 551215976Sjmallett "***Ignoring variables starting with `%s'\n", 552215976Sjmallett vl->name); 553215976Sjmallett break; 554215976Sjmallett } 555215976Sjmallett 556215976Sjmallett if (cp != data) 557215976Sjmallett *cp++ = ','; 558215976Sjmallett memcpy(cp, vl->name, (size_t)namelen); 559215976Sjmallett cp += namelen; 560215976Sjmallett if (valuelen != 0) { 561215976Sjmallett *cp++ = '='; 562215976Sjmallett memcpy(cp, vl->value, (size_t)valuelen); 563215976Sjmallett cp += valuelen; 564215976Sjmallett } 565215976Sjmallett } 566215976Sjmallett *datalen = (size_t)(cp - data); 567215976Sjmallett} 568215976Sjmallett 569215976Sjmallett 570215976Sjmallett/* 571215976Sjmallett * doquerylist - send a message including variables in a list 572215976Sjmallett */ 573215976Sjmallettstatic int 574215976Sjmallettdoquerylist( 575215976Sjmallett struct varlist *vlist, 576215976Sjmallett int op, 577215976Sjmallett associd_t associd, 578215976Sjmallett int auth, 579215976Sjmallett u_short *rstatus, 580215976Sjmallett size_t *dsize, 581215976Sjmallett const char **datap 582215976Sjmallett ) 583215976Sjmallett{ 584215976Sjmallett char data[CTL_MAX_DATA_LEN]; 585215976Sjmallett size_t datalen; 586215976Sjmallett 587215976Sjmallett datalen = sizeof(data); 588215976Sjmallett makequerydata(vlist, &datalen, data); 589215976Sjmallett 590215976Sjmallett return doquery(op, associd, auth, datalen, data, rstatus, dsize, 591215976Sjmallett datap); 592215976Sjmallett} 593215976Sjmallett 594215976Sjmallett 595215976Sjmallett/* 596215976Sjmallett * doprintvlist - print the variables on a list 597215976Sjmallett */ 598215976Sjmallettstatic void 599215976Sjmallettdoprintvlist( 600215976Sjmallett struct varlist *vlist, 601215976Sjmallett FILE *fp 602215976Sjmallett ) 603215976Sjmallett{ 604215976Sjmallett size_t n; 605215976Sjmallett 606215976Sjmallett if (NULL == vlist->name) { 607215976Sjmallett fprintf(fp, "No variables on list\n"); 608215976Sjmallett return; 609215976Sjmallett } 610215976Sjmallett for (n = 0; n < MAXLIST && vlist[n].name != NULL; n++) { 611215976Sjmallett if (NULL == vlist[n].value) 612215976Sjmallett fprintf(fp, "%s\n", vlist[n].name); 613215976Sjmallett else 614215976Sjmallett fprintf(fp, "%s=%s\n", vlist[n].name, 615215976Sjmallett vlist[n].value); 616215976Sjmallett } 617215976Sjmallett} 618215976Sjmallett 619215976Sjmallett/* 620215976Sjmallett * addvars - add variables to the variable list 621215976Sjmallett */ 622215976Sjmallett/*ARGSUSED*/ 623215976Sjmallettstatic void 624215976Sjmallettaddvars( 625215976Sjmallett struct parse *pcmd, 626215976Sjmallett FILE *fp 627215976Sjmallett ) 628215976Sjmallett{ 629215976Sjmallett doaddvlist(g_varlist, pcmd->argval[0].string); 630215976Sjmallett} 631215976Sjmallett 632215976Sjmallett 633215976Sjmallett/* 634215976Sjmallett * rmvars - remove variables from the variable list 635215976Sjmallett */ 636215976Sjmallett/*ARGSUSED*/ 637215976Sjmallettstatic void 638215976Sjmallettrmvars( 639215976Sjmallett struct parse *pcmd, 640215976Sjmallett FILE *fp 641215976Sjmallett ) 642215976Sjmallett{ 643215976Sjmallett dormvlist(g_varlist, pcmd->argval[0].string); 644215976Sjmallett} 645215976Sjmallett 646215976Sjmallett 647215976Sjmallett/* 648215976Sjmallett * clearvars - clear the variable list 649215976Sjmallett */ 650215976Sjmallett/*ARGSUSED*/ 651215976Sjmallettstatic void 652215976Sjmallettclearvars( 653215976Sjmallett struct parse *pcmd, 654215976Sjmallett FILE *fp 655215976Sjmallett ) 656215976Sjmallett{ 657215976Sjmallett doclearvlist(g_varlist); 658215976Sjmallett} 659215976Sjmallett 660215976Sjmallett 661215976Sjmallett/* 662215976Sjmallett * showvars - show variables on the variable list 663215976Sjmallett */ 664215976Sjmallett/*ARGSUSED*/ 665215976Sjmallettstatic void 666215976Sjmallettshowvars( 667215976Sjmallett struct parse *pcmd, 668215976Sjmallett FILE *fp 669215976Sjmallett ) 670215976Sjmallett{ 671215976Sjmallett doprintvlist(g_varlist, fp); 672215976Sjmallett} 673215976Sjmallett 674215976Sjmallett 675215976Sjmallett/* 676215976Sjmallett * dolist - send a request with the given list of variables 677215976Sjmallett */ 678215976Sjmallettstatic int 679215976Sjmallettdolist( 680215976Sjmallett struct varlist *vlist, 681215976Sjmallett associd_t associd, 682215976Sjmallett int op, 683215976Sjmallett int type, 684215976Sjmallett FILE *fp 685215976Sjmallett ) 686215976Sjmallett{ 687215976Sjmallett const char *datap; 688215976Sjmallett int res; 689215976Sjmallett size_t dsize; 690215976Sjmallett u_short rstatus; 691215976Sjmallett int quiet; 692215976Sjmallett 693215976Sjmallett /* 694215976Sjmallett * if we're asking for specific variables don't include the 695215976Sjmallett * status header line in the output. 696215976Sjmallett */ 697215976Sjmallett if (old_rv) 698215976Sjmallett quiet = 0; 699215976Sjmallett else 700215976Sjmallett quiet = (vlist->name != NULL); 701215976Sjmallett 702215976Sjmallett res = doquerylist(vlist, op, associd, 0, &rstatus, &dsize, &datap); 703215976Sjmallett 704215976Sjmallett if (res != 0) 705215976Sjmallett return 0; 706215976Sjmallett 707215976Sjmallett if (numhosts > 1) 708215976Sjmallett fprintf(fp, "server=%s ", currenthost); 709215976Sjmallett if (dsize == 0) { 710215976Sjmallett if (associd == 0) 711215976Sjmallett fprintf(fp, "No system%s variables returned\n", 712215976Sjmallett (type == TYPE_CLOCK) ? " clock" : ""); 713215976Sjmallett else 714215976Sjmallett fprintf(fp, 715215976Sjmallett "No information returned for%s association %u\n", 716215976Sjmallett (type == TYPE_CLOCK) ? " clock" : "", 717215976Sjmallett associd); 718215976Sjmallett return 1; 719215976Sjmallett } 720215976Sjmallett 721215976Sjmallett if (!quiet) 722215976Sjmallett fprintf(fp, "associd=%u ", associd); 723215976Sjmallett printvars(dsize, datap, (int)rstatus, type, quiet, fp); 724215976Sjmallett return 1; 725215976Sjmallett} 726215976Sjmallett 727215976Sjmallett 728215976Sjmallett/* 729215976Sjmallett * readlist - send a read variables request with the variables on the list 730215976Sjmallett */ 731215976Sjmallettstatic void 732215976Sjmallettreadlist( 733215976Sjmallett struct parse *pcmd, 734215976Sjmallett FILE *fp 735215976Sjmallett ) 736215976Sjmallett{ 737215976Sjmallett associd_t associd; 738215976Sjmallett int type; 739215976Sjmallett 740215976Sjmallett if (pcmd->nargs == 0) { 741215976Sjmallett associd = 0; 742215976Sjmallett } else { 743215976Sjmallett /* HMS: I think we want the u_int32 target here, not the u_long */ 744215976Sjmallett if (pcmd->argval[0].uval == 0) 745215976Sjmallett associd = 0; 746215976Sjmallett else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0) 747215976Sjmallett return; 748215976Sjmallett } 749215976Sjmallett 750215976Sjmallett type = (0 == associd) 751215976Sjmallett ? TYPE_SYS 752215976Sjmallett : TYPE_PEER; 753215976Sjmallett dolist(g_varlist, associd, CTL_OP_READVAR, type, fp); 754215976Sjmallett} 755215976Sjmallett 756215976Sjmallett 757215976Sjmallett/* 758215976Sjmallett * writelist - send a write variables request with the variables on the list 759215976Sjmallett */ 760215976Sjmallettstatic void 761215976Sjmallettwritelist( 762215976Sjmallett struct parse *pcmd, 763215976Sjmallett FILE *fp 764215976Sjmallett ) 765215976Sjmallett{ 766215976Sjmallett const char *datap; 767215976Sjmallett int res; 768215976Sjmallett associd_t associd; 769215976Sjmallett size_t dsize; 770215976Sjmallett u_short rstatus; 771215976Sjmallett 772215976Sjmallett if (pcmd->nargs == 0) { 773215976Sjmallett associd = 0; 774215976Sjmallett } else { 775215976Sjmallett /* HMS: Do we really want uval here? */ 776215976Sjmallett if (pcmd->argval[0].uval == 0) 777215976Sjmallett associd = 0; 778215976Sjmallett else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0) 779215976Sjmallett return; 780215976Sjmallett } 781215976Sjmallett 782215976Sjmallett res = doquerylist(g_varlist, CTL_OP_WRITEVAR, associd, 1, &rstatus, 783215976Sjmallett &dsize, &datap); 784215976Sjmallett 785215976Sjmallett if (res != 0) 786215976Sjmallett return; 787215976Sjmallett 788215976Sjmallett if (numhosts > 1) 789215976Sjmallett (void) fprintf(fp, "server=%s ", currenthost); 790215976Sjmallett if (dsize == 0) 791215976Sjmallett (void) fprintf(fp, "done! (no data returned)\n"); 792215976Sjmallett else { 793215976Sjmallett (void) fprintf(fp,"associd=%u ", associd); 794215976Sjmallett printvars(dsize, datap, (int)rstatus, 795215976Sjmallett (associd != 0) ? TYPE_PEER : TYPE_SYS, 0, fp); 796215976Sjmallett } 797215976Sjmallett return; 798215976Sjmallett} 799215976Sjmallett 800215976Sjmallett 801215976Sjmallett/* 802215976Sjmallett * readvar - send a read variables request with the specified variables 803215976Sjmallett */ 804215976Sjmallettstatic void 805215976Sjmallettreadvar( 806215976Sjmallett struct parse *pcmd, 807215976Sjmallett FILE *fp 808215976Sjmallett ) 809215976Sjmallett{ 810215976Sjmallett associd_t associd; 811215976Sjmallett size_t tmpcount; 812215976Sjmallett size_t u; 813215976Sjmallett int type; 814215976Sjmallett struct varlist tmplist[MAXLIST]; 815215976Sjmallett 816215976Sjmallett 817215976Sjmallett /* HMS: uval? */ 818215976Sjmallett if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0) 819215976Sjmallett associd = 0; 820215976Sjmallett else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0) 821215976Sjmallett return; 822215976Sjmallett 823215976Sjmallett ZERO(tmplist); 824215976Sjmallett if (pcmd->nargs > 1) { 825215976Sjmallett tmpcount = pcmd->nargs - 1; 826215976Sjmallett for (u = 0; u < tmpcount; u++) 827215976Sjmallett doaddvlist(tmplist, pcmd->argval[1 + u].string); 828215976Sjmallett } 829215976Sjmallett 830215976Sjmallett type = (0 == associd) 831215976Sjmallett ? TYPE_SYS 832215976Sjmallett : TYPE_PEER; 833215976Sjmallett dolist(tmplist, associd, CTL_OP_READVAR, type, fp); 834215976Sjmallett 835215976Sjmallett doclearvlist(tmplist); 836215976Sjmallett} 837215976Sjmallett 838215976Sjmallett 839215976Sjmallett/* 840215976Sjmallett * writevar - send a write variables request with the specified variables 841215976Sjmallett */ 842215976Sjmallettstatic void 843215976Sjmallettwritevar( 844215976Sjmallett struct parse *pcmd, 845215976Sjmallett FILE *fp 846215976Sjmallett ) 847215976Sjmallett{ 848215976Sjmallett const char *datap; 849215976Sjmallett int res; 850215976Sjmallett associd_t associd; 851215976Sjmallett int type; 852215976Sjmallett size_t dsize; 853215976Sjmallett u_short rstatus; 854215976Sjmallett struct varlist tmplist[MAXLIST]; 855215976Sjmallett 856215976Sjmallett /* HMS: uval? */ 857215976Sjmallett if (pcmd->argval[0].uval == 0) 858215976Sjmallett associd = 0; 859215976Sjmallett else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0) 860215976Sjmallett return; 861215976Sjmallett 862215976Sjmallett ZERO(tmplist); 863215976Sjmallett doaddvlist(tmplist, pcmd->argval[1].string); 864215976Sjmallett 865215976Sjmallett res = doquerylist(tmplist, CTL_OP_WRITEVAR, associd, 1, &rstatus, 866215976Sjmallett &dsize, &datap); 867215976Sjmallett 868215976Sjmallett doclearvlist(tmplist); 869215976Sjmallett 870215976Sjmallett if (res != 0) 871215976Sjmallett return; 872215976Sjmallett 873215976Sjmallett if (numhosts > 1) 874215976Sjmallett fprintf(fp, "server=%s ", currenthost); 875215976Sjmallett if (dsize == 0) 876215976Sjmallett fprintf(fp, "done! (no data returned)\n"); 877215976Sjmallett else { 878215976Sjmallett fprintf(fp,"associd=%u ", associd); 879215976Sjmallett type = (0 == associd) 880215976Sjmallett ? TYPE_SYS 881215976Sjmallett : TYPE_PEER; 882215976Sjmallett printvars(dsize, datap, (int)rstatus, type, 0, fp); 883215976Sjmallett } 884215976Sjmallett return; 885215976Sjmallett} 886215976Sjmallett 887215976Sjmallett 888215976Sjmallett/* 889215976Sjmallett * clocklist - send a clock variables request with the variables on the list 890215976Sjmallett */ 891215976Sjmallettstatic void 892215976Sjmallettclocklist( 893215976Sjmallett struct parse *pcmd, 894215976Sjmallett FILE *fp 895215976Sjmallett ) 896215976Sjmallett{ 897215976Sjmallett associd_t associd; 898215976Sjmallett 899215976Sjmallett /* HMS: uval? */ 900215976Sjmallett if (pcmd->nargs == 0) { 901215976Sjmallett associd = 0; 902215976Sjmallett } else { 903215976Sjmallett if (pcmd->argval[0].uval == 0) 904215976Sjmallett associd = 0; 905215976Sjmallett else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0) 906215976Sjmallett return; 907215976Sjmallett } 908215976Sjmallett 909215976Sjmallett dolist(g_varlist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp); 910215976Sjmallett} 911215976Sjmallett 912215976Sjmallett 913215976Sjmallett/* 914215976Sjmallett * clockvar - send a clock variables request with the specified variables 915215976Sjmallett */ 916215976Sjmallettstatic void 917215976Sjmallettclockvar( 918215976Sjmallett struct parse *pcmd, 919215976Sjmallett FILE *fp 920215976Sjmallett ) 921215976Sjmallett{ 922215976Sjmallett associd_t associd; 923215976Sjmallett struct varlist tmplist[MAXLIST]; 924215976Sjmallett 925215976Sjmallett /* HMS: uval? */ 926215976Sjmallett if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0) 927215976Sjmallett associd = 0; 928215976Sjmallett else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0) 929215976Sjmallett return; 930215976Sjmallett 931215976Sjmallett ZERO(tmplist); 932215976Sjmallett if (pcmd->nargs >= 2) 933215976Sjmallett doaddvlist(tmplist, pcmd->argval[1].string); 934215976Sjmallett 935215976Sjmallett dolist(tmplist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp); 936215976Sjmallett 937215976Sjmallett doclearvlist(tmplist); 938215976Sjmallett} 939215976Sjmallett 940215976Sjmallett 941215976Sjmallett/* 942215976Sjmallett * findassidrange - verify a range of association ID's 943215976Sjmallett */ 944215976Sjmallettstatic int 945215976Sjmallettfindassidrange( 946215976Sjmallett u_int32 assid1, 947215976Sjmallett u_int32 assid2, 948215976Sjmallett int * from, 949215976Sjmallett int * to, 950215976Sjmallett FILE * fp 951215976Sjmallett ) 952215976Sjmallett{ 953215976Sjmallett associd_t assids[2]; 954215976Sjmallett int ind[COUNTOF(assids)]; 955215976Sjmallett u_int i; 956215976Sjmallett size_t a; 957215976Sjmallett 958215976Sjmallett 959215976Sjmallett if (0 == numassoc) 960215976Sjmallett dogetassoc(fp); 961215976Sjmallett 962215976Sjmallett assids[0] = checkassocid(assid1); 963215976Sjmallett if (0 == assids[0]) 964215976Sjmallett return 0; 965215976Sjmallett assids[1] = checkassocid(assid2); 966215976Sjmallett if (0 == assids[1]) 967215976Sjmallett return 0; 968215976Sjmallett 969215976Sjmallett for (a = 0; a < COUNTOF(assids); a++) { 970215976Sjmallett ind[a] = -1; 971215976Sjmallett for (i = 0; i < numassoc; i++) 972215976Sjmallett if (assoc_cache[i].assid == assids[a]) 973215976Sjmallett ind[a] = i; 974215976Sjmallett } 975215976Sjmallett for (a = 0; a < COUNTOF(assids); a++) 976215976Sjmallett if (-1 == ind[a]) { 977215976Sjmallett fprintf(stderr, 978215976Sjmallett "***Association ID %u not found in list\n", 979215976Sjmallett assids[a]); 980215976Sjmallett return 0; 981215976Sjmallett } 982215976Sjmallett 983215976Sjmallett if (ind[0] < ind[1]) { 984215976Sjmallett *from = ind[0]; 985215976Sjmallett *to = ind[1]; 986215976Sjmallett } else { 987215976Sjmallett *to = ind[0]; 988215976Sjmallett *from = ind[1]; 989215976Sjmallett } 990215976Sjmallett return 1; 991215976Sjmallett} 992215976Sjmallett 993215976Sjmallett 994215976Sjmallett 995215976Sjmallett/* 996215976Sjmallett * mreadlist - send a read variables request for multiple associations 997215976Sjmallett */ 998215976Sjmallettstatic void 999215976Sjmallettmreadlist( 1000215976Sjmallett struct parse *pcmd, 1001215976Sjmallett FILE *fp 1002215976Sjmallett ) 1003215976Sjmallett{ 1004215976Sjmallett int i; 1005215976Sjmallett int from; 1006215976Sjmallett int to; 1007215976Sjmallett 1008215976Sjmallett if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval, 1009215976Sjmallett &from, &to, fp)) 1010215976Sjmallett return; 1011215976Sjmallett 1012215976Sjmallett for (i = from; i <= to; i++) { 1013215976Sjmallett if (i != from) 1014215976Sjmallett fprintf(fp, "\n"); 1015215976Sjmallett if (!dolist(g_varlist, assoc_cache[i].assid, 1016215976Sjmallett CTL_OP_READVAR, TYPE_PEER, fp)) 1017215976Sjmallett return; 1018215976Sjmallett } 1019215976Sjmallett return; 1020215976Sjmallett} 1021215976Sjmallett 1022215976Sjmallett 1023215976Sjmallett/* 1024215976Sjmallett * mreadvar - send a read variables request for multiple associations 1025215976Sjmallett */ 1026215976Sjmallettstatic void 1027215976Sjmallettmreadvar( 1028215976Sjmallett struct parse *pcmd, 1029215976Sjmallett FILE *fp 1030215976Sjmallett ) 1031215976Sjmallett{ 1032215976Sjmallett int i; 1033215976Sjmallett int from; 1034215976Sjmallett int to; 1035215976Sjmallett struct varlist tmplist[MAXLIST]; 1036215976Sjmallett struct varlist *pvars; 1037215976Sjmallett 1038215976Sjmallett if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval, 1039215976Sjmallett &from, &to, fp)) 1040215976Sjmallett return; 1041215976Sjmallett 1042215976Sjmallett ZERO(tmplist); 1043215976Sjmallett if (pcmd->nargs >= 3) { 1044215976Sjmallett doaddvlist(tmplist, pcmd->argval[2].string); 1045215976Sjmallett pvars = tmplist; 1046215976Sjmallett } else { 1047215976Sjmallett pvars = g_varlist; 1048215976Sjmallett } 1049215976Sjmallett 1050215976Sjmallett for (i = from; i <= to; i++) { 1051215976Sjmallett if (!dolist(pvars, assoc_cache[i].assid, CTL_OP_READVAR, 1052215976Sjmallett TYPE_PEER, fp)) 1053215976Sjmallett break; 1054215976Sjmallett } 1055215976Sjmallett 1056215976Sjmallett if (pvars == tmplist) 1057215976Sjmallett doclearvlist(tmplist); 1058215976Sjmallett 1059215976Sjmallett return; 1060215976Sjmallett} 1061215976Sjmallett 1062215976Sjmallett 1063215976Sjmallett/* 1064215976Sjmallett * dogetassoc - query the host for its list of associations 1065215976Sjmallett */ 1066215976Sjmallettint 1067215976Sjmallettdogetassoc( 1068215976Sjmallett FILE *fp 1069215976Sjmallett ) 1070215976Sjmallett{ 1071215976Sjmallett const char *datap; 1072215976Sjmallett const u_short *pus; 1073215976Sjmallett int res; 1074215976Sjmallett size_t dsize; 1075215976Sjmallett u_short rstatus; 1076215976Sjmallett 1077215976Sjmallett res = doquery(CTL_OP_READSTAT, 0, 0, 0, (char *)0, &rstatus, 1078215976Sjmallett &dsize, &datap); 1079215976Sjmallett 1080215976Sjmallett if (res != 0) 1081215976Sjmallett return 0; 1082215976Sjmallett 1083215976Sjmallett if (dsize == 0) { 1084215976Sjmallett if (numhosts > 1) 1085215976Sjmallett fprintf(fp, "server=%s ", currenthost); 1086215976Sjmallett fprintf(fp, "No association ID's returned\n"); 1087215976Sjmallett return 0; 1088215976Sjmallett } 1089215976Sjmallett 1090215976Sjmallett if (dsize & 0x3) { 1091215976Sjmallett if (numhosts > 1) 1092215976Sjmallett fprintf(stderr, "server=%s ", currenthost); 1093215976Sjmallett fprintf(stderr, 1094215976Sjmallett "***Server returned %zu octets, should be multiple of 4\n", 1095215976Sjmallett dsize); 1096215976Sjmallett return 0; 1097215976Sjmallett } 1098215976Sjmallett 1099215976Sjmallett numassoc = 0; 1100215976Sjmallett 1101215976Sjmallett while (dsize > 0) { 1102215976Sjmallett if (numassoc >= assoc_cache_slots) { 1103215976Sjmallett grow_assoc_cache(); 1104215976Sjmallett } 1105215976Sjmallett pus = (const void *)datap; 1106215976Sjmallett assoc_cache[numassoc].assid = ntohs(*pus); 1107215976Sjmallett datap += sizeof(*pus); 1108215976Sjmallett pus = (const void *)datap; 1109215976Sjmallett assoc_cache[numassoc].status = ntohs(*pus); 1110215976Sjmallett datap += sizeof(*pus); 1111215976Sjmallett dsize -= 2 * sizeof(*pus); 1112215976Sjmallett if (debug) { 1113215976Sjmallett fprintf(stderr, "[%u] ", 1114215976Sjmallett assoc_cache[numassoc].assid); 1115215976Sjmallett } 1116215976Sjmallett numassoc++; 1117215976Sjmallett } 1118215976Sjmallett if (debug) { 1119215976Sjmallett fprintf(stderr, "\n%d associations total\n", numassoc); 1120215976Sjmallett } 1121215976Sjmallett sortassoc(); 1122215976Sjmallett return 1; 1123215976Sjmallett} 1124215976Sjmallett 1125215976Sjmallett 1126215976Sjmallett/* 1127215976Sjmallett * printassoc - print the current list of associations 1128215976Sjmallett */ 1129215976Sjmallettstatic void 1130215976Sjmallettprintassoc( 1131215976Sjmallett int showall, 1132215976Sjmallett FILE *fp 1133215976Sjmallett ) 1134215976Sjmallett{ 1135215976Sjmallett register char *bp; 1136215976Sjmallett u_int i; 1137215976Sjmallett u_char statval; 1138215976Sjmallett int event; 1139215976Sjmallett u_long event_count; 1140215976Sjmallett const char *conf; 1141215976Sjmallett const char *reach; 1142215976Sjmallett const char *auth; 1143215976Sjmallett const char *condition = ""; 1144215976Sjmallett const char *last_event; 1145215976Sjmallett char buf[128]; 1146215976Sjmallett 1147215976Sjmallett if (numassoc == 0) { 1148215976Sjmallett (void) fprintf(fp, "No association ID's in list\n"); 1149215976Sjmallett return; 1150215976Sjmallett } 1151215976Sjmallett 1152215976Sjmallett /* 1153215976Sjmallett * Output a header 1154215976Sjmallett */ 1155215976Sjmallett (void) fprintf(fp, 1156215976Sjmallett "\nind assid status conf reach auth condition last_event cnt\n"); 1157215976Sjmallett (void) fprintf(fp, 1158215976Sjmallett "===========================================================\n"); 1159215976Sjmallett for (i = 0; i < numassoc; i++) { 1160215976Sjmallett statval = (u_char) CTL_PEER_STATVAL(assoc_cache[i].status); 1161215976Sjmallett if (!showall && !(statval & (CTL_PST_CONFIG|CTL_PST_REACH))) 1162215976Sjmallett continue; 1163215976Sjmallett event = CTL_PEER_EVENT(assoc_cache[i].status); 1164215976Sjmallett event_count = CTL_PEER_NEVNT(assoc_cache[i].status); 1165215976Sjmallett if (statval & CTL_PST_CONFIG) 1166215976Sjmallett conf = "yes"; 1167215976Sjmallett else 1168215976Sjmallett conf = "no"; 1169215976Sjmallett if (statval & CTL_PST_BCAST) { 1170215976Sjmallett reach = "none"; 1171215976Sjmallett if (statval & CTL_PST_AUTHENABLE) 1172215976Sjmallett auth = "yes"; 1173215976Sjmallett else 1174215976Sjmallett auth = "none"; 1175215976Sjmallett } else { 1176215976Sjmallett if (statval & CTL_PST_REACH) 1177215976Sjmallett reach = "yes"; 1178215976Sjmallett else 1179215976Sjmallett reach = "no"; 1180215976Sjmallett if (statval & CTL_PST_AUTHENABLE) { 1181215976Sjmallett if (statval & CTL_PST_AUTHENTIC) 1182215976Sjmallett auth = "ok "; 1183215976Sjmallett else 1184215976Sjmallett auth = "bad"; 1185215976Sjmallett } else { 1186215976Sjmallett auth = "none"; 1187215976Sjmallett } 1188215976Sjmallett } 1189215976Sjmallett if (pktversion > NTP_OLDVERSION) { 1190215976Sjmallett switch (statval & 0x7) { 1191215976Sjmallett 1192215976Sjmallett case CTL_PST_SEL_REJECT: 1193215976Sjmallett condition = "reject"; 1194215976Sjmallett break; 1195215976Sjmallett 1196215976Sjmallett case CTL_PST_SEL_SANE: 1197215976Sjmallett condition = "falsetick"; 1198215976Sjmallett break; 1199215976Sjmallett 1200215976Sjmallett case CTL_PST_SEL_CORRECT: 1201215976Sjmallett condition = "excess"; 1202215976Sjmallett break; 1203215976Sjmallett 1204215976Sjmallett case CTL_PST_SEL_SELCAND: 1205215976Sjmallett condition = "outlier"; 1206215976Sjmallett break; 1207215976Sjmallett 1208215976Sjmallett case CTL_PST_SEL_SYNCCAND: 1209215976Sjmallett condition = "candidate"; 1210215976Sjmallett break; 1211215976Sjmallett 1212215976Sjmallett case CTL_PST_SEL_EXCESS: 1213215976Sjmallett condition = "backup"; 1214215976Sjmallett break; 1215215976Sjmallett 1216215976Sjmallett case CTL_PST_SEL_SYSPEER: 1217215976Sjmallett condition = "sys.peer"; 1218215976Sjmallett break; 1219215976Sjmallett 1220215976Sjmallett case CTL_PST_SEL_PPS: 1221215976Sjmallett condition = "pps.peer"; 1222215976Sjmallett break; 1223215976Sjmallett } 1224215976Sjmallett } else { 1225215976Sjmallett switch (statval & 0x3) { 1226215976Sjmallett 1227215976Sjmallett case OLD_CTL_PST_SEL_REJECT: 1228215976Sjmallett if (!(statval & OLD_CTL_PST_SANE)) 1229215976Sjmallett condition = "insane"; 1230215976Sjmallett else if (!(statval & OLD_CTL_PST_DISP)) 1231215976Sjmallett condition = "hi_disp"; 1232215976Sjmallett else 1233215976Sjmallett condition = ""; 1234215976Sjmallett break; 1235215976Sjmallett 1236215976Sjmallett case OLD_CTL_PST_SEL_SELCAND: 1237215976Sjmallett condition = "sel_cand"; 1238215976Sjmallett break; 1239215976Sjmallett 1240215976Sjmallett case OLD_CTL_PST_SEL_SYNCCAND: 1241215976Sjmallett condition = "sync_cand"; 1242215976Sjmallett break; 1243215976Sjmallett 1244215976Sjmallett case OLD_CTL_PST_SEL_SYSPEER: 1245215976Sjmallett condition = "sys_peer"; 1246215976Sjmallett break; 1247215976Sjmallett } 1248215976Sjmallett } 1249215976Sjmallett switch (PEER_EVENT|event) { 1250215976Sjmallett 1251215976Sjmallett case PEVNT_MOBIL: 1252215976Sjmallett last_event = "mobilize"; 1253215976Sjmallett break; 1254215976Sjmallett 1255215976Sjmallett case PEVNT_DEMOBIL: 1256215976Sjmallett last_event = "demobilize"; 1257215976Sjmallett break; 1258215976Sjmallett 1259215976Sjmallett case PEVNT_REACH: 1260215976Sjmallett last_event = "reachable"; 1261215976Sjmallett break; 1262215976Sjmallett 1263215976Sjmallett case PEVNT_UNREACH: 1264215976Sjmallett last_event = "unreachable"; 1265215976Sjmallett break; 1266215976Sjmallett 1267215976Sjmallett case PEVNT_RESTART: 1268215976Sjmallett last_event = "restart"; 1269215976Sjmallett break; 1270215976Sjmallett 1271215976Sjmallett case PEVNT_REPLY: 1272215976Sjmallett last_event = "no_reply"; 1273215976Sjmallett break; 1274215976Sjmallett 1275215976Sjmallett case PEVNT_RATE: 1276215976Sjmallett last_event = "rate_exceeded"; 1277215976Sjmallett break; 1278215976Sjmallett 1279215976Sjmallett case PEVNT_DENY: 1280215976Sjmallett last_event = "access_denied"; 1281215976Sjmallett break; 1282215976Sjmallett 1283215976Sjmallett case PEVNT_ARMED: 1284215976Sjmallett last_event = "leap_armed"; 1285215976Sjmallett break; 1286215976Sjmallett 1287215976Sjmallett case PEVNT_NEWPEER: 1288215976Sjmallett last_event = "sys_peer"; 1289215976Sjmallett break; 1290215976Sjmallett 1291215976Sjmallett case PEVNT_CLOCK: 1292215976Sjmallett last_event = "clock_alarm"; 1293215976Sjmallett break; 1294215976Sjmallett 1295215976Sjmallett default: 1296215976Sjmallett last_event = ""; 1297215976Sjmallett break; 1298215976Sjmallett } 1299215976Sjmallett snprintf(buf, sizeof(buf), 1300215976Sjmallett "%3d %5u %04x %3.3s %4s %4.4s %9.9s %11s %2lu", 1301215976Sjmallett i + 1, assoc_cache[i].assid, 1302215976Sjmallett assoc_cache[i].status, conf, reach, auth, 1303215976Sjmallett condition, last_event, event_count); 1304215976Sjmallett bp = buf + strlen(buf); 1305215976Sjmallett while (bp > buf && ' ' == bp[-1]) 1306215976Sjmallett --bp; 1307215976Sjmallett bp[0] = '\0'; 1308215976Sjmallett fprintf(fp, "%s\n", buf); 1309215976Sjmallett } 1310215976Sjmallett} 1311215976Sjmallett 1312215976Sjmallett 1313215976Sjmallett/* 1314215976Sjmallett * associations - get, record and print a list of associations 1315215976Sjmallett */ 1316215976Sjmallett/*ARGSUSED*/ 1317215976Sjmallettstatic void 1318215976Sjmallettassociations( 1319215976Sjmallett struct parse *pcmd, 1320215976Sjmallett FILE *fp 1321215976Sjmallett ) 1322215976Sjmallett{ 1323215976Sjmallett if (dogetassoc(fp)) 1324215976Sjmallett printassoc(0, fp); 1325215976Sjmallett} 1326215976Sjmallett 1327215976Sjmallett 1328215976Sjmallett/* 1329215976Sjmallett * lassociations - get, record and print a long list of associations 1330215976Sjmallett */ 1331215976Sjmallett/*ARGSUSED*/ 1332215976Sjmallettstatic void 1333215976Sjmallettlassociations( 1334215976Sjmallett struct parse *pcmd, 1335215976Sjmallett FILE *fp 1336215976Sjmallett ) 1337215976Sjmallett{ 1338215976Sjmallett if (dogetassoc(fp)) 1339215976Sjmallett printassoc(1, fp); 1340215976Sjmallett} 1341215976Sjmallett 1342215976Sjmallett 1343215976Sjmallett/* 1344215976Sjmallett * passociations - print the association list 1345215976Sjmallett */ 1346215976Sjmallett/*ARGSUSED*/ 1347215976Sjmallettstatic void 1348215976Sjmallettpassociations( 1349215976Sjmallett struct parse *pcmd, 1350215976Sjmallett FILE *fp 1351215976Sjmallett ) 1352215976Sjmallett{ 1353215976Sjmallett printassoc(0, fp); 1354215976Sjmallett} 1355215976Sjmallett 1356215976Sjmallett 1357215976Sjmallett/* 1358215976Sjmallett * lpassociations - print the long association list 1359215976Sjmallett */ 1360215976Sjmallett/*ARGSUSED*/ 1361215976Sjmallettstatic void 1362215976Sjmallettlpassociations( 1363215976Sjmallett struct parse *pcmd, 1364215976Sjmallett FILE *fp 1365215976Sjmallett ) 1366215976Sjmallett{ 1367215976Sjmallett printassoc(1, fp); 1368215976Sjmallett} 1369215976Sjmallett 1370215976Sjmallett 1371215976Sjmallett/* 1372215976Sjmallett * saveconfig - dump ntp server configuration to server file 1373215976Sjmallett */ 1374215976Sjmallettstatic void 1375215976Sjmallettsaveconfig( 1376215976Sjmallett struct parse *pcmd, 1377215976Sjmallett FILE *fp 1378215976Sjmallett ) 1379215976Sjmallett{ 1380215976Sjmallett const char *datap; 1381215976Sjmallett int res; 1382215976Sjmallett size_t dsize; 1383215976Sjmallett u_short rstatus; 1384215976Sjmallett 1385215976Sjmallett if (0 == pcmd->nargs) 1386215976Sjmallett return; 1387215976Sjmallett 1388215976Sjmallett res = doquery(CTL_OP_SAVECONFIG, 0, 1, 1389215976Sjmallett strlen(pcmd->argval[0].string), 1390215976Sjmallett pcmd->argval[0].string, &rstatus, &dsize, 1391215976Sjmallett &datap); 1392215976Sjmallett 1393215976Sjmallett if (res != 0) 1394215976Sjmallett return; 1395215976Sjmallett 1396215976Sjmallett if (0 == dsize) 1397215976Sjmallett fprintf(fp, "(no response message, curiously)"); 1398215976Sjmallett else 1399215976Sjmallett fprintf(fp, "%.*s", (int)dsize, datap); /* cast is wobbly */ 1400215976Sjmallett} 1401215976Sjmallett 1402215976Sjmallett 1403215976Sjmallett#ifdef UNUSED 1404215976Sjmallett/* 1405215976Sjmallett * radiostatus - print the radio status returned by the server 1406215976Sjmallett */ 1407215976Sjmallett/*ARGSUSED*/ 1408215976Sjmallettstatic void 1409215976Sjmallettradiostatus( 1410215976Sjmallett struct parse *pcmd, 1411215976Sjmallett FILE *fp 1412215976Sjmallett ) 1413215976Sjmallett{ 1414215976Sjmallett char *datap; 1415215976Sjmallett int res; 1416215976Sjmallett int dsize; 1417215976Sjmallett u_short rstatus; 1418215976Sjmallett 1419215976Sjmallett res = doquery(CTL_OP_READCLOCK, 0, 0, 0, (char *)0, &rstatus, 1420215976Sjmallett &dsize, &datap); 1421215976Sjmallett 1422215976Sjmallett if (res != 0) 1423215976Sjmallett return; 1424215976Sjmallett 1425215976Sjmallett if (numhosts > 1) 1426215976Sjmallett (void) fprintf(fp, "server=%s ", currenthost); 1427215976Sjmallett if (dsize == 0) { 1428215976Sjmallett (void) fprintf(fp, "No radio status string returned\n"); 1429215976Sjmallett return; 1430215976Sjmallett } 1431215976Sjmallett 1432215976Sjmallett asciize(dsize, datap, fp); 1433215976Sjmallett} 1434215976Sjmallett#endif /* UNUSED */ 1435215976Sjmallett 1436215976Sjmallett/* 1437215976Sjmallett * when - print how long its been since his last packet arrived 1438215976Sjmallett */ 1439215976Sjmallettstatic long 1440215976Sjmallettwhen( 1441215976Sjmallett l_fp *ts, 1442215976Sjmallett l_fp *rec, 1443215976Sjmallett l_fp *reftime 1444215976Sjmallett ) 1445215976Sjmallett{ 1446215976Sjmallett l_fp *lasttime; 1447215976Sjmallett 1448215976Sjmallett if (rec->l_ui != 0) 1449215976Sjmallett lasttime = rec; 1450215976Sjmallett else if (reftime->l_ui != 0) 1451215976Sjmallett lasttime = reftime; 1452215976Sjmallett else 1453215976Sjmallett return 0; 1454215976Sjmallett 1455215976Sjmallett return (ts->l_ui - lasttime->l_ui); 1456215976Sjmallett} 1457215976Sjmallett 1458215976Sjmallett 1459215976Sjmallett/* 1460215976Sjmallett * Pretty-print an interval into the given buffer, in a human-friendly format. 1461215976Sjmallett */ 1462215976Sjmallettstatic char * 1463215976Sjmallettprettyinterval( 1464215976Sjmallett char *buf, 1465215976Sjmallett size_t cb, 1466215976Sjmallett long diff 1467215976Sjmallett ) 1468215976Sjmallett{ 1469215976Sjmallett if (diff <= 0) { 1470215976Sjmallett buf[0] = '-'; 1471215976Sjmallett buf[1] = 0; 1472215976Sjmallett return buf; 1473215976Sjmallett } 1474215976Sjmallett 1475215976Sjmallett if (diff <= 2048) { 1476215976Sjmallett snprintf(buf, cb, "%ld", diff); 1477215976Sjmallett return buf; 1478215976Sjmallett } 1479215976Sjmallett 1480215976Sjmallett diff = (diff + 29) / 60; 1481215976Sjmallett if (diff <= 300) { 1482215976Sjmallett snprintf(buf, cb, "%ldm", diff); 1483215976Sjmallett return buf; 1484215976Sjmallett } 1485215976Sjmallett 1486215976Sjmallett diff = (diff + 29) / 60; 1487215976Sjmallett if (diff <= 96) { 1488215976Sjmallett snprintf(buf, cb, "%ldh", diff); 1489215976Sjmallett return buf; 1490215976Sjmallett } 1491215976Sjmallett 1492215976Sjmallett diff = (diff + 11) / 24; 1493215976Sjmallett snprintf(buf, cb, "%ldd", diff); 1494215976Sjmallett return buf; 1495215976Sjmallett} 1496215976Sjmallett 1497215976Sjmallettstatic char 1498215976Sjmallettdecodeaddrtype( 1499215976Sjmallett sockaddr_u *sock 1500215976Sjmallett ) 1501215976Sjmallett{ 1502215976Sjmallett char ch = '-'; 1503215976Sjmallett u_int32 dummy; 1504215976Sjmallett 1505215976Sjmallett switch(AF(sock)) { 1506215976Sjmallett case AF_INET: 1507215976Sjmallett dummy = SRCADR(sock); 1508215976Sjmallett ch = (char)(((dummy&0xf0000000)==0xe0000000) ? 'm' : 1509215976Sjmallett ((dummy&0x000000ff)==0x000000ff) ? 'b' : 1510215976Sjmallett ((dummy&0xffffffff)==0x7f000001) ? 'l' : 1511215976Sjmallett ((dummy&0xffffffe0)==0x00000000) ? '-' : 1512215976Sjmallett 'u'); 1513215976Sjmallett break; 1514215976Sjmallett case AF_INET6: 1515215976Sjmallett if (IN6_IS_ADDR_MULTICAST(PSOCK_ADDR6(sock))) 1516215976Sjmallett ch = 'm'; 1517215976Sjmallett else 1518215976Sjmallett ch = 'u'; 1519215976Sjmallett break; 1520215976Sjmallett default: 1521215976Sjmallett ch = '-'; 1522215976Sjmallett break; 1523215976Sjmallett } 1524215976Sjmallett return ch; 1525215976Sjmallett} 1526215976Sjmallett 1527215976Sjmallett/* 1528215976Sjmallett * A list of variables required by the peers command 1529215976Sjmallett */ 1530215976Sjmallettstruct varlist opeervarlist[] = { 1531215976Sjmallett { "srcadr", 0 }, /* 0 */ 1532215976Sjmallett { "dstadr", 0 }, /* 1 */ 1533215976Sjmallett { "stratum", 0 }, /* 2 */ 1534215976Sjmallett { "hpoll", 0 }, /* 3 */ 1535215976Sjmallett { "ppoll", 0 }, /* 4 */ 1536215976Sjmallett { "reach", 0 }, /* 5 */ 1537215976Sjmallett { "delay", 0 }, /* 6 */ 1538215976Sjmallett { "offset", 0 }, /* 7 */ 1539215976Sjmallett { "jitter", 0 }, /* 8 */ 1540215976Sjmallett { "dispersion", 0 }, /* 9 */ 1541215976Sjmallett { "rec", 0 }, /* 10 */ 1542215976Sjmallett { "reftime", 0 }, /* 11 */ 1543215976Sjmallett { "srcport", 0 }, /* 12 */ 1544215976Sjmallett { "hmode", 0 }, /* 13 */ 1545215976Sjmallett { 0, 0 } 1546215976Sjmallett}; 1547215976Sjmallett 1548215976Sjmallettstruct varlist peervarlist[] = { 1549215976Sjmallett { "srcadr", 0 }, /* 0 */ 1550215976Sjmallett { "refid", 0 }, /* 1 */ 1551215976Sjmallett { "stratum", 0 }, /* 2 */ 1552215976Sjmallett { "hpoll", 0 }, /* 3 */ 1553215976Sjmallett { "ppoll", 0 }, /* 4 */ 1554215976Sjmallett { "reach", 0 }, /* 5 */ 1555215976Sjmallett { "delay", 0 }, /* 6 */ 1556215976Sjmallett { "offset", 0 }, /* 7 */ 1557215976Sjmallett { "jitter", 0 }, /* 8 */ 1558215976Sjmallett { "dispersion", 0 }, /* 9 */ 1559215976Sjmallett { "rec", 0 }, /* 10 */ 1560215976Sjmallett { "reftime", 0 }, /* 11 */ 1561215976Sjmallett { "srcport", 0 }, /* 12 */ 1562215976Sjmallett { "hmode", 0 }, /* 13 */ 1563215976Sjmallett { "srchost", 0 }, /* 14 */ 1564215976Sjmallett { 0, 0 } 1565215976Sjmallett}; 1566215976Sjmallett 1567215976Sjmallettstruct varlist apeervarlist[] = { 1568215976Sjmallett { "srcadr", 0 }, /* 0 */ 1569215976Sjmallett { "refid", 0 }, /* 1 */ 1570215976Sjmallett { "assid", 0 }, /* 2 */ 1571215976Sjmallett { "stratum", 0 }, /* 3 */ 1572215976Sjmallett { "hpoll", 0 }, /* 4 */ 1573215976Sjmallett { "ppoll", 0 }, /* 5 */ 1574215976Sjmallett { "reach", 0 }, /* 6 */ 1575215976Sjmallett { "delay", 0 }, /* 7 */ 1576215976Sjmallett { "offset", 0 }, /* 8 */ 1577215976Sjmallett { "jitter", 0 }, /* 9 */ 1578215976Sjmallett { "dispersion", 0 }, /* 10 */ 1579215976Sjmallett { "rec", 0 }, /* 11 */ 1580215976Sjmallett { "reftime", 0 }, /* 12 */ 1581215976Sjmallett { "srcport", 0 }, /* 13 */ 1582215976Sjmallett { "hmode", 0 }, /* 14 */ 1583215976Sjmallett { "srchost", 0 }, /* 15 */ 1584215976Sjmallett { 0, 0 } 1585215976Sjmallett}; 1586215976Sjmallett 1587215976Sjmallett 1588215976Sjmallett/* 1589215976Sjmallett * Decode an incoming data buffer and print a line in the peer list 1590215976Sjmallett */ 1591215976Sjmallettstatic int 1592215976Sjmallettdoprintpeers( 1593215976Sjmallett struct varlist *pvl, 1594215976Sjmallett int associd, 1595215976Sjmallett int rstatus, 1596215976Sjmallett size_t datalen, 1597215976Sjmallett const char *data, 1598215976Sjmallett FILE *fp, 1599215976Sjmallett int af 1600215976Sjmallett ) 1601215976Sjmallett{ 1602215976Sjmallett char *name; 1603215976Sjmallett char *value = NULL; 1604215976Sjmallett int c; 1605215976Sjmallett size_t len; 1606215976Sjmallett int have_srchost; 1607215976Sjmallett int have_dstadr; 1608215976Sjmallett int have_da_rid; 1609215976Sjmallett int have_jitter; 1610215976Sjmallett sockaddr_u srcadr; 1611215976Sjmallett sockaddr_u dstadr; 1612215976Sjmallett sockaddr_u dum_store; 1613215976Sjmallett sockaddr_u refidadr; 1614215976Sjmallett long hmode = 0; 1615215976Sjmallett u_long srcport = 0; 1616215976Sjmallett u_int32 u32; 1617215976Sjmallett const char *dstadr_refid = "0.0.0.0"; 1618215976Sjmallett const char *serverlocal; 1619215976Sjmallett size_t drlen; 1620215976Sjmallett u_long stratum = 0; 1621215976Sjmallett long ppoll = 0; 1622215976Sjmallett long hpoll = 0; 1623215976Sjmallett u_long reach = 0; 1624215976Sjmallett l_fp estoffset; 1625215976Sjmallett l_fp estdelay; 1626215976Sjmallett l_fp estjitter; 1627215976Sjmallett l_fp estdisp; 1628215976Sjmallett l_fp reftime; 1629215976Sjmallett l_fp rec; 1630215976Sjmallett l_fp ts; 1631215976Sjmallett u_long poll_sec; 1632215976Sjmallett char type = '?'; 1633215976Sjmallett char whenbuf[8], pollbuf[8]; 1634215976Sjmallett char clock_name[LENHOSTNAME]; 1635215976Sjmallett 1636215976Sjmallett get_systime(&ts); 1637215976Sjmallett 1638215976Sjmallett have_srchost = FALSE; 1639215976Sjmallett have_dstadr = FALSE; 1640215976Sjmallett have_da_rid = FALSE; 1641215976Sjmallett have_jitter = FALSE; 1642215976Sjmallett ZERO_SOCK(&srcadr); 1643215976Sjmallett ZERO_SOCK(&dstadr); 1644215976Sjmallett clock_name[0] = '\0'; 1645215976Sjmallett ZERO(estoffset); 1646215976Sjmallett ZERO(estdelay); 1647215976Sjmallett ZERO(estjitter); 1648215976Sjmallett ZERO(estdisp); 1649215976Sjmallett 1650215976Sjmallett while (nextvar(&datalen, &data, &name, &value)) { 1651215976Sjmallett if (!strcmp("srcadr", name) || 1652215976Sjmallett !strcmp("peeradr", name)) { 1653215976Sjmallett if (!decodenetnum(value, &srcadr)) 1654215976Sjmallett fprintf(stderr, "malformed %s=%s\n", 1655215976Sjmallett name, value); 1656215976Sjmallett } else if (!strcmp("srchost", name)) { 1657215976Sjmallett if (pvl == peervarlist || pvl == apeervarlist) { 1658215976Sjmallett len = strlen(value); 1659215976Sjmallett if (2 < len && 1660215976Sjmallett (size_t)len < sizeof(clock_name)) { 1661215976Sjmallett /* strip quotes */ 1662215976Sjmallett value++; 1663215976Sjmallett len -= 2; 1664215976Sjmallett memcpy(clock_name, value, len); 1665215976Sjmallett clock_name[len] = '\0'; 1666215976Sjmallett have_srchost = TRUE; 1667215976Sjmallett } 1668215976Sjmallett } 1669215976Sjmallett } else if (!strcmp("dstadr", name)) { 1670215976Sjmallett if (decodenetnum(value, &dum_store)) { 1671215976Sjmallett type = decodeaddrtype(&dum_store); 1672215976Sjmallett have_dstadr = TRUE; 1673215976Sjmallett dstadr = dum_store; 1674215976Sjmallett if (pvl == opeervarlist) { 1675215976Sjmallett have_da_rid = TRUE; 1676215976Sjmallett dstadr_refid = trunc_left(stoa(&dstadr), 15); 1677215976Sjmallett } 1678215976Sjmallett } 1679215976Sjmallett } else if (!strcmp("hmode", name)) { 1680215976Sjmallett decodeint(value, &hmode); 1681215976Sjmallett } else if (!strcmp("refid", name)) { 1682215976Sjmallett if ( (pvl == peervarlist) 1683215976Sjmallett && (drefid == REFID_IPV4)) { 1684215976Sjmallett have_da_rid = TRUE; 1685215976Sjmallett drlen = strlen(value); 1686215976Sjmallett if (0 == drlen) { 1687215976Sjmallett dstadr_refid = ""; 1688215976Sjmallett } else if (drlen <= 4) { 1689215976Sjmallett ZERO(u32); 1690215976Sjmallett memcpy(&u32, value, drlen); 1691215976Sjmallett dstadr_refid = refid_str(u32, 1); 1692215976Sjmallett } else if (decodenetnum(value, &refidadr)) { 1693215976Sjmallett if (SOCK_UNSPEC(&refidadr)) 1694215976Sjmallett dstadr_refid = "0.0.0.0"; 1695215976Sjmallett else if (ISREFCLOCKADR(&refidadr)) 1696215976Sjmallett dstadr_refid = 1697215976Sjmallett refnumtoa(&refidadr); 1698215976Sjmallett else 1699215976Sjmallett dstadr_refid = 1700215976Sjmallett stoa(&refidadr); 1701215976Sjmallett } else { 1702215976Sjmallett have_da_rid = FALSE; 1703215976Sjmallett } 1704215976Sjmallett } else if ( (pvl == apeervarlist) 1705215976Sjmallett || (pvl == peervarlist)) { 1706215976Sjmallett /* no need to check drefid == REFID_HASH */ 1707215976Sjmallett have_da_rid = TRUE; 1708215976Sjmallett drlen = strlen(value); 1709215976Sjmallett if (0 == drlen) { 1710215976Sjmallett dstadr_refid = ""; 1711215976Sjmallett } else if (drlen <= 4) { 1712215976Sjmallett ZERO(u32); 1713215976Sjmallett memcpy(&u32, value, drlen); 1714215976Sjmallett dstadr_refid = refid_str(u32, 1); 1715215976Sjmallett //fprintf(stderr, "apeervarlist S1 refid: value=<%s>\n", value); 1716215976Sjmallett } else if (decodenetnum(value, &refidadr)) { 1717215976Sjmallett if (SOCK_UNSPEC(&refidadr)) 1718215976Sjmallett dstadr_refid = "0.0.0.0"; 1719215976Sjmallett else if (ISREFCLOCKADR(&refidadr)) 1720215976Sjmallett dstadr_refid = 1721215976Sjmallett refnumtoa(&refidadr); 1722215976Sjmallett else { 1723215976Sjmallett char *buf = emalloc(10); 1724215976Sjmallett int i = ntohl(refidadr.sa4.sin_addr.s_addr); 1725215976Sjmallett 1726215976Sjmallett snprintf(buf, 10, 1727215976Sjmallett "%0x", i); 1728215976Sjmallett dstadr_refid = buf; 1729215976Sjmallett //fprintf(stderr, "apeervarlist refid: value=<%x>\n", i); 1730215976Sjmallett } 1731215976Sjmallett //fprintf(stderr, "apeervarlist refid: value=<%s>\n", value); 1732215976Sjmallett } else { 1733215976Sjmallett have_da_rid = FALSE; 1734215976Sjmallett } 1735215976Sjmallett } 1736215976Sjmallett } else if (!strcmp("stratum", name)) { 1737215976Sjmallett decodeuint(value, &stratum); 1738215976Sjmallett } else if (!strcmp("hpoll", name)) { 1739215976Sjmallett if (decodeint(value, &hpoll) && hpoll < 0) 1740215976Sjmallett hpoll = NTP_MINPOLL; 1741215976Sjmallett } else if (!strcmp("ppoll", name)) { 1742215976Sjmallett if (decodeint(value, &ppoll) && ppoll < 0) 1743215976Sjmallett ppoll = NTP_MINPOLL; 1744215976Sjmallett } else if (!strcmp("reach", name)) { 1745215976Sjmallett decodeuint(value, &reach); 1746215976Sjmallett } else if (!strcmp("delay", name)) { 1747215976Sjmallett decodetime(value, &estdelay); 1748215976Sjmallett } else if (!strcmp("offset", name)) { 1749215976Sjmallett decodetime(value, &estoffset); 1750215976Sjmallett } else if (!strcmp("jitter", name)) { 1751215976Sjmallett if ((pvl == peervarlist || pvl == apeervarlist) 1752215976Sjmallett && decodetime(value, &estjitter)) 1753215976Sjmallett have_jitter = 1; 1754215976Sjmallett } else if (!strcmp("rootdisp", name) || 1755215976Sjmallett !strcmp("dispersion", name)) { 1756215976Sjmallett decodetime(value, &estdisp); 1757215976Sjmallett } else if (!strcmp("rec", name)) { 1758215976Sjmallett decodets(value, &rec); 1759215976Sjmallett } else if (!strcmp("srcport", name) || 1760215976Sjmallett !strcmp("peerport", name)) { 1761215976Sjmallett decodeuint(value, &srcport); 1762215976Sjmallett } else if (!strcmp("reftime", name)) { 1763215976Sjmallett if (!decodets(value, &reftime)) 1764215976Sjmallett L_CLR(&reftime); 1765215976Sjmallett } else { 1766215976Sjmallett // fprintf(stderr, "UNRECOGNIZED name=%s ", name); 1767215976Sjmallett } 1768215976Sjmallett } 1769215976Sjmallett 1770215976Sjmallett /* 1771215976Sjmallett * hmode gives the best guidance for the t column. If the response 1772215976Sjmallett * did not include hmode we'll use the old decodeaddrtype() result. 1773215976Sjmallett */ 1774215976Sjmallett switch (hmode) { 1775215976Sjmallett 1776215976Sjmallett case MODE_BCLIENT: 1777215976Sjmallett /* broadcastclient or multicastclient */ 1778215976Sjmallett type = 'b'; 1779215976Sjmallett break; 1780215976Sjmallett 1781215976Sjmallett case MODE_BROADCAST: 1782215976Sjmallett /* broadcast or multicast server */ 1783215976Sjmallett if (IS_MCAST(&srcadr)) 1784215976Sjmallett type = 'M'; 1785215976Sjmallett else 1786215976Sjmallett type = 'B'; 1787215976Sjmallett break; 1788215976Sjmallett 1789215976Sjmallett case MODE_CLIENT: 1790215976Sjmallett if (ISREFCLOCKADR(&srcadr)) 1791215976Sjmallett type = 'l'; /* local refclock*/ 1792215976Sjmallett else if (SOCK_UNSPEC(&srcadr)) 1793215976Sjmallett type = 'p'; /* pool */ 1794215976Sjmallett else if (IS_MCAST(&srcadr)) 1795215976Sjmallett type = 'a'; /* manycastclient */ 1796215976Sjmallett else 1797215976Sjmallett type = 'u'; /* unicast */ 1798215976Sjmallett break; 1799215976Sjmallett 1800215976Sjmallett case MODE_ACTIVE: 1801215976Sjmallett type = 's'; /* symmetric active */ 1802215976Sjmallett break; /* configured */ 1803215976Sjmallett 1804215976Sjmallett case MODE_PASSIVE: 1805215976Sjmallett type = 'S'; /* symmetric passive */ 1806215976Sjmallett break; /* ephemeral */ 1807215976Sjmallett } 1808215976Sjmallett 1809215976Sjmallett /* 1810215976Sjmallett * Got everything, format the line 1811215976Sjmallett */ 1812215976Sjmallett poll_sec = 1 << min(ppoll, hpoll); 1813215976Sjmallett if (pktversion > NTP_OLDVERSION) 1814215976Sjmallett c = flash3[CTL_PEER_STATVAL(rstatus) & 0x7]; 1815215976Sjmallett else 1816215976Sjmallett c = flash2[CTL_PEER_STATVAL(rstatus) & 0x3]; 1817215976Sjmallett if (numhosts > 1) { 1818215976Sjmallett if ((pvl == peervarlist || pvl == apeervarlist) 1819215976Sjmallett && have_dstadr) { 1820215976Sjmallett serverlocal = nntohost_col(&dstadr, 1821215976Sjmallett (size_t)min(LIB_BUFLENGTH - 1, maxhostlen), 1822215976Sjmallett TRUE); 1823215976Sjmallett } else { 1824215976Sjmallett if (currenthostisnum) 1825215976Sjmallett serverlocal = trunc_left(currenthost, 1826215976Sjmallett maxhostlen); 1827215976Sjmallett else 1828215976Sjmallett serverlocal = currenthost; 1829215976Sjmallett } 1830215976Sjmallett fprintf(fp, "%-*s ", (int)maxhostlen, serverlocal); 1831215976Sjmallett } 1832215976Sjmallett if (AF_UNSPEC == af || AF(&srcadr) == af) { 1833215976Sjmallett if (!have_srchost) 1834215976Sjmallett strlcpy(clock_name, nntohost(&srcadr), 1835215976Sjmallett sizeof(clock_name)); 1836215976Sjmallett if (wideremote && 15 < strlen(clock_name)) 1837215976Sjmallett fprintf(fp, "%c%s\n ", c, clock_name); 1838215976Sjmallett else 1839215976Sjmallett fprintf(fp, "%c%-15.15s ", c, clock_name); 1840215976Sjmallett if (!have_da_rid) { 1841215976Sjmallett drlen = 0; 1842215976Sjmallett } else { 1843215976Sjmallett drlen = strlen(dstadr_refid); 1844215976Sjmallett makeascii(drlen, dstadr_refid, fp); 1845215976Sjmallett } 1846215976Sjmallett if (pvl == apeervarlist) { 1847215976Sjmallett while (drlen++ < 9) 1848215976Sjmallett fputc(' ', fp); 1849215976Sjmallett fprintf(fp, "%-6d", associd); 1850215976Sjmallett } else { 1851215976Sjmallett while (drlen++ < 15) 1852215976Sjmallett fputc(' ', fp); 1853215976Sjmallett } 1854215976Sjmallett fprintf(fp, 1855215976Sjmallett " %2ld %c %4.4s %4.4s %3lo %7.7s %8.7s %7.7s\n", 1856215976Sjmallett stratum, type, 1857215976Sjmallett prettyinterval(whenbuf, sizeof(whenbuf), 1858215976Sjmallett when(&ts, &rec, &reftime)), 1859215976Sjmallett prettyinterval(pollbuf, sizeof(pollbuf), 1860215976Sjmallett (int)poll_sec), 1861215976Sjmallett reach, lfptoms(&estdelay, 3), 1862215976Sjmallett lfptoms(&estoffset, 3), 1863215976Sjmallett (have_jitter) 1864215976Sjmallett ? lfptoms(&estjitter, 3) 1865215976Sjmallett : lfptoms(&estdisp, 3)); 1866215976Sjmallett return (1); 1867215976Sjmallett } 1868215976Sjmallett else 1869215976Sjmallett return(1); 1870215976Sjmallett} 1871215976Sjmallett 1872215976Sjmallett 1873215976Sjmallett/* 1874215976Sjmallett * dogetpeers - given an association ID, read and print the spreadsheet 1875215976Sjmallett * peer variables. 1876215976Sjmallett */ 1877215976Sjmallettstatic int 1878215976Sjmallettdogetpeers( 1879215976Sjmallett struct varlist *pvl, 1880215976Sjmallett associd_t associd, 1881215976Sjmallett FILE *fp, 1882215976Sjmallett int af 1883215976Sjmallett ) 1884215976Sjmallett{ 1885215976Sjmallett const char *datap; 1886215976Sjmallett int res; 1887215976Sjmallett size_t dsize; 1888215976Sjmallett u_short rstatus; 1889215976Sjmallett 1890215976Sjmallett#ifdef notdef 1891215976Sjmallett res = doquerylist(pvl, CTL_OP_READVAR, associd, 0, &rstatus, 1892215976Sjmallett &dsize, &datap); 1893215976Sjmallett#else 1894215976Sjmallett /* 1895215976Sjmallett * Damn fuzzballs 1896215976Sjmallett */ 1897215976Sjmallett res = doquery(CTL_OP_READVAR, associd, 0, 0, NULL, &rstatus, 1898215976Sjmallett &dsize, &datap); 1899215976Sjmallett#endif 1900215976Sjmallett 1901215976Sjmallett if (res != 0) 1902215976Sjmallett return 0; 1903215976Sjmallett 1904215976Sjmallett if (dsize == 0) { 1905215976Sjmallett if (numhosts > 1) 1906215976Sjmallett fprintf(stderr, "server=%s ", currenthost); 1907215976Sjmallett fprintf(stderr, 1908215976Sjmallett "***No information returned for association %u\n", 1909215976Sjmallett associd); 1910215976Sjmallett return 0; 1911215976Sjmallett } 1912215976Sjmallett 1913215976Sjmallett return doprintpeers(pvl, associd, (int)rstatus, dsize, datap, 1914215976Sjmallett fp, af); 1915215976Sjmallett} 1916215976Sjmallett 1917215976Sjmallett 1918215976Sjmallett/* 1919215976Sjmallett * peers - print a peer spreadsheet 1920215976Sjmallett */ 1921215976Sjmallettstatic void 1922215976Sjmallettdopeers( 1923215976Sjmallett int showall, 1924215976Sjmallett FILE *fp, 1925215976Sjmallett int af 1926215976Sjmallett ) 1927215976Sjmallett{ 1928215976Sjmallett u_int u; 1929215976Sjmallett char fullname[LENHOSTNAME]; 1930215976Sjmallett sockaddr_u netnum; 1931215976Sjmallett const char * name_or_num; 1932215976Sjmallett size_t sl; 1933215976Sjmallett 1934215976Sjmallett if (!dogetassoc(fp)) 1935215976Sjmallett return; 1936215976Sjmallett 1937215976Sjmallett for (u = 0; u < numhosts; u++) { 1938215976Sjmallett if (getnetnum(chosts[u].name, &netnum, fullname, af)) { 1939215976Sjmallett name_or_num = nntohost(&netnum); 1940215976Sjmallett sl = strlen(name_or_num); 1941215976Sjmallett maxhostlen = max(maxhostlen, sl); 1942215976Sjmallett } 1943215976Sjmallett } 1944215976Sjmallett if (numhosts > 1) 1945215976Sjmallett fprintf(fp, "%-*.*s ", (int)maxhostlen, (int)maxhostlen, 1946215976Sjmallett "server (local)"); 1947215976Sjmallett fprintf(fp, 1948215976Sjmallett " remote refid st t when poll reach delay offset jitter\n"); 1949215976Sjmallett if (numhosts > 1) 1950215976Sjmallett for (u = 0; u <= maxhostlen; u++) 1951215976Sjmallett fprintf(fp, "="); 1952215976Sjmallett fprintf(fp, 1953215976Sjmallett "==============================================================================\n"); 1954215976Sjmallett 1955215976Sjmallett for (u = 0; u < numassoc; u++) { 1956215976Sjmallett if (!showall && 1957215976Sjmallett !(CTL_PEER_STATVAL(assoc_cache[u].status) 1958215976Sjmallett & (CTL_PST_CONFIG|CTL_PST_REACH))) { 1959215976Sjmallett if (debug) 1960215976Sjmallett fprintf(stderr, "eliding [%d]\n", 1961215976Sjmallett (int)assoc_cache[u].assid); 1962215976Sjmallett continue; 1963215976Sjmallett } 1964215976Sjmallett if (!dogetpeers(peervarlist, (int)assoc_cache[u].assid, 1965215976Sjmallett fp, af)) 1966215976Sjmallett return; 1967215976Sjmallett } 1968215976Sjmallett return; 1969215976Sjmallett} 1970215976Sjmallett 1971215976Sjmallett 1972215976Sjmallett/* 1973215976Sjmallett * doapeers - print a peer spreadsheet with assocIDs 1974215976Sjmallett */ 1975215976Sjmallettstatic void 1976215976Sjmallettdoapeers( 1977215976Sjmallett int showall, 1978215976Sjmallett FILE *fp, 1979215976Sjmallett int af 1980215976Sjmallett ) 1981215976Sjmallett{ 1982215976Sjmallett u_int u; 1983215976Sjmallett char fullname[LENHOSTNAME]; 1984215976Sjmallett sockaddr_u netnum; 1985215976Sjmallett const char * name_or_num; 1986215976Sjmallett size_t sl; 1987215976Sjmallett 1988215976Sjmallett if (!dogetassoc(fp)) 1989215976Sjmallett return; 1990215976Sjmallett 1991215976Sjmallett for (u = 0; u < numhosts; u++) { 1992215976Sjmallett if (getnetnum(chosts[u].name, &netnum, fullname, af)) { 1993215976Sjmallett name_or_num = nntohost(&netnum); 1994215976Sjmallett sl = strlen(name_or_num); 1995215976Sjmallett maxhostlen = max(maxhostlen, sl); 1996215976Sjmallett } 1997215976Sjmallett } 1998215976Sjmallett if (numhosts > 1) 1999215976Sjmallett fprintf(fp, "%-*.*s ", (int)maxhostlen, (int)maxhostlen, 2000215976Sjmallett "server (local)"); 2001215976Sjmallett fprintf(fp, 2002215976Sjmallett " remote refid assid st t when poll reach delay offset jitter\n"); 2003215976Sjmallett if (numhosts > 1) 2004215976Sjmallett for (u = 0; u <= maxhostlen; u++) 2005215976Sjmallett fprintf(fp, "="); 2006215976Sjmallett fprintf(fp, 2007215976Sjmallett "==============================================================================\n"); 2008215976Sjmallett 2009215976Sjmallett for (u = 0; u < numassoc; u++) { 2010215976Sjmallett if (!showall && 2011215976Sjmallett !(CTL_PEER_STATVAL(assoc_cache[u].status) 2012215976Sjmallett & (CTL_PST_CONFIG|CTL_PST_REACH))) { 2013215976Sjmallett if (debug) 2014215976Sjmallett fprintf(stderr, "eliding [%d]\n", 2015215976Sjmallett (int)assoc_cache[u].assid); 2016215976Sjmallett continue; 2017215976Sjmallett } 2018215976Sjmallett if (!dogetpeers(apeervarlist, (int)assoc_cache[u].assid, 2019215976Sjmallett fp, af)) 2020215976Sjmallett return; 2021215976Sjmallett } 2022215976Sjmallett return; 2023215976Sjmallett} 2024215976Sjmallett 2025215976Sjmallett 2026215976Sjmallett/* 2027215976Sjmallett * peers - print a peer spreadsheet 2028215976Sjmallett */ 2029215976Sjmallett/*ARGSUSED*/ 2030215976Sjmallettstatic void 2031215976Sjmallettpeers( 2032215976Sjmallett struct parse *pcmd, 2033215976Sjmallett FILE *fp 2034215976Sjmallett ) 2035215976Sjmallett{ 2036215976Sjmallett if (drefid == REFID_HASH) { 2037215976Sjmallett apeers(pcmd, fp); 2038215976Sjmallett } else { 2039215976Sjmallett int af = 0; 2040215976Sjmallett 2041215976Sjmallett if (pcmd->nargs == 1) { 2042215976Sjmallett if (pcmd->argval->ival == 6) 2043215976Sjmallett af = AF_INET6; 2044215976Sjmallett else 2045215976Sjmallett af = AF_INET; 2046215976Sjmallett } 2047215976Sjmallett dopeers(0, fp, af); 2048215976Sjmallett } 2049215976Sjmallett} 2050215976Sjmallett 2051215976Sjmallett 2052215976Sjmallett/* 2053215976Sjmallett * apeers - print a peer spreadsheet, with assocIDs 2054215976Sjmallett */ 2055215976Sjmallett/*ARGSUSED*/ 2056215976Sjmallettstatic void 2057215976Sjmallettapeers( 2058215976Sjmallett struct parse *pcmd, 2059215976Sjmallett FILE *fp 2060215976Sjmallett ) 2061215976Sjmallett{ 2062215976Sjmallett int af = 0; 2063215976Sjmallett 2064215976Sjmallett if (pcmd->nargs == 1) { 2065215976Sjmallett if (pcmd->argval->ival == 6) 2066215976Sjmallett af = AF_INET6; 2067215976Sjmallett else 2068215976Sjmallett af = AF_INET; 2069215976Sjmallett } 2070215976Sjmallett doapeers(0, fp, af); 2071215976Sjmallett} 2072215976Sjmallett 2073215976Sjmallett 2074215976Sjmallett/* 2075215976Sjmallett * lpeers - print a peer spreadsheet including all fuzzball peers 2076215976Sjmallett */ 2077215976Sjmallett/*ARGSUSED*/ 2078215976Sjmallettstatic void 2079215976Sjmallettlpeers( 2080215976Sjmallett struct parse *pcmd, 2081215976Sjmallett FILE *fp 2082215976Sjmallett ) 2083215976Sjmallett{ 2084215976Sjmallett int af = 0; 2085215976Sjmallett 2086215976Sjmallett if (pcmd->nargs == 1) { 2087215976Sjmallett if (pcmd->argval->ival == 6) 2088215976Sjmallett af = AF_INET6; 2089215976Sjmallett else 2090215976Sjmallett af = AF_INET; 2091215976Sjmallett } 2092215976Sjmallett dopeers(1, fp, af); 2093215976Sjmallett} 2094215976Sjmallett 2095215976Sjmallett 2096215976Sjmallett/* 2097215976Sjmallett * opeers - print a peer spreadsheet 2098215976Sjmallett */ 2099215976Sjmallettstatic void 2100215976Sjmallettdoopeers( 2101215976Sjmallett int showall, 2102215976Sjmallett FILE *fp, 2103215976Sjmallett int af 2104215976Sjmallett ) 2105215976Sjmallett{ 2106215976Sjmallett u_int i; 2107215976Sjmallett char fullname[LENHOSTNAME]; 2108215976Sjmallett sockaddr_u netnum; 2109215976Sjmallett 2110215976Sjmallett if (!dogetassoc(fp)) 2111215976Sjmallett return; 2112215976Sjmallett 2113215976Sjmallett for (i = 0; i < numhosts; ++i) { 2114215976Sjmallett if (getnetnum(chosts[i].name, &netnum, fullname, af)) 2115215976Sjmallett if (strlen(fullname) > maxhostlen) 2116215976Sjmallett maxhostlen = strlen(fullname); 2117215976Sjmallett } 2118215976Sjmallett if (numhosts > 1) 2119215976Sjmallett fprintf(fp, "%-*.*s ", (int)maxhostlen, (int)maxhostlen, 2120215976Sjmallett "server"); 2121215976Sjmallett fprintf(fp, 2122215976Sjmallett " remote local st t when poll reach delay offset disp\n"); 2123215976Sjmallett if (numhosts > 1) 2124215976Sjmallett for (i = 0; i <= maxhostlen; ++i) 2125215976Sjmallett fprintf(fp, "="); 2126215976Sjmallett fprintf(fp, 2127215976Sjmallett "==============================================================================\n"); 2128215976Sjmallett 2129215976Sjmallett for (i = 0; i < numassoc; i++) { 2130215976Sjmallett if (!showall && 2131215976Sjmallett !(CTL_PEER_STATVAL(assoc_cache[i].status) & 2132215976Sjmallett (CTL_PST_CONFIG | CTL_PST_REACH))) 2133215976Sjmallett continue; 2134215976Sjmallett if (!dogetpeers(opeervarlist, assoc_cache[i].assid, fp, af)) 2135215976Sjmallett return; 2136215976Sjmallett } 2137215976Sjmallett return; 2138215976Sjmallett} 2139215976Sjmallett 2140215976Sjmallett 2141215976Sjmallett/* 2142215976Sjmallett * opeers - print a peer spreadsheet the old way 2143215976Sjmallett */ 2144215976Sjmallett/*ARGSUSED*/ 2145215976Sjmallettstatic void 2146215976Sjmallettopeers( 2147215976Sjmallett struct parse *pcmd, 2148215976Sjmallett FILE *fp 2149215976Sjmallett ) 2150215976Sjmallett{ 2151215976Sjmallett int af = 0; 2152215976Sjmallett 2153215976Sjmallett if (pcmd->nargs == 1) { 2154215976Sjmallett if (pcmd->argval->ival == 6) 2155215976Sjmallett af = AF_INET6; 2156215976Sjmallett else 2157215976Sjmallett af = AF_INET; 2158215976Sjmallett } 2159215976Sjmallett doopeers(0, fp, af); 2160215976Sjmallett} 2161215976Sjmallett 2162215976Sjmallett 2163215976Sjmallett/* 2164215976Sjmallett * lopeers - print a peer spreadsheet including all fuzzball peers 2165215976Sjmallett */ 2166215976Sjmallett/*ARGSUSED*/ 2167215976Sjmallettstatic void 2168215976Sjmallettlopeers( 2169215976Sjmallett struct parse *pcmd, 2170215976Sjmallett FILE *fp 2171215976Sjmallett ) 2172215976Sjmallett{ 2173215976Sjmallett int af = 0; 2174215976Sjmallett 2175215976Sjmallett if (pcmd->nargs == 1) { 2176215976Sjmallett if (pcmd->argval->ival == 6) 2177215976Sjmallett af = AF_INET6; 2178215976Sjmallett else 2179215976Sjmallett af = AF_INET; 2180215976Sjmallett } 2181215976Sjmallett doopeers(1, fp, af); 2182215976Sjmallett} 2183215976Sjmallett 2184215976Sjmallett 2185215976Sjmallett/* 2186215976Sjmallett * config - send a configuration command to a remote host 2187215976Sjmallett */ 2188215976Sjmallettstatic void 2189215976Sjmallettconfig ( 2190215976Sjmallett struct parse *pcmd, 2191215976Sjmallett FILE *fp 2192215976Sjmallett ) 2193215976Sjmallett{ 2194215976Sjmallett const char *cfgcmd; 2195215976Sjmallett u_short rstatus; 2196215976Sjmallett size_t rsize; 2197215976Sjmallett const char *rdata; 2198215976Sjmallett char *resp; 2199215976Sjmallett int res; 2200215976Sjmallett int col; 2201215976Sjmallett int i; 2202215976Sjmallett 2203215976Sjmallett cfgcmd = pcmd->argval[0].string; 2204215976Sjmallett 2205215976Sjmallett if (debug > 2) 2206215976Sjmallett fprintf(stderr, 2207215976Sjmallett "In Config\n" 2208215976Sjmallett "Keyword = %s\n" 2209215976Sjmallett "Command = %s\n", pcmd->keyword, cfgcmd); 2210215976Sjmallett 2211215976Sjmallett res = doquery(CTL_OP_CONFIGURE, 0, 1, 2212215976Sjmallett strlen(cfgcmd), cfgcmd, 2213215976Sjmallett &rstatus, &rsize, &rdata); 2214215976Sjmallett 2215215976Sjmallett if (res != 0) 2216215976Sjmallett return; 2217215976Sjmallett 2218215976Sjmallett if (rsize > 0 && '\n' == rdata[rsize - 1]) 2219215976Sjmallett rsize--; 2220215976Sjmallett 2221215976Sjmallett resp = emalloc(rsize + 1); 2222215976Sjmallett memcpy(resp, rdata, rsize); 2223215976Sjmallett resp[rsize] = '\0'; 2224215976Sjmallett 2225215976Sjmallett col = -1; 2226215976Sjmallett if (1 == sscanf(resp, "column %d syntax error", &col) 2227215976Sjmallett && col >= 0 && (size_t)col <= strlen(cfgcmd) + 1) { 2228215976Sjmallett if (interactive) { 2229215976Sjmallett printf("______"); /* "ntpq> " */ 2230215976Sjmallett printf("________"); /* ":config " */ 2231215976Sjmallett } else 2232215976Sjmallett printf("%s\n", cfgcmd); 2233215976Sjmallett for (i = 1; i < col; i++) 2234215976Sjmallett putchar('_'); 2235215976Sjmallett printf("^\n"); 2236215976Sjmallett } 2237215976Sjmallett printf("%s\n", resp); 2238215976Sjmallett free(resp); 2239215976Sjmallett} 2240215976Sjmallett 2241215976Sjmallett 2242215976Sjmallett/* 2243215976Sjmallett * config_from_file - remotely configure an ntpd daemon using the 2244215976Sjmallett * specified configuration file 2245215976Sjmallett * SK: This function is a kludge at best and is full of bad design 2246215976Sjmallett * bugs: 2247215976Sjmallett * 1. ntpq uses UDP, which means that there is no guarantee of in-order, 2248215976Sjmallett * error-free delivery. 2249215976Sjmallett * 2. The maximum length of a packet is constrained, and as a result, the 2250215976Sjmallett * maximum length of a line in a configuration file is constrained. 2251215976Sjmallett * Longer lines will lead to unpredictable results. 2252215976Sjmallett * 3. Since this function is sending a line at a time, we can't update 2253215976Sjmallett * the control key through the configuration file (YUCK!!) 2254215976Sjmallett * 2255215976Sjmallett * Pearly: There are a few places where 'size_t' is cast to 'int' based 2256215976Sjmallett * on the assumption that 'int' can hold the size of the involved 2257215976Sjmallett * buffers without overflow. 2258215976Sjmallett */ 2259215976Sjmallettstatic void 2260215976Sjmallettconfig_from_file ( 2261215976Sjmallett struct parse *pcmd, 2262215976Sjmallett FILE *fp 2263215976Sjmallett ) 2264215976Sjmallett{ 2265215976Sjmallett u_short rstatus; 2266215976Sjmallett size_t rsize; 2267215976Sjmallett const char *rdata; 2268215976Sjmallett char * cp; 2269215976Sjmallett int res; 2270215976Sjmallett FILE *config_fd; 2271215976Sjmallett char config_cmd[MAXLINE]; 2272215976Sjmallett size_t config_len; 2273215976Sjmallett int i; 2274215976Sjmallett int retry_limit; 2275215976Sjmallett 2276215976Sjmallett if (debug > 2) 2277215976Sjmallett fprintf(stderr, 2278215976Sjmallett "In Config\n" 2279215976Sjmallett "Keyword = %s\n" 2280215976Sjmallett "Filename = %s\n", pcmd->keyword, 2281215976Sjmallett pcmd->argval[0].string); 2282215976Sjmallett 2283215976Sjmallett config_fd = fopen(pcmd->argval[0].string, "r"); 2284215976Sjmallett if (NULL == config_fd) { 2285215976Sjmallett printf("ERROR!! Couldn't open file: %s\n", 2286215976Sjmallett pcmd->argval[0].string); 2287215976Sjmallett return; 2288215976Sjmallett } 2289215976Sjmallett 2290215976Sjmallett printf("Sending configuration file, one line at a time.\n"); 2291215976Sjmallett i = 0; 2292215976Sjmallett while (fgets(config_cmd, MAXLINE, config_fd) != NULL) { 2293215976Sjmallett /* Eliminate comments first. */ 2294215976Sjmallett cp = strchr(config_cmd, '#'); 2295215976Sjmallett config_len = (NULL != cp) 2296215976Sjmallett ? (size_t)(cp - config_cmd) 2297215976Sjmallett : strlen(config_cmd); 2298215976Sjmallett 2299215976Sjmallett /* [Bug 3015] make sure there's no trailing whitespace; 2300215976Sjmallett * the fix for [Bug 2853] on the server side forbids 2301215976Sjmallett * those. And don't transmit empty lines, as this would 2302215976Sjmallett * just be waste. 2303215976Sjmallett */ 2304215976Sjmallett while (config_len != 0 && 2305215976Sjmallett (u_char)config_cmd[config_len-1] <= ' ') 2306215976Sjmallett --config_len; 2307215976Sjmallett config_cmd[config_len] = '\0'; 2308215976Sjmallett 2309215976Sjmallett ++i; 2310215976Sjmallett if (0 == config_len) 2311215976Sjmallett continue; 2312215976Sjmallett 2313215976Sjmallett retry_limit = 2; 2314215976Sjmallett do 2315215976Sjmallett res = doquery(CTL_OP_CONFIGURE, 0, 1, 2316215976Sjmallett config_len, config_cmd, 2317215976Sjmallett &rstatus, &rsize, &rdata); 2318215976Sjmallett while (res != 0 && retry_limit--); 2319215976Sjmallett if (res != 0) { 2320215976Sjmallett printf("Line No: %d query failed: %.*s\n" 2321215976Sjmallett "Subsequent lines not sent.\n", 2322215976Sjmallett i, (int)config_len, config_cmd); 2323215976Sjmallett fclose(config_fd); 2324215976Sjmallett return; 2325215976Sjmallett } 2326215976Sjmallett 2327215976Sjmallett /* Right-strip the result code string, then output the 2328215976Sjmallett * last line executed, with result code. */ 2329215976Sjmallett while (rsize != 0 && (u_char)rdata[rsize - 1] <= ' ') 2330215976Sjmallett --rsize; 2331215976Sjmallett printf("Line No: %d %.*s: %.*s\n", i, 2332215976Sjmallett (int)rsize, rdata, 2333215976Sjmallett (int)config_len, config_cmd); 2334215976Sjmallett } 2335215976Sjmallett printf("Done sending file\n"); 2336215976Sjmallett fclose(config_fd); 2337215976Sjmallett} 2338215976Sjmallett 2339215976Sjmallett 2340215976Sjmallettstatic int 2341215976Sjmallettfetch_nonce( 2342215976Sjmallett char * nonce, 2343215976Sjmallett size_t cb_nonce 2344215976Sjmallett ) 2345215976Sjmallett{ 2346215976Sjmallett const char nonce_eq[] = "nonce="; 2347215976Sjmallett int qres; 2348215976Sjmallett u_short rstatus; 2349215976Sjmallett size_t rsize; 2350215976Sjmallett const char * rdata; 2351215976Sjmallett size_t chars; 2352215976Sjmallett 2353215976Sjmallett /* 2354215976Sjmallett * Retrieve a nonce specific to this client to demonstrate to 2355215976Sjmallett * ntpd that we're capable of receiving responses to our source 2356215976Sjmallett * IP address, and thereby unlikely to be forging the source. 2357215976Sjmallett */ 2358215976Sjmallett qres = doquery(CTL_OP_REQ_NONCE, 0, 0, 0, NULL, &rstatus, 2359215976Sjmallett &rsize, &rdata); 2360215976Sjmallett if (qres) { 2361215976Sjmallett fprintf(stderr, "nonce request failed\n"); 2362215976Sjmallett return FALSE; 2363215976Sjmallett } 2364215976Sjmallett 2365215976Sjmallett if ((size_t)rsize <= sizeof(nonce_eq) - 1 || 2366215976Sjmallett strncmp(rdata, nonce_eq, sizeof(nonce_eq) - 1)) { 2367215976Sjmallett fprintf(stderr, "unexpected nonce response format: %.*s\n", 2368215976Sjmallett (int)rsize, rdata); /* cast is wobbly */ 2369215976Sjmallett return FALSE; 2370215976Sjmallett } 2371215976Sjmallett chars = rsize - (sizeof(nonce_eq) - 1); 2372215976Sjmallett if (chars >= (int)cb_nonce) 2373215976Sjmallett return FALSE; 2374215976Sjmallett memcpy(nonce, rdata + sizeof(nonce_eq) - 1, chars); 2375215976Sjmallett nonce[chars] = '\0'; 2376215976Sjmallett while (chars > 0 && 2377215976Sjmallett ('\r' == nonce[chars - 1] || '\n' == nonce[chars - 1])) { 2378215976Sjmallett chars--; 2379215976Sjmallett nonce[chars] = '\0'; 2380215976Sjmallett } 2381215976Sjmallett 2382215976Sjmallett return TRUE; 2383215976Sjmallett} 2384215976Sjmallett 2385215976Sjmallett 2386215976Sjmallett/* 2387215976Sjmallett * add_mru Add and entry to mru list, hash table, and allocate 2388215976Sjmallett * and return a replacement. 2389215976Sjmallett * This is a helper for collect_mru_list(). 2390215976Sjmallett */ 2391215976Sjmallettstatic mru * 2392215976Sjmallettadd_mru( 2393215976Sjmallett mru *add 2394215976Sjmallett ) 2395215976Sjmallett{ 2396215976Sjmallett u_short hash; 2397215976Sjmallett mru *mon; 2398215976Sjmallett mru *unlinked; 2399215976Sjmallett 2400215976Sjmallett 2401215976Sjmallett hash = NTP_HASH_ADDR(&add->addr); 2402215976Sjmallett /* see if we have it among previously received entries */ 2403215976Sjmallett for (mon = hash_table[hash]; mon != NULL; mon = mon->hlink) 2404215976Sjmallett if (SOCK_EQ(&mon->addr, &add->addr)) 2405215976Sjmallett break; 2406215976Sjmallett if (mon != NULL) { 2407215976Sjmallett if (!L_ISGEQ(&add->first, &mon->first)) { 2408215976Sjmallett fprintf(stderr, 2409215976Sjmallett "add_mru duplicate %s new first ts %08x.%08x precedes prior %08x.%08x\n", 2410215976Sjmallett sptoa(&add->addr), add->last.l_ui, 2411215976Sjmallett add->last.l_uf, mon->last.l_ui, 2412215976Sjmallett mon->last.l_uf); 2413215976Sjmallett exit(1); 2414215976Sjmallett } 2415215976Sjmallett UNLINK_DLIST(mon, mlink); 2416215976Sjmallett UNLINK_SLIST(unlinked, hash_table[hash], mon, hlink, mru); 2417215976Sjmallett INSIST(unlinked == mon); 2418215976Sjmallett mru_dupes++; 2419215976Sjmallett TRACE(2, ("(updated from %08x.%08x) ", mon->last.l_ui, 2420215976Sjmallett mon->last.l_uf)); 2421215976Sjmallett } 2422215976Sjmallett LINK_DLIST(mru_list, add, mlink); 2423215976Sjmallett LINK_SLIST(hash_table[hash], add, hlink); 2424215976Sjmallett TRACE(2, ("add_mru %08x.%08x c %d m %d v %d rest %x first %08x.%08x %s\n", 2425215976Sjmallett add->last.l_ui, add->last.l_uf, add->count, 2426215976Sjmallett (int)add->mode, (int)add->ver, (u_int)add->rs, 2427215976Sjmallett add->first.l_ui, add->first.l_uf, sptoa(&add->addr))); 2428215976Sjmallett /* if we didn't update an existing entry, alloc replacement */ 2429215976Sjmallett if (NULL == mon) { 2430215976Sjmallett mon = emalloc(sizeof(*mon)); 2431215976Sjmallett mru_count++; 2432215976Sjmallett } 2433215976Sjmallett ZERO(*mon); 2434215976Sjmallett 2435215976Sjmallett return mon; 2436215976Sjmallett} 2437215976Sjmallett 2438215976Sjmallett 2439215976Sjmallett/* MGOT macro is specific to collect_mru_list() */ 2440215976Sjmallett#define MGOT(bit) \ 2441215976Sjmallett do { \ 2442215976Sjmallett got |= (bit); \ 2443215976Sjmallett if (MRU_GOT_ALL == got) { \ 2444215976Sjmallett got = 0; \ 2445215976Sjmallett mon = add_mru(mon); \ 2446215976Sjmallett ci++; \ 2447215976Sjmallett } \ 2448215976Sjmallett } while (0) 2449215976Sjmallett 2450215976Sjmallett 2451215976Sjmallettint 2452215976Sjmallettmrulist_ctrl_c_hook(void) 2453215976Sjmallett{ 2454215976Sjmallett mrulist_interrupted = TRUE; 2455215976Sjmallett return TRUE; 2456215976Sjmallett} 2457215976Sjmallett 2458215976Sjmallett 2459215976Sjmallettstatic int 2460215976Sjmallettcollect_mru_list( 2461215976Sjmallett const char * parms, 2462215976Sjmallett l_fp * pnow 2463215976Sjmallett ) 2464215976Sjmallett{ 2465215976Sjmallett const u_int sleep_msecs = 5; 2466215976Sjmallett static int ntpd_row_limit = MRU_ROW_LIMIT; 2467215976Sjmallett int c_mru_l_rc; /* this function's return code */ 2468215976Sjmallett u_char got; /* MRU_GOT_* bits */ 2469215976Sjmallett time_t next_report; 2470215976Sjmallett size_t cb; 2471215976Sjmallett mru *mon; 2472215976Sjmallett mru *head; 2473215976Sjmallett mru *recent; 2474215976Sjmallett int list_complete; 2475215976Sjmallett char nonce[128]; 2476215976Sjmallett char buf[128]; 2477215976Sjmallett char req_buf[CTL_MAX_DATA_LEN]; 2478215976Sjmallett char *req; 2479215976Sjmallett char *req_end; 2480215976Sjmallett size_t chars; 2481215976Sjmallett int qres; 2482215976Sjmallett u_short rstatus; 2483215976Sjmallett size_t rsize; 2484215976Sjmallett const char *rdata; 2485215976Sjmallett int limit; 2486215976Sjmallett int frags; 2487215976Sjmallett int cap_frags; 2488215976Sjmallett char *tag; 2489215976Sjmallett char *val; 2490215976Sjmallett int si; /* server index in response */ 2491215976Sjmallett int ci; /* client (our) index for validation */ 2492215976Sjmallett int ri; /* request index (.# suffix) */ 2493215976Sjmallett int mv; 2494215976Sjmallett l_fp newest; 2495215976Sjmallett l_fp last_older; 2496215976Sjmallett sockaddr_u addr_older; 2497215976Sjmallett int have_now; 2498215976Sjmallett int have_addr_older; 2499215976Sjmallett int have_last_older; 2500215976Sjmallett u_int restarted_count; 2501215976Sjmallett u_int nonce_uses; 2502215976Sjmallett u_short hash; 2503215976Sjmallett mru *unlinked; 2504215976Sjmallett 2505215976Sjmallett if (!fetch_nonce(nonce, sizeof(nonce))) 2506215976Sjmallett return FALSE; 2507215976Sjmallett 2508215976Sjmallett nonce_uses = 0; 2509215976Sjmallett restarted_count = 0; 2510215976Sjmallett mru_count = 0; 2511215976Sjmallett INIT_DLIST(mru_list, mlink); 2512215976Sjmallett cb = NTP_HASH_SIZE * sizeof(*hash_table); 2513215976Sjmallett INSIST(NULL == hash_table); 2514215976Sjmallett hash_table = emalloc_zero(cb); 2515215976Sjmallett 2516215976Sjmallett c_mru_l_rc = FALSE; 2517215976Sjmallett list_complete = FALSE; 2518215976Sjmallett have_now = FALSE; 2519215976Sjmallett cap_frags = TRUE; 2520215976Sjmallett got = 0; 2521215976Sjmallett ri = 0; 2522215976Sjmallett cb = sizeof(*mon); 2523215976Sjmallett mon = emalloc_zero(cb); 2524215976Sjmallett ZERO(*pnow); 2525215976Sjmallett ZERO(last_older); 2526215976Sjmallett next_report = time(NULL) + MRU_REPORT_SECS; 2527215976Sjmallett 2528215976Sjmallett limit = min(3 * MAXFRAGS, ntpd_row_limit); 2529215976Sjmallett frags = MAXFRAGS; 2530215976Sjmallett snprintf(req_buf, sizeof(req_buf), "nonce=%s, frags=%d%s", 2531215976Sjmallett nonce, frags, parms); 2532215976Sjmallett nonce_uses++; 2533215976Sjmallett 2534215976Sjmallett while (TRUE) { 2535215976Sjmallett if (debug) 2536215976Sjmallett fprintf(stderr, "READ_MRU parms: %s\n", req_buf); 2537215976Sjmallett 2538215976Sjmallett qres = doqueryex(CTL_OP_READ_MRU, 0, 0, 2539215976Sjmallett strlen(req_buf), req_buf, 2540215976Sjmallett &rstatus, &rsize, &rdata, TRUE); 2541215976Sjmallett 2542215976Sjmallett if (CERR_UNKNOWNVAR == qres && ri > 0) { 2543215976Sjmallett /* 2544215976Sjmallett * None of the supplied prior entries match, so 2545215976Sjmallett * toss them from our list and try again. 2546215976Sjmallett */ 2547215976Sjmallett if (debug) 2548215976Sjmallett fprintf(stderr, 2549215976Sjmallett "no overlap between %d prior entries and server MRU list\n", 2550215976Sjmallett ri); 2551215976Sjmallett while (ri--) { 2552215976Sjmallett recent = HEAD_DLIST(mru_list, mlink); 2553215976Sjmallett INSIST(recent != NULL); 2554215976Sjmallett if (debug) 2555215976Sjmallett fprintf(stderr, 2556215976Sjmallett "tossing prior entry %s to resync\n", 2557215976Sjmallett sptoa(&recent->addr)); 2558215976Sjmallett UNLINK_DLIST(recent, mlink); 2559215976Sjmallett hash = NTP_HASH_ADDR(&recent->addr); 2560215976Sjmallett UNLINK_SLIST(unlinked, hash_table[hash], 2561215976Sjmallett recent, hlink, mru); 2562215976Sjmallett INSIST(unlinked == recent); 2563215976Sjmallett free(recent); 2564215976Sjmallett mru_count--; 2565215976Sjmallett } 2566215976Sjmallett if (NULL == HEAD_DLIST(mru_list, mlink)) { 2567215976Sjmallett restarted_count++; 2568215976Sjmallett if (restarted_count > 8) { 2569215976Sjmallett fprintf(stderr, 2570215976Sjmallett "Giving up after 8 restarts from the beginning.\n" 2571215976Sjmallett "With high-traffic NTP servers, this can occur if the\n" 2572215976Sjmallett "MRU list is limited to less than about 16 seconds' of\n" 2573215976Sjmallett "entries. See the 'mru' ntp.conf directive to adjust.\n"); 2574215976Sjmallett goto cleanup_return; 2575215976Sjmallett } 2576215976Sjmallett if (debug) 2577215976Sjmallett fprintf(stderr, 2578215976Sjmallett "---> Restarting from the beginning, retry #%u\n", 2579215976Sjmallett restarted_count); 2580215976Sjmallett } 2581215976Sjmallett } else if (CERR_UNKNOWNVAR == qres) { 2582215976Sjmallett fprintf(stderr, 2583215976Sjmallett "CERR_UNKNOWNVAR from ntpd but no priors given.\n"); 2584215976Sjmallett goto cleanup_return; 2585215976Sjmallett } else if (CERR_BADVALUE == qres) { 2586215976Sjmallett if (cap_frags) { 2587215976Sjmallett cap_frags = FALSE; 2588215976Sjmallett if (debug) 2589215976Sjmallett fprintf(stderr, 2590215976Sjmallett "Reverted to row limit from fragments limit.\n"); 2591215976Sjmallett } else { 2592215976Sjmallett /* ntpd has lower cap on row limit */ 2593215976Sjmallett ntpd_row_limit--; 2594215976Sjmallett limit = min(limit, ntpd_row_limit); 2595215976Sjmallett if (debug) 2596215976Sjmallett fprintf(stderr, 2597215976Sjmallett "Row limit reduced to %d following CERR_BADVALUE.\n", 2598215976Sjmallett limit); 2599215976Sjmallett } 2600215976Sjmallett } else if (ERR_INCOMPLETE == qres || 2601215976Sjmallett ERR_TIMEOUT == qres) { 2602215976Sjmallett /* 2603215976Sjmallett * Reduce the number of rows/frags requested by 2604215976Sjmallett * half to recover from lost response fragments. 2605215976Sjmallett */ 2606215976Sjmallett if (cap_frags) { 2607215976Sjmallett frags = max(2, frags / 2); 2608215976Sjmallett if (debug) 2609215976Sjmallett fprintf(stderr, 2610215976Sjmallett "Frag limit reduced to %d following incomplete response.\n", 2611215976Sjmallett frags); 2612215976Sjmallett } else { 2613215976Sjmallett limit = max(2, limit / 2); 2614215976Sjmallett if (debug) 2615215976Sjmallett fprintf(stderr, 2616215976Sjmallett "Row limit reduced to %d following incomplete response.\n", 2617215976Sjmallett limit); 2618215976Sjmallett } 2619215976Sjmallett } else if (qres) { 2620215976Sjmallett show_error_msg(qres, 0); 2621215976Sjmallett goto cleanup_return; 2622215976Sjmallett } 2623215976Sjmallett /* 2624215976Sjmallett * This is a cheap cop-out implementation of rawmode 2625215976Sjmallett * output for mrulist. A better approach would be to 2626215976Sjmallett * dump similar output after the list is collected by 2627215976Sjmallett * ntpq with a continuous sequence of indexes. This 2628215976Sjmallett * cheap approach has indexes resetting to zero for 2629215976Sjmallett * each query/response, and duplicates are not 2630215976Sjmallett * coalesced. 2631215976Sjmallett */ 2632215976Sjmallett if (!qres && rawmode) 2633215976Sjmallett printvars(rsize, rdata, rstatus, TYPE_SYS, 1, stdout); 2634215976Sjmallett ci = 0; 2635215976Sjmallett have_addr_older = FALSE; 2636215976Sjmallett have_last_older = FALSE; 2637215976Sjmallett while (!qres && nextvar(&rsize, &rdata, &tag, &val)) { 2638215976Sjmallett if (debug > 1) 2639215976Sjmallett fprintf(stderr, "nextvar gave: %s = %s\n", 2640215976Sjmallett tag, val); 2641215976Sjmallett switch(tag[0]) { 2642215976Sjmallett 2643215976Sjmallett case 'a': 2644215976Sjmallett if (!strcmp(tag, "addr.older")) { 2645215976Sjmallett if (!have_last_older) { 2646215976Sjmallett fprintf(stderr, 2647215976Sjmallett "addr.older %s before last.older\n", 2648215976Sjmallett val); 2649215976Sjmallett goto cleanup_return; 2650215976Sjmallett } 2651215976Sjmallett if (!decodenetnum(val, &addr_older)) { 2652215976Sjmallett fprintf(stderr, 2653215976Sjmallett "addr.older %s garbled\n", 2654215976Sjmallett val); 2655215976Sjmallett goto cleanup_return; 2656215976Sjmallett } 2657215976Sjmallett hash = NTP_HASH_ADDR(&addr_older); 2658215976Sjmallett for (recent = hash_table[hash]; 2659215976Sjmallett recent != NULL; 2660215976Sjmallett recent = recent->hlink) 2661215976Sjmallett if (ADDR_PORT_EQ( 2662215976Sjmallett &addr_older, 2663215976Sjmallett &recent->addr)) 2664215976Sjmallett break; 2665215976Sjmallett if (NULL == recent) { 2666215976Sjmallett fprintf(stderr, 2667215976Sjmallett "addr.older %s not in hash table\n", 2668215976Sjmallett val); 2669215976Sjmallett goto cleanup_return; 2670215976Sjmallett } 2671215976Sjmallett if (!L_ISEQU(&last_older, 2672215976Sjmallett &recent->last)) { 2673215976Sjmallett fprintf(stderr, 2674215976Sjmallett "last.older %08x.%08x mismatches %08x.%08x expected.\n", 2675215976Sjmallett last_older.l_ui, 2676215976Sjmallett last_older.l_uf, 2677215976Sjmallett recent->last.l_ui, 2678215976Sjmallett recent->last.l_uf); 2679215976Sjmallett goto cleanup_return; 2680215976Sjmallett } 2681215976Sjmallett have_addr_older = TRUE; 2682215976Sjmallett } else if (1 != sscanf(tag, "addr.%d", &si) 2683215976Sjmallett || si != ci) 2684215976Sjmallett goto nomatch; 2685215976Sjmallett else if (decodenetnum(val, &mon->addr)) 2686215976Sjmallett MGOT(MRU_GOT_ADDR); 2687215976Sjmallett break; 2688215976Sjmallett 2689215976Sjmallett case 'l': 2690215976Sjmallett if (!strcmp(tag, "last.older")) { 2691215976Sjmallett if ('0' != val[0] || 2692215976Sjmallett 'x' != val[1] || 2693215976Sjmallett !hextolfp(val + 2, &last_older)) { 2694215976Sjmallett fprintf(stderr, 2695215976Sjmallett "last.older %s garbled\n", 2696215976Sjmallett val); 2697215976Sjmallett goto cleanup_return; 2698215976Sjmallett } 2699215976Sjmallett have_last_older = TRUE; 2700215976Sjmallett } else if (!strcmp(tag, "last.newest")) { 2701215976Sjmallett if (0 != got) { 2702215976Sjmallett fprintf(stderr, 2703215976Sjmallett "last.newest %s before complete row, got = 0x%x\n", 2704215976Sjmallett val, (u_int)got); 2705215976Sjmallett goto cleanup_return; 2706215976Sjmallett } 2707215976Sjmallett if (!have_now) { 2708215976Sjmallett fprintf(stderr, 2709215976Sjmallett "last.newest %s before now=\n", 2710215976Sjmallett val); 2711215976Sjmallett goto cleanup_return; 2712215976Sjmallett } 2713215976Sjmallett head = HEAD_DLIST(mru_list, mlink); 2714215976Sjmallett if (NULL != head) { 2715215976Sjmallett if ('0' != val[0] || 2716215976Sjmallett 'x' != val[1] || 2717215976Sjmallett !hextolfp(val + 2, &newest) || 2718215976Sjmallett !L_ISEQU(&newest, 2719215976Sjmallett &head->last)) { 2720215976Sjmallett fprintf(stderr, 2721215976Sjmallett "last.newest %s mismatches %08x.%08x", 2722215976Sjmallett val, 2723215976Sjmallett head->last.l_ui, 2724215976Sjmallett head->last.l_uf); 2725215976Sjmallett goto cleanup_return; 2726215976Sjmallett } 2727215976Sjmallett } 2728215976Sjmallett list_complete = TRUE; 2729215976Sjmallett } else if (1 != sscanf(tag, "last.%d", &si) || 2730215976Sjmallett si != ci || '0' != val[0] || 2731215976Sjmallett 'x' != val[1] || 2732215976Sjmallett !hextolfp(val + 2, &mon->last)) { 2733215976Sjmallett goto nomatch; 2734215976Sjmallett } else { 2735215976Sjmallett MGOT(MRU_GOT_LAST); 2736215976Sjmallett /* 2737215976Sjmallett * allow interrupted retrieval, 2738215976Sjmallett * using most recent retrieved 2739215976Sjmallett * entry's last seen timestamp 2740215976Sjmallett * as the end of operation. 2741215976Sjmallett */ 2742215976Sjmallett *pnow = mon->last; 2743215976Sjmallett } 2744215976Sjmallett break; 2745215976Sjmallett 2746215976Sjmallett case 'f': 2747215976Sjmallett if (1 != sscanf(tag, "first.%d", &si) || 2748215976Sjmallett si != ci || '0' != val[0] || 2749215976Sjmallett 'x' != val[1] || 2750215976Sjmallett !hextolfp(val + 2, &mon->first)) 2751215976Sjmallett goto nomatch; 2752215976Sjmallett MGOT(MRU_GOT_FIRST); 2753215976Sjmallett break; 2754215976Sjmallett 2755215976Sjmallett case 'n': 2756215976Sjmallett if (!strcmp(tag, "nonce")) { 2757215976Sjmallett strlcpy(nonce, val, sizeof(nonce)); 2758215976Sjmallett nonce_uses = 0; 2759215976Sjmallett break; /* case */ 2760215976Sjmallett } else if (strcmp(tag, "now") || 2761215976Sjmallett '0' != val[0] || 2762215976Sjmallett 'x' != val[1] || 2763215976Sjmallett !hextolfp(val + 2, pnow)) 2764215976Sjmallett goto nomatch; 2765215976Sjmallett have_now = TRUE; 2766215976Sjmallett break; 2767215976Sjmallett 2768215976Sjmallett case 'c': 2769215976Sjmallett if (1 != sscanf(tag, "ct.%d", &si) || 2770215976Sjmallett si != ci || 2771215976Sjmallett 1 != sscanf(val, "%d", &mon->count) 2772215976Sjmallett || mon->count < 1) 2773215976Sjmallett goto nomatch; 2774215976Sjmallett MGOT(MRU_GOT_COUNT); 2775215976Sjmallett break; 2776215976Sjmallett 2777215976Sjmallett case 'm': 2778215976Sjmallett if (1 != sscanf(tag, "mv.%d", &si) || 2779215976Sjmallett si != ci || 2780215976Sjmallett 1 != sscanf(val, "%d", &mv)) 2781215976Sjmallett goto nomatch; 2782215976Sjmallett mon->mode = PKT_MODE(mv); 2783215976Sjmallett mon->ver = PKT_VERSION(mv); 2784215976Sjmallett MGOT(MRU_GOT_MV); 2785215976Sjmallett break; 2786215976Sjmallett 2787215976Sjmallett case 'r': 2788215976Sjmallett if (1 != sscanf(tag, "rs.%d", &si) || 2789215976Sjmallett si != ci || 2790215976Sjmallett 1 != sscanf(val, "0x%hx", &mon->rs)) 2791215976Sjmallett goto nomatch; 2792215976Sjmallett MGOT(MRU_GOT_RS); 2793215976Sjmallett break; 2794215976Sjmallett 2795215976Sjmallett default: 2796215976Sjmallett nomatch: 2797215976Sjmallett /* empty stmt */ ; 2798215976Sjmallett /* ignore unknown tags */ 2799215976Sjmallett } 2800215976Sjmallett } 2801215976Sjmallett if (have_now) 2802215976Sjmallett list_complete = TRUE; 2803215976Sjmallett if (list_complete) { 2804215976Sjmallett INSIST(0 == ri || have_addr_older); 2805215976Sjmallett } 2806215976Sjmallett if (mrulist_interrupted) { 2807215976Sjmallett printf("mrulist retrieval interrupted by operator.\n" 2808215976Sjmallett "Displaying partial client list.\n"); 2809215976Sjmallett fflush(stdout); 2810215976Sjmallett } 2811215976Sjmallett if (list_complete || mrulist_interrupted) { 2812215976Sjmallett fprintf(stderr, 2813215976Sjmallett "\rRetrieved %u unique MRU entries and %u updates.\n", 2814215976Sjmallett mru_count, mru_dupes); 2815215976Sjmallett fflush(stderr); 2816215976Sjmallett break; 2817215976Sjmallett } 2818215976Sjmallett if (time(NULL) >= next_report) { 2819215976Sjmallett next_report += MRU_REPORT_SECS; 2820215976Sjmallett fprintf(stderr, "\r%u (%u updates) ", mru_count, 2821215976Sjmallett mru_dupes); 2822215976Sjmallett fflush(stderr); 2823215976Sjmallett } 2824215976Sjmallett 2825215976Sjmallett /* 2826215976Sjmallett * Snooze for a bit between queries to let ntpd catch 2827215976Sjmallett * up with other duties. 2828215976Sjmallett */ 2829215976Sjmallett#ifdef SYS_WINNT 2830215976Sjmallett Sleep(sleep_msecs); 2831215976Sjmallett#elif !defined(HAVE_NANOSLEEP) 2832215976Sjmallett sleep((sleep_msecs / 1000) + 1); 2833215976Sjmallett#else 2834215976Sjmallett { 2835215976Sjmallett struct timespec interv = { 0, 2836215976Sjmallett 1000 * sleep_msecs }; 2837215976Sjmallett nanosleep(&interv, NULL); 2838215976Sjmallett } 2839215976Sjmallett#endif 2840215976Sjmallett /* 2841215976Sjmallett * If there were no errors, increase the number of rows 2842215976Sjmallett * to a maximum of 3 * MAXFRAGS (the most packets ntpq 2843215976Sjmallett * can handle in one response), on the assumption that 2844215976Sjmallett * no less than 3 rows fit in each packet, capped at 2845215976Sjmallett * our best guess at the server's row limit. 2846215976Sjmallett */ 2847215976Sjmallett if (!qres) { 2848215976Sjmallett if (cap_frags) { 2849215976Sjmallett frags = min(MAXFRAGS, frags + 1); 2850215976Sjmallett } else { 2851215976Sjmallett limit = min3(3 * MAXFRAGS, 2852215976Sjmallett ntpd_row_limit, 2853215976Sjmallett max(limit + 1, 2854215976Sjmallett limit * 33 / 32)); 2855215976Sjmallett } 2856215976Sjmallett } 2857215976Sjmallett /* 2858215976Sjmallett * prepare next query with as many address and last-seen 2859215976Sjmallett * timestamps as will fit in a single packet. 2860215976Sjmallett */ 2861215976Sjmallett req = req_buf; 2862215976Sjmallett req_end = req_buf + sizeof(req_buf); 2863215976Sjmallett#define REQ_ROOM (req_end - req) 2864215976Sjmallett snprintf(req, REQ_ROOM, "nonce=%s, %s=%d%s", nonce, 2865215976Sjmallett (cap_frags) 2866215976Sjmallett ? "frags" 2867215976Sjmallett : "limit", 2868215976Sjmallett (cap_frags) 2869215976Sjmallett ? frags 2870215976Sjmallett : limit, 2871215976Sjmallett parms); 2872215976Sjmallett req += strlen(req); 2873215976Sjmallett nonce_uses++; 2874215976Sjmallett if (nonce_uses >= 4) { 2875215976Sjmallett if (!fetch_nonce(nonce, sizeof(nonce))) 2876215976Sjmallett goto cleanup_return; 2877215976Sjmallett nonce_uses = 0; 2878215976Sjmallett } 2879215976Sjmallett 2880215976Sjmallett 2881215976Sjmallett for (ri = 0, recent = HEAD_DLIST(mru_list, mlink); 2882215976Sjmallett recent != NULL; 2883215976Sjmallett ri++, recent = NEXT_DLIST(mru_list, recent, mlink)) { 2884215976Sjmallett 2885215976Sjmallett snprintf(buf, sizeof(buf), 2886215976Sjmallett ", addr.%d=%s, last.%d=0x%08x.%08x", 2887215976Sjmallett ri, sptoa(&recent->addr), ri, 2888215976Sjmallett recent->last.l_ui, recent->last.l_uf); 2889215976Sjmallett chars = strlen(buf); 2890215976Sjmallett if ((size_t)REQ_ROOM <= chars) 2891215976Sjmallett break; 2892215976Sjmallett memcpy(req, buf, chars + 1); 2893215976Sjmallett req += chars; 2894215976Sjmallett } 2895215976Sjmallett } 2896215976Sjmallett 2897215976Sjmallett c_mru_l_rc = TRUE; 2898215976Sjmallett goto retain_hash_table; 2899215976Sjmallett 2900215976Sjmallettcleanup_return: 2901215976Sjmallett free(hash_table); 2902215976Sjmallett hash_table = NULL; 2903215976Sjmallett 2904215976Sjmallettretain_hash_table: 2905215976Sjmallett if (mon != NULL) 2906215976Sjmallett free(mon); 2907215976Sjmallett 2908215976Sjmallett return c_mru_l_rc; 2909215976Sjmallett} 2910215976Sjmallett 2911215976Sjmallett 2912215976Sjmallett/* 2913215976Sjmallett * qcmp_mru_addr - sort MRU entries by remote address. 2914215976Sjmallett * 2915215976Sjmallett * All IPv4 addresses sort before any IPv6, addresses are sorted by 2916215976Sjmallett * value within address family. 2917215976Sjmallett */ 2918215976Sjmallettstatic int 2919215976Sjmallettqcmp_mru_addr( 2920215976Sjmallett const void *v1, 2921215976Sjmallett const void *v2 2922215976Sjmallett ) 2923215976Sjmallett{ 2924215976Sjmallett const mru * const * ppm1 = v1; 2925215976Sjmallett const mru * const * ppm2 = v2; 2926215976Sjmallett const mru * pm1; 2927215976Sjmallett const mru * pm2; 2928215976Sjmallett u_short af1; 2929215976Sjmallett u_short af2; 2930215976Sjmallett size_t cmplen; 2931215976Sjmallett size_t addr_off; 2932215976Sjmallett 2933215976Sjmallett pm1 = *ppm1; 2934215976Sjmallett pm2 = *ppm2; 2935215976Sjmallett 2936215976Sjmallett af1 = AF(&pm1->addr); 2937215976Sjmallett af2 = AF(&pm2->addr); 2938215976Sjmallett 2939215976Sjmallett if (af1 != af2) 2940215976Sjmallett return (AF_INET == af1) 2941215976Sjmallett ? -1 2942215976Sjmallett : 1; 2943215976Sjmallett 2944215976Sjmallett cmplen = SIZEOF_INADDR(af1); 2945215976Sjmallett addr_off = (AF_INET == af1) 2946215976Sjmallett ? offsetof(struct sockaddr_in, sin_addr) 2947215976Sjmallett : offsetof(struct sockaddr_in6, sin6_addr); 2948215976Sjmallett 2949215976Sjmallett return memcmp((const char *)&pm1->addr + addr_off, 2950215976Sjmallett (const char *)&pm2->addr + addr_off, 2951215976Sjmallett cmplen); 2952215976Sjmallett} 2953215976Sjmallett 2954215976Sjmallett 2955215976Sjmallettstatic int 2956215976Sjmallettqcmp_mru_r_addr( 2957215976Sjmallett const void *v1, 2958215976Sjmallett const void *v2 2959215976Sjmallett ) 2960215976Sjmallett{ 2961215976Sjmallett return -qcmp_mru_addr(v1, v2); 2962215976Sjmallett} 2963215976Sjmallett 2964215976Sjmallett 2965215976Sjmallett/* 2966215976Sjmallett * qcmp_mru_count - sort MRU entries by times seen (hit count). 2967215976Sjmallett */ 2968215976Sjmallettstatic int 2969215976Sjmallettqcmp_mru_count( 2970215976Sjmallett const void *v1, 2971215976Sjmallett const void *v2 2972215976Sjmallett ) 2973215976Sjmallett{ 2974215976Sjmallett const mru * const * ppm1 = v1; 2975215976Sjmallett const mru * const * ppm2 = v2; 2976215976Sjmallett const mru * pm1; 2977215976Sjmallett const mru * pm2; 2978215976Sjmallett 2979215976Sjmallett pm1 = *ppm1; 2980215976Sjmallett pm2 = *ppm2; 2981215976Sjmallett 2982215976Sjmallett return (pm1->count < pm2->count) 2983215976Sjmallett ? -1 2984215976Sjmallett : ((pm1->count == pm2->count) 2985215976Sjmallett ? 0 2986215976Sjmallett : 1); 2987215976Sjmallett} 2988215976Sjmallett 2989215976Sjmallett 2990215976Sjmallettstatic int 2991215976Sjmallettqcmp_mru_r_count( 2992215976Sjmallett const void *v1, 2993215976Sjmallett const void *v2 2994215976Sjmallett ) 2995215976Sjmallett{ 2996215976Sjmallett return -qcmp_mru_count(v1, v2); 2997215976Sjmallett} 2998215976Sjmallett 2999215976Sjmallett 3000215976Sjmallett/* 3001215976Sjmallett * qcmp_mru_avgint - sort MRU entries by average interval. 3002215976Sjmallett */ 3003215976Sjmallettstatic int 3004215976Sjmallettqcmp_mru_avgint( 3005215976Sjmallett const void *v1, 3006215976Sjmallett const void *v2 3007215976Sjmallett ) 3008215976Sjmallett{ 3009215976Sjmallett const mru * const * ppm1 = v1; 3010215976Sjmallett const mru * const * ppm2 = v2; 3011215976Sjmallett const mru * pm1; 3012215976Sjmallett const mru * pm2; 3013215976Sjmallett l_fp interval; 3014215976Sjmallett double avg1; 3015215976Sjmallett double avg2; 3016215976Sjmallett 3017215976Sjmallett pm1 = *ppm1; 3018215976Sjmallett pm2 = *ppm2; 3019215976Sjmallett 3020215976Sjmallett interval = pm1->last; 3021215976Sjmallett L_SUB(&interval, &pm1->first); 3022215976Sjmallett LFPTOD(&interval, avg1); 3023215976Sjmallett avg1 /= pm1->count; 3024215976Sjmallett 3025215976Sjmallett interval = pm2->last; 3026215976Sjmallett L_SUB(&interval, &pm2->first); 3027215976Sjmallett LFPTOD(&interval, avg2); 3028215976Sjmallett avg2 /= pm2->count; 3029215976Sjmallett 3030215976Sjmallett if (avg1 < avg2) 3031215976Sjmallett return -1; 3032215976Sjmallett else if (avg1 > avg2) 3033215976Sjmallett return 1; 3034215976Sjmallett 3035215976Sjmallett /* secondary sort on lstint - rarely tested */ 3036215976Sjmallett if (L_ISEQU(&pm1->last, &pm2->last)) 3037215976Sjmallett return 0; 3038215976Sjmallett else if (L_ISGEQ(&pm1->last, &pm2->last)) 3039215976Sjmallett return -1; 3040215976Sjmallett else 3041215976Sjmallett return 1; 3042215976Sjmallett} 3043215976Sjmallett 3044215976Sjmallett 3045215976Sjmallettstatic int 3046215976Sjmallettqcmp_mru_r_avgint( 3047215976Sjmallett const void *v1, 3048215976Sjmallett const void *v2 3049215976Sjmallett ) 3050215976Sjmallett{ 3051215976Sjmallett return -qcmp_mru_avgint(v1, v2); 3052215976Sjmallett} 3053215976Sjmallett 3054215976Sjmallett 3055215976Sjmallett/* 3056215976Sjmallett * mrulist - ntpq's mrulist command to fetch an arbitrarily large Most 3057215976Sjmallett * Recently Used (seen) remote address list from ntpd. 3058215976Sjmallett * 3059215976Sjmallett * Similar to ntpdc's monlist command, but not limited to a single 3060215976Sjmallett * request/response, and thereby not limited to a few hundred remote 3061215976Sjmallett * addresses. 3062215976Sjmallett * 3063215976Sjmallett * See ntpd/ntp_control.c read_mru_list() for comments on the way 3064215976Sjmallett * CTL_OP_READ_MRU is designed to be used. 3065215976Sjmallett * 3066215976Sjmallett * mrulist intentionally differs from monlist in the way the avgint 3067215976Sjmallett * column is calculated. monlist includes the time after the last 3068215976Sjmallett * packet from the client until the monlist query time in the average, 3069215976Sjmallett * while mrulist excludes it. That is, monlist's average interval grows 3070215976Sjmallett * over time for remote addresses not heard from in some time, while it 3071215976Sjmallett * remains unchanged in mrulist. This also affects the avgint value for 3072215976Sjmallett * entries representing a single packet, with identical first and last 3073215976Sjmallett * timestamps. mrulist shows 0 avgint, monlist shows a value identical 3074215976Sjmallett * to lstint. 3075215976Sjmallett */ 3076215976Sjmallettstatic void 3077215976Sjmallettmrulist( 3078215976Sjmallett struct parse * pcmd, 3079215976Sjmallett FILE * fp 3080215976Sjmallett ) 3081215976Sjmallett{ 3082215976Sjmallett const char mincount_eq[] = "mincount="; 3083215976Sjmallett const char resall_eq[] = "resall="; 3084215976Sjmallett const char resany_eq[] = "resany="; 3085215976Sjmallett const char maxlstint_eq[] = "maxlstint="; 3086215976Sjmallett const char laddr_eq[] = "laddr="; 3087215976Sjmallett const char sort_eq[] = "sort="; 3088215976Sjmallett mru_sort_order order; 3089215976Sjmallett size_t n; 3090215976Sjmallett char parms_buf[128]; 3091215976Sjmallett char buf[24]; 3092215976Sjmallett char *parms; 3093215976Sjmallett const char *arg; 3094215976Sjmallett size_t cb; 3095215976Sjmallett mru **sorted; 3096215976Sjmallett mru **ppentry; 3097215976Sjmallett mru *recent; 3098215976Sjmallett l_fp now; 3099215976Sjmallett l_fp interval; 3100215976Sjmallett double favgint; 3101215976Sjmallett double flstint; 3102215976Sjmallett int avgint; 3103215976Sjmallett int lstint; 3104215976Sjmallett size_t i; 3105215976Sjmallett 3106215976Sjmallett mrulist_interrupted = FALSE; 3107215976Sjmallett push_ctrl_c_handler(&mrulist_ctrl_c_hook); 3108215976Sjmallett fprintf(stderr, 3109215976Sjmallett "Ctrl-C will stop MRU retrieval and display partial results.\n"); 3110215976Sjmallett fflush(stderr); 3111215976Sjmallett 3112215976Sjmallett order = MRUSORT_DEF; 3113215976Sjmallett parms_buf[0] = '\0'; 3114215976Sjmallett parms = parms_buf; 3115215976Sjmallett for (i = 0; i < pcmd->nargs; i++) { 3116215976Sjmallett arg = pcmd->argval[i].string; 3117215976Sjmallett if (arg != NULL) { 3118215976Sjmallett cb = strlen(arg) + 1; 3119215976Sjmallett if ((!strncmp(resall_eq, arg, sizeof(resall_eq) 3120215976Sjmallett - 1) || !strncmp(resany_eq, arg, 3121215976Sjmallett sizeof(resany_eq) - 1) || !strncmp( 3122215976Sjmallett mincount_eq, arg, sizeof(mincount_eq) - 1) 3123215976Sjmallett || !strncmp(laddr_eq, arg, sizeof(laddr_eq) 3124215976Sjmallett - 1) || !strncmp(maxlstint_eq, arg, 3125215976Sjmallett sizeof(laddr_eq) - 1)) && parms + cb + 2 <= 3126215976Sjmallett parms_buf + sizeof(parms_buf)) { 3127215976Sjmallett /* these are passed intact to ntpd */ 3128215976Sjmallett memcpy(parms, ", ", 2); 3129215976Sjmallett parms += 2; 3130215976Sjmallett memcpy(parms, arg, cb); 3131215976Sjmallett parms += cb - 1; 3132215976Sjmallett } else if (!strncmp(sort_eq, arg, 3133215976Sjmallett sizeof(sort_eq) - 1)) { 3134215976Sjmallett arg += sizeof(sort_eq) - 1; 3135215976Sjmallett for (n = 0; 3136215976Sjmallett n < COUNTOF(mru_sort_keywords); 3137215976Sjmallett n++) 3138215976Sjmallett if (!strcmp(mru_sort_keywords[n], 3139215976Sjmallett arg)) 3140215976Sjmallett break; 3141215976Sjmallett if (n < COUNTOF(mru_sort_keywords)) 3142215976Sjmallett order = n; 3143215976Sjmallett } else if (!strcmp("limited", arg) || 3144215976Sjmallett !strcmp("kod", arg)) { 3145215976Sjmallett /* transform to resany=... */ 3146215976Sjmallett snprintf(buf, sizeof(buf), 3147215976Sjmallett ", resany=0x%x", 3148215976Sjmallett ('k' == arg[0]) 3149215976Sjmallett ? RES_KOD 3150215976Sjmallett : RES_LIMITED); 3151215976Sjmallett cb = 1 + strlen(buf); 3152215976Sjmallett if (parms + cb < 3153215976Sjmallett parms_buf + sizeof(parms_buf)) { 3154215976Sjmallett memcpy(parms, buf, cb); 3155215976Sjmallett parms += cb - 1; 3156215976Sjmallett } 3157215976Sjmallett } else 3158215976Sjmallett fprintf(stderr, 3159215976Sjmallett "ignoring unrecognized mrulist parameter: %s\n", 3160215976Sjmallett arg); 3161215976Sjmallett } 3162215976Sjmallett } 3163215976Sjmallett parms = parms_buf; 3164215976Sjmallett 3165215976Sjmallett if (!collect_mru_list(parms, &now)) 3166215976Sjmallett return; 3167215976Sjmallett 3168215976Sjmallett /* display the results */ 3169215976Sjmallett if (rawmode) 3170215976Sjmallett goto cleanup_return; 3171215976Sjmallett 3172215976Sjmallett /* construct an array of entry pointers in default order */ 3173215976Sjmallett sorted = eallocarray(mru_count, sizeof(*sorted)); 3174215976Sjmallett ppentry = sorted; 3175215976Sjmallett if (MRUSORT_R_DEF != order) { 3176215976Sjmallett ITER_DLIST_BEGIN(mru_list, recent, mlink, mru) 3177215976Sjmallett INSIST(ppentry < sorted + mru_count); 3178215976Sjmallett *ppentry = recent; 3179215976Sjmallett ppentry++; 3180215976Sjmallett ITER_DLIST_END() 3181215976Sjmallett } else { 3182215976Sjmallett REV_ITER_DLIST_BEGIN(mru_list, recent, mlink, mru) 3183215976Sjmallett INSIST(ppentry < sorted + mru_count); 3184215976Sjmallett *ppentry = recent; 3185215976Sjmallett ppentry++; 3186215976Sjmallett REV_ITER_DLIST_END() 3187215976Sjmallett } 3188215976Sjmallett 3189215976Sjmallett if (ppentry - sorted != (int)mru_count) { 3190215976Sjmallett fprintf(stderr, 3191215976Sjmallett "mru_count %u should match MRU list depth %ld.\n", 3192215976Sjmallett mru_count, (long)(ppentry - sorted)); 3193215976Sjmallett free(sorted); 3194215976Sjmallett goto cleanup_return; 3195215976Sjmallett } 3196215976Sjmallett 3197215976Sjmallett /* re-sort sorted[] if not default or reverse default */ 3198215976Sjmallett if (MRUSORT_R_DEF < order) 3199215976Sjmallett qsort(sorted, mru_count, sizeof(sorted[0]), 3200215976Sjmallett mru_qcmp_table[order]); 3201215976Sjmallett 3202215976Sjmallett mrulist_interrupted = FALSE; 3203215976Sjmallett printf( "lstint avgint rstr r m v count rport remote address\n" 3204215976Sjmallett "==============================================================================\n"); 3205215976Sjmallett /* '=' x 78 */ 3206215976Sjmallett for (ppentry = sorted; ppentry < sorted + mru_count; ppentry++) { 3207215976Sjmallett recent = *ppentry; 3208215976Sjmallett interval = now; 3209215976Sjmallett L_SUB(&interval, &recent->last); 3210215976Sjmallett LFPTOD(&interval, flstint); 3211215976Sjmallett lstint = (int)(flstint + 0.5); 3212215976Sjmallett interval = recent->last; 3213215976Sjmallett L_SUB(&interval, &recent->first); 3214215976Sjmallett LFPTOD(&interval, favgint); 3215215976Sjmallett favgint /= recent->count; 3216215976Sjmallett avgint = (int)(favgint + 0.5); 3217215976Sjmallett fprintf(fp, "%6d %6d %4hx %c %d %d %6d %5u %s\n", 3218215976Sjmallett lstint, avgint, recent->rs, 3219215976Sjmallett (RES_KOD & recent->rs) 3220215976Sjmallett ? 'K' 3221215976Sjmallett : (RES_LIMITED & recent->rs) 3222215976Sjmallett ? 'L' 3223215976Sjmallett : '.', 3224215976Sjmallett (int)recent->mode, (int)recent->ver, 3225215976Sjmallett recent->count, SRCPORT(&recent->addr), 3226215976Sjmallett nntohost(&recent->addr)); 3227215976Sjmallett if (showhostnames) 3228215976Sjmallett fflush(fp); 3229215976Sjmallett if (mrulist_interrupted) { 3230215976Sjmallett fputs("\n --interrupted--\n", fp); 3231215976Sjmallett fflush(fp); 3232215976Sjmallett break; 3233215976Sjmallett } 3234215976Sjmallett } 3235215976Sjmallett fflush(fp); 3236215976Sjmallett if (debug) { 3237215976Sjmallett fprintf(stderr, 3238215976Sjmallett "--- completed, freeing sorted[] pointers\n"); 3239215976Sjmallett fflush(stderr); 3240215976Sjmallett } 3241215976Sjmallett free(sorted); 3242215976Sjmallett 3243215976Sjmallettcleanup_return: 3244215976Sjmallett if (debug) { 3245215976Sjmallett fprintf(stderr, "... freeing MRU entries\n"); 3246215976Sjmallett fflush(stderr); 3247215976Sjmallett } 3248215976Sjmallett ITER_DLIST_BEGIN(mru_list, recent, mlink, mru) 3249215976Sjmallett free(recent); 3250215976Sjmallett ITER_DLIST_END() 3251215976Sjmallett if (debug) { 3252215976Sjmallett fprintf(stderr, "... freeing hash_table[]\n"); 3253215976Sjmallett fflush(stderr); 3254215976Sjmallett } 3255215976Sjmallett free(hash_table); 3256215976Sjmallett hash_table = NULL; 3257215976Sjmallett INIT_DLIST(mru_list, mlink); 3258215976Sjmallett 3259215976Sjmallett pop_ctrl_c_handler(&mrulist_ctrl_c_hook); 3260215976Sjmallett} 3261215976Sjmallett 3262215976Sjmallett 3263215976Sjmallett/* 3264215976Sjmallett * validate_ifnum - helper for ifstats() 3265215976Sjmallett * 3266215976Sjmallett * Ensures rows are received in order and complete. 3267215976Sjmallett */ 3268215976Sjmallettstatic void 3269215976Sjmallettvalidate_ifnum( 3270215976Sjmallett FILE * fp, 3271215976Sjmallett u_int ifnum, 3272215976Sjmallett int * pfields, 3273215976Sjmallett ifstats_row * prow 3274215976Sjmallett ) 3275215976Sjmallett{ 3276215976Sjmallett if (prow->ifnum == ifnum) 3277215976Sjmallett return; 3278215976Sjmallett if (prow->ifnum + 1 <= ifnum) { 3279215976Sjmallett if (*pfields < IFSTATS_FIELDS) 3280215976Sjmallett fprintf(fp, "Warning: incomplete row with %d (of %d) fields", 3281215976Sjmallett *pfields, IFSTATS_FIELDS); 3282215976Sjmallett *pfields = 0; 3283215976Sjmallett prow->ifnum = ifnum; 3284215976Sjmallett return; 3285215976Sjmallett } 3286215976Sjmallett fprintf(stderr, 3287215976Sjmallett "received if index %u, have %d of %d fields for index %u, aborting.\n", 3288215976Sjmallett ifnum, *pfields, IFSTATS_FIELDS, prow->ifnum); 3289215976Sjmallett exit(1); 3290215976Sjmallett} 3291215976Sjmallett 3292215976Sjmallett 3293215976Sjmallett/* 3294215976Sjmallett * another_ifstats_field - helper for ifstats() 3295215976Sjmallett * 3296215976Sjmallett * If all fields for the row have been received, print it. 3297215976Sjmallett */ 3298215976Sjmallettstatic void 3299215976Sjmallettanother_ifstats_field( 3300215976Sjmallett int * pfields, 3301215976Sjmallett ifstats_row * prow, 3302215976Sjmallett FILE * fp 3303215976Sjmallett ) 3304215976Sjmallett{ 3305215976Sjmallett u_int ifnum; 3306215976Sjmallett 3307215976Sjmallett (*pfields)++; 3308215976Sjmallett /* we understand 12 tags */ 3309215976Sjmallett if (IFSTATS_FIELDS > *pfields) 3310215976Sjmallett return; 3311215976Sjmallett /* 3312215976Sjmallett " interface name send\n" 3313215976Sjmallett " # address/broadcast drop flag ttl mc received sent failed peers uptime\n" 3314215976Sjmallett "==============================================================================\n"); 3315215976Sjmallett */ 3316215976Sjmallett fprintf(fp, 3317215976Sjmallett "%3u %-24.24s %c %4x %3d %2d %6d %6d %6d %5d %8d\n" 3318215976Sjmallett " %s\n", 3319215976Sjmallett prow->ifnum, prow->name, 3320215976Sjmallett (prow->enabled) 3321215976Sjmallett ? '.' 3322215976Sjmallett : 'D', 3323215976Sjmallett prow->flags, prow->ttl, prow->mcast_count, 3324215976Sjmallett prow->received, prow->sent, prow->send_errors, 3325215976Sjmallett prow->peer_count, prow->uptime, sptoa(&prow->addr)); 3326215976Sjmallett if (!SOCK_UNSPEC(&prow->bcast)) 3327215976Sjmallett fprintf(fp, " %s\n", sptoa(&prow->bcast)); 3328215976Sjmallett ifnum = prow->ifnum; 3329215976Sjmallett ZERO(*prow); 3330215976Sjmallett prow->ifnum = ifnum; 3331215976Sjmallett} 3332215976Sjmallett 3333215976Sjmallett 3334215976Sjmallett/* 3335215976Sjmallett * ifstats - ntpq -c ifstats modeled on ntpdc -c ifstats. 3336215976Sjmallett */ 3337215976Sjmallettstatic void 3338215976Sjmallettifstats( 3339215976Sjmallett struct parse * pcmd, 3340215976Sjmallett FILE * fp 3341215976Sjmallett ) 3342215976Sjmallett{ 3343215976Sjmallett const char addr_fmt[] = "addr.%u"; 3344215976Sjmallett const char bcast_fmt[] = "bcast.%u"; 3345215976Sjmallett const char en_fmt[] = "en.%u"; /* enabled */ 3346215976Sjmallett const char flags_fmt[] = "flags.%u"; 3347215976Sjmallett const char mc_fmt[] = "mc.%u"; /* mcast count */ 3348215976Sjmallett const char name_fmt[] = "name.%u"; 3349215976Sjmallett const char pc_fmt[] = "pc.%u"; /* peer count */ 3350215976Sjmallett const char rx_fmt[] = "rx.%u"; 3351215976Sjmallett const char tl_fmt[] = "tl.%u"; /* ttl */ 3352215976Sjmallett const char tx_fmt[] = "tx.%u"; 3353215976Sjmallett const char txerr_fmt[] = "txerr.%u"; 3354215976Sjmallett const char up_fmt[] = "up.%u"; /* uptime */ 3355215976Sjmallett const char * datap; 3356215976Sjmallett int qres; 3357215976Sjmallett size_t dsize; 3358215976Sjmallett u_short rstatus; 3359215976Sjmallett char * tag; 3360215976Sjmallett char * val; 3361215976Sjmallett int fields; 3362215976Sjmallett u_int ui; 3363215976Sjmallett ifstats_row row; 3364215976Sjmallett int comprende; 3365215976Sjmallett size_t len; 3366215976Sjmallett 3367215976Sjmallett qres = doquery(CTL_OP_READ_ORDLIST_A, 0, TRUE, 0, NULL, &rstatus, 3368215976Sjmallett &dsize, &datap); 3369215976Sjmallett if (qres) /* message already displayed */ 3370215976Sjmallett return; 3371215976Sjmallett 3372215976Sjmallett fprintf(fp, 3373215976Sjmallett " interface name send\n" 3374215976Sjmallett " # address/broadcast drop flag ttl mc received sent failed peers uptime\n" 3375215976Sjmallett "==============================================================================\n"); 3376215976Sjmallett /* '=' x 78 */ 3377215976Sjmallett 3378215976Sjmallett ZERO(row); 3379215976Sjmallett fields = 0; 3380215976Sjmallett ui = 0; 3381215976Sjmallett while (nextvar(&dsize, &datap, &tag, &val)) { 3382215976Sjmallett if (debug > 1) 3383215976Sjmallett fprintf(stderr, "nextvar gave: %s = %s\n", tag, 3384215976Sjmallett (NULL == val) 3385215976Sjmallett ? "" 3386215976Sjmallett : val); 3387215976Sjmallett comprende = FALSE; 3388215976Sjmallett switch(tag[0]) { 3389215976Sjmallett 3390215976Sjmallett case 'a': 3391215976Sjmallett if (1 == sscanf(tag, addr_fmt, &ui) && 3392215976Sjmallett decodenetnum(val, &row.addr)) 3393215976Sjmallett comprende = TRUE; 3394215976Sjmallett break; 3395215976Sjmallett 3396215976Sjmallett case 'b': 3397215976Sjmallett if (1 == sscanf(tag, bcast_fmt, &ui) && 3398215976Sjmallett (NULL == val || 3399215976Sjmallett decodenetnum(val, &row.bcast))) 3400215976Sjmallett comprende = TRUE; 3401215976Sjmallett break; 3402215976Sjmallett 3403215976Sjmallett case 'e': 3404215976Sjmallett if (1 == sscanf(tag, en_fmt, &ui) && 3405215976Sjmallett 1 == sscanf(val, "%d", &row.enabled)) 3406215976Sjmallett comprende = TRUE; 3407215976Sjmallett break; 3408215976Sjmallett 3409215976Sjmallett case 'f': 3410215976Sjmallett if (1 == sscanf(tag, flags_fmt, &ui) && 3411215976Sjmallett 1 == sscanf(val, "0x%x", &row.flags)) 3412215976Sjmallett comprende = TRUE; 3413215976Sjmallett break; 3414215976Sjmallett 3415215976Sjmallett case 'm': 3416215976Sjmallett if (1 == sscanf(tag, mc_fmt, &ui) && 3417215976Sjmallett 1 == sscanf(val, "%d", &row.mcast_count)) 3418215976Sjmallett comprende = TRUE; 3419215976Sjmallett break; 3420215976Sjmallett 3421215976Sjmallett case 'n': 3422215976Sjmallett if (1 == sscanf(tag, name_fmt, &ui)) { 3423215976Sjmallett /* strip quotes */ 3424215976Sjmallett INSIST(val); 3425215976Sjmallett len = strlen(val); 3426215976Sjmallett if (len >= 2 && 3427215976Sjmallett len - 2 < sizeof(row.name)) { 3428215976Sjmallett len -= 2; 3429215976Sjmallett memcpy(row.name, val + 1, len); 3430215976Sjmallett row.name[len] = '\0'; 3431215976Sjmallett comprende = TRUE; 3432215976Sjmallett } 3433215976Sjmallett } 3434215976Sjmallett break; 3435215976Sjmallett 3436215976Sjmallett case 'p': 3437215976Sjmallett if (1 == sscanf(tag, pc_fmt, &ui) && 3438215976Sjmallett 1 == sscanf(val, "%d", &row.peer_count)) 3439215976Sjmallett comprende = TRUE; 3440215976Sjmallett break; 3441215976Sjmallett 3442215976Sjmallett case 'r': 3443215976Sjmallett if (1 == sscanf(tag, rx_fmt, &ui) && 3444215976Sjmallett 1 == sscanf(val, "%d", &row.received)) 3445215976Sjmallett comprende = TRUE; 3446215976Sjmallett break; 3447215976Sjmallett 3448215976Sjmallett case 't': 3449215976Sjmallett if (1 == sscanf(tag, tl_fmt, &ui) && 3450215976Sjmallett 1 == sscanf(val, "%d", &row.ttl)) 3451215976Sjmallett comprende = TRUE; 3452215976Sjmallett else if (1 == sscanf(tag, tx_fmt, &ui) && 3453215976Sjmallett 1 == sscanf(val, "%d", &row.sent)) 3454215976Sjmallett comprende = TRUE; 3455215976Sjmallett else if (1 == sscanf(tag, txerr_fmt, &ui) && 3456215976Sjmallett 1 == sscanf(val, "%d", &row.send_errors)) 3457215976Sjmallett comprende = TRUE; 3458215976Sjmallett break; 3459215976Sjmallett 3460215976Sjmallett case 'u': 3461215976Sjmallett if (1 == sscanf(tag, up_fmt, &ui) && 3462215976Sjmallett 1 == sscanf(val, "%d", &row.uptime)) 3463215976Sjmallett comprende = TRUE; 3464215976Sjmallett break; 3465215976Sjmallett } 3466215976Sjmallett 3467215976Sjmallett if (comprende) { 3468215976Sjmallett /* error out if rows out of order */ 3469215976Sjmallett validate_ifnum(fp, ui, &fields, &row); 3470215976Sjmallett /* if the row is complete, print it */ 3471215976Sjmallett another_ifstats_field(&fields, &row, fp); 3472215976Sjmallett } 3473215976Sjmallett } 3474215976Sjmallett if (fields != IFSTATS_FIELDS) 3475215976Sjmallett fprintf(fp, "Warning: incomplete row with %d (of %d) fields", 3476215976Sjmallett fields, IFSTATS_FIELDS); 3477215976Sjmallett 3478215976Sjmallett fflush(fp); 3479215976Sjmallett} 3480215976Sjmallett 3481215976Sjmallett 3482215976Sjmallett/* 3483215976Sjmallett * validate_reslist_idx - helper for reslist() 3484215976Sjmallett * 3485215976Sjmallett * Ensures rows are received in order and complete. 3486215976Sjmallett */ 3487215976Sjmallettstatic void 3488215976Sjmallettvalidate_reslist_idx( 3489215976Sjmallett FILE * fp, 3490215976Sjmallett u_int idx, 3491215976Sjmallett int * pfields, 3492215976Sjmallett reslist_row * prow 3493215976Sjmallett ) 3494215976Sjmallett{ 3495215976Sjmallett if (prow->idx == idx) 3496215976Sjmallett return; 3497215976Sjmallett if (prow->idx + 1 == idx) { 3498215976Sjmallett if (*pfields < RESLIST_FIELDS) 3499215976Sjmallett fprintf(fp, "Warning: incomplete row with %d (of %d) fields", 3500215976Sjmallett *pfields, RESLIST_FIELDS); 3501215976Sjmallett *pfields = 0; 3502215976Sjmallett prow->idx = idx; 3503215976Sjmallett return; 3504215976Sjmallett } 3505215976Sjmallett fprintf(stderr, 3506215976Sjmallett "received reslist index %u, have %d of %d fields for index %u, aborting.\n", 3507215976Sjmallett idx, *pfields, RESLIST_FIELDS, prow->idx); 3508215976Sjmallett exit(1); 3509215976Sjmallett} 3510215976Sjmallett 3511215976Sjmallett 3512215976Sjmallett/* 3513215976Sjmallett * another_reslist_field - helper for reslist() 3514215976Sjmallett * 3515215976Sjmallett * If all fields for the row have been received, print it. 3516215976Sjmallett */ 3517215976Sjmallettstatic void 3518215976Sjmallettanother_reslist_field( 3519215976Sjmallett int * pfields, 3520215976Sjmallett reslist_row * prow, 3521215976Sjmallett FILE * fp 3522215976Sjmallett ) 3523215976Sjmallett{ 3524215976Sjmallett char addrmaskstr[128]; 3525215976Sjmallett int prefix; /* subnet mask as prefix bits count */ 3526215976Sjmallett u_int idx; 3527215976Sjmallett 3528215976Sjmallett (*pfields)++; 3529215976Sjmallett /* we understand 4 tags */ 3530215976Sjmallett if (RESLIST_FIELDS > *pfields) 3531215976Sjmallett return; 3532215976Sjmallett 3533215976Sjmallett prefix = sockaddr_masktoprefixlen(&prow->mask); 3534215976Sjmallett if (prefix >= 0) 3535215976Sjmallett snprintf(addrmaskstr, sizeof(addrmaskstr), "%s/%d", 3536215976Sjmallett stoa(&prow->addr), prefix); 3537215976Sjmallett else 3538215976Sjmallett snprintf(addrmaskstr, sizeof(addrmaskstr), "%s %s", 3539215976Sjmallett stoa(&prow->addr), stoa(&prow->mask)); 3540215976Sjmallett 3541215976Sjmallett /* 3542215976Sjmallett " hits addr/prefix or addr mask\n" 3543215976Sjmallett " restrictions\n" 3544215976Sjmallett "==============================================================================\n"); 3545215976Sjmallett */ 3546215976Sjmallett fprintf(fp, 3547215976Sjmallett "%10lu %s\n" 3548215976Sjmallett " %s\n", 3549215976Sjmallett prow->hits, addrmaskstr, prow->flagstr); 3550215976Sjmallett idx = prow->idx; 3551215976Sjmallett ZERO(*prow); 3552215976Sjmallett prow->idx = idx; 3553215976Sjmallett} 3554215976Sjmallett 3555215976Sjmallett 3556215976Sjmallett/* 3557215976Sjmallett * reslist - ntpq -c reslist modeled on ntpdc -c reslist. 3558215976Sjmallett */ 3559215976Sjmallettstatic void 3560215976Sjmallettreslist( 3561215976Sjmallett struct parse * pcmd, 3562215976Sjmallett FILE * fp 3563215976Sjmallett ) 3564215976Sjmallett{ 3565215976Sjmallett const char addr_fmtu[] = "addr.%u"; 3566215976Sjmallett const char mask_fmtu[] = "mask.%u"; 3567215976Sjmallett const char hits_fmt[] = "hits.%u"; 3568215976Sjmallett const char flags_fmt[] = "flags.%u"; 3569215976Sjmallett const char qdata[] = "addr_restrictions"; 3570215976Sjmallett const int qdata_chars = COUNTOF(qdata) - 1; 3571215976Sjmallett const char * datap; 3572215976Sjmallett int qres; 3573215976Sjmallett size_t dsize; 3574215976Sjmallett u_short rstatus; 3575215976Sjmallett char * tag; 3576215976Sjmallett char * val; 3577215976Sjmallett int fields; 3578215976Sjmallett u_int ui; 3579215976Sjmallett reslist_row row; 3580215976Sjmallett int comprende; 3581215976Sjmallett size_t len; 3582215976Sjmallett 3583215976Sjmallett qres = doquery(CTL_OP_READ_ORDLIST_A, 0, TRUE, qdata_chars, 3584215976Sjmallett qdata, &rstatus, &dsize, &datap); 3585215976Sjmallett if (qres) /* message already displayed */ 3586215976Sjmallett return; 3587215976Sjmallett 3588215976Sjmallett fprintf(fp, 3589215976Sjmallett " hits addr/prefix or addr mask\n" 3590215976Sjmallett " restrictions\n" 3591215976Sjmallett "==============================================================================\n"); 3592215976Sjmallett /* '=' x 78 */ 3593215976Sjmallett 3594215976Sjmallett ZERO(row); 3595215976Sjmallett fields = 0; 3596215976Sjmallett ui = 0; 3597215976Sjmallett while (nextvar(&dsize, &datap, &tag, &val)) { 3598215976Sjmallett if (debug > 1) 3599215976Sjmallett fprintf(stderr, "nextvar gave: %s = %s\n", tag, 3600215976Sjmallett (NULL == val) 3601215976Sjmallett ? "" 3602215976Sjmallett : val); 3603215976Sjmallett comprende = FALSE; 3604215976Sjmallett switch(tag[0]) { 3605215976Sjmallett 3606215976Sjmallett case 'a': 3607215976Sjmallett if (1 == sscanf(tag, addr_fmtu, &ui) && 3608215976Sjmallett decodenetnum(val, &row.addr)) 3609215976Sjmallett comprende = TRUE; 3610215976Sjmallett break; 3611215976Sjmallett 3612215976Sjmallett case 'f': 3613215976Sjmallett if (1 == sscanf(tag, flags_fmt, &ui)) { 3614215976Sjmallett if (NULL == val) { 3615215976Sjmallett row.flagstr[0] = '\0'; 3616215976Sjmallett comprende = TRUE; 3617215976Sjmallett } else if ((len = strlen(val)) < sizeof(row.flagstr)) { 3618215976Sjmallett memcpy(row.flagstr, val, len); 3619215976Sjmallett row.flagstr[len] = '\0'; 3620215976Sjmallett comprende = TRUE; 3621215976Sjmallett } else { 3622215976Sjmallett /* no flags, and still !comprende */ 3623215976Sjmallett row.flagstr[0] = '\0'; 3624215976Sjmallett } 3625215976Sjmallett } 3626215976Sjmallett break; 3627215976Sjmallett 3628215976Sjmallett case 'h': 3629215976Sjmallett if (1 == sscanf(tag, hits_fmt, &ui) && 3630215976Sjmallett 1 == sscanf(val, "%lu", &row.hits)) 3631215976Sjmallett comprende = TRUE; 3632215976Sjmallett break; 3633215976Sjmallett 3634215976Sjmallett case 'm': 3635215976Sjmallett if (1 == sscanf(tag, mask_fmtu, &ui) && 3636215976Sjmallett decodenetnum(val, &row.mask)) 3637215976Sjmallett comprende = TRUE; 3638215976Sjmallett break; 3639215976Sjmallett } 3640215976Sjmallett 3641215976Sjmallett if (comprende) { 3642215976Sjmallett /* error out if rows out of order */ 3643215976Sjmallett validate_reslist_idx(fp, ui, &fields, &row); 3644215976Sjmallett /* if the row is complete, print it */ 3645215976Sjmallett another_reslist_field(&fields, &row, fp); 3646215976Sjmallett } 3647215976Sjmallett } 3648215976Sjmallett if (fields != RESLIST_FIELDS) 3649215976Sjmallett fprintf(fp, "Warning: incomplete row with %d (of %d) fields", 3650215976Sjmallett fields, RESLIST_FIELDS); 3651215976Sjmallett 3652215976Sjmallett fflush(fp); 3653215976Sjmallett} 3654215976Sjmallett 3655215976Sjmallett 3656215976Sjmallett/* 3657215976Sjmallett * collect_display_vdc 3658215976Sjmallett */ 3659215976Sjmallettstatic void 3660215976Sjmallettcollect_display_vdc( 3661215976Sjmallett associd_t as, 3662215976Sjmallett vdc * table, 3663215976Sjmallett int decodestatus, 3664215976Sjmallett FILE * fp 3665215976Sjmallett ) 3666215976Sjmallett{ 3667215976Sjmallett static const char * const suf[2] = { "adr", "port" }; 3668215976Sjmallett static const char * const leapbits[4] = { "00", "01", 3669215976Sjmallett "10", "11" }; 3670215976Sjmallett struct varlist vl[MAXLIST]; 3671215976Sjmallett char tagbuf[32]; 3672215976Sjmallett vdc *pvdc; 3673215976Sjmallett u_short rstatus; 3674215976Sjmallett size_t rsize; 3675215976Sjmallett const char *rdata; 3676215976Sjmallett int qres; 3677215976Sjmallett char *tag; 3678215976Sjmallett char *val; 3679215976Sjmallett u_int n; 3680215976Sjmallett size_t len; 3681215976Sjmallett int match; 3682215976Sjmallett u_long ul; 3683215976Sjmallett int vtype; 3684215976Sjmallett 3685215976Sjmallett ZERO(vl); 3686215976Sjmallett for (pvdc = table; pvdc->tag != NULL; pvdc++) { 3687215976Sjmallett ZERO(pvdc->v); 3688215976Sjmallett if (NTP_ADD != pvdc->type) { 3689215976Sjmallett doaddvlist(vl, pvdc->tag); 3690215976Sjmallett } else { 3691215976Sjmallett for (n = 0; n < COUNTOF(suf); n++) { 3692215976Sjmallett snprintf(tagbuf, sizeof(tagbuf), "%s%s", 3693215976Sjmallett pvdc->tag, suf[n]); 3694215976Sjmallett doaddvlist(vl, tagbuf); 3695215976Sjmallett } 3696215976Sjmallett } 3697215976Sjmallett } 3698215976Sjmallett qres = doquerylist(vl, CTL_OP_READVAR, as, 0, &rstatus, &rsize, 3699215976Sjmallett &rdata); 3700215976Sjmallett doclearvlist(vl); 3701215976Sjmallett if (qres) 3702215976Sjmallett return; /* error msg already displayed */ 3703215976Sjmallett 3704215976Sjmallett /* 3705215976Sjmallett * iterate over the response variables filling vdc_table with 3706215976Sjmallett * the retrieved values. 3707215976Sjmallett */ 3708215976Sjmallett while (nextvar(&rsize, &rdata, &tag, &val)) { 3709215976Sjmallett if (NULL == val) 3710215976Sjmallett continue; 3711215976Sjmallett n = 0; 3712215976Sjmallett for (pvdc = table; pvdc->tag != NULL; pvdc++) { 3713215976Sjmallett len = strlen(pvdc->tag); 3714215976Sjmallett if (strncmp(tag, pvdc->tag, len)) 3715215976Sjmallett continue; 3716215976Sjmallett if (NTP_ADD != pvdc->type) { 3717215976Sjmallett if ('\0' != tag[len]) 3718215976Sjmallett continue; 3719215976Sjmallett break; 3720215976Sjmallett } 3721215976Sjmallett match = FALSE; 3722215976Sjmallett for (n = 0; n < COUNTOF(suf); n++) { 3723215976Sjmallett if (strcmp(tag + len, suf[n])) 3724215976Sjmallett continue; 3725215976Sjmallett match = TRUE; 3726215976Sjmallett break; 3727215976Sjmallett } 3728215976Sjmallett if (match) 3729215976Sjmallett break; 3730215976Sjmallett } 3731215976Sjmallett if (NULL == pvdc->tag) 3732215976Sjmallett continue; 3733215976Sjmallett switch (pvdc->type) { 3734215976Sjmallett 3735215976Sjmallett case NTP_STR: 3736215976Sjmallett /* strip surrounding double quotes */ 3737215976Sjmallett if ('"' == val[0]) { 3738215976Sjmallett len = strlen(val); 3739215976Sjmallett if (len > 0 && '"' == val[len - 1]) { 3740215976Sjmallett val[len - 1] = '\0'; 3741215976Sjmallett val++; 3742215976Sjmallett } 3743215976Sjmallett } 3744215976Sjmallett /* fallthru */ 3745215976Sjmallett case NTP_MODE: /* fallthru */ 3746215976Sjmallett case NTP_2BIT: 3747215976Sjmallett pvdc->v.str = estrdup(val); 3748215976Sjmallett break; 3749215976Sjmallett 3750215976Sjmallett case NTP_LFP: 3751215976Sjmallett decodets(val, &pvdc->v.lfp); 3752215976Sjmallett break; 3753215976Sjmallett 3754215976Sjmallett case NTP_ADP: 3755215976Sjmallett if (!decodenetnum(val, &pvdc->v.sau)) 3756215976Sjmallett fprintf(stderr, "malformed %s=%s\n", 3757215976Sjmallett pvdc->tag, val); 3758215976Sjmallett break; 3759215976Sjmallett 3760215976Sjmallett case NTP_ADD: 3761215976Sjmallett if (0 == n) { /* adr */ 3762215976Sjmallett if (!decodenetnum(val, &pvdc->v.sau)) 3763215976Sjmallett fprintf(stderr, 3764215976Sjmallett "malformed %s=%s\n", 3765215976Sjmallett pvdc->tag, val); 3766215976Sjmallett } else { /* port */ 3767215976Sjmallett if (atouint(val, &ul)) 3768215976Sjmallett SET_PORT(&pvdc->v.sau, 3769215976Sjmallett (u_short)ul); 3770215976Sjmallett } 3771215976Sjmallett break; 3772215976Sjmallett } 3773215976Sjmallett } 3774215976Sjmallett 3775215976Sjmallett /* and display */ 3776215976Sjmallett if (decodestatus) { 3777215976Sjmallett vtype = (0 == as) 3778215976Sjmallett ? TYPE_SYS 3779215976Sjmallett : TYPE_PEER; 3780215976Sjmallett fprintf(fp, "associd=%u status=%04x %s,\n", as, rstatus, 3781215976Sjmallett statustoa(vtype, rstatus)); 3782215976Sjmallett } 3783215976Sjmallett 3784215976Sjmallett for (pvdc = table; pvdc->tag != NULL; pvdc++) { 3785215976Sjmallett switch (pvdc->type) { 3786215976Sjmallett 3787215976Sjmallett case NTP_STR: 3788215976Sjmallett if (pvdc->v.str != NULL) { 3789215976Sjmallett fprintf(fp, "%s %s\n", pvdc->display, 3790215976Sjmallett pvdc->v.str); 3791215976Sjmallett free(pvdc->v.str); 3792215976Sjmallett pvdc->v.str = NULL; 3793215976Sjmallett } 3794215976Sjmallett break; 3795215976Sjmallett 3796215976Sjmallett case NTP_ADD: /* fallthru */ 3797215976Sjmallett case NTP_ADP: 3798215976Sjmallett fprintf(fp, "%s %s\n", pvdc->display, 3799215976Sjmallett nntohostp(&pvdc->v.sau)); 3800215976Sjmallett break; 3801215976Sjmallett 3802215976Sjmallett case NTP_LFP: 3803215976Sjmallett fprintf(fp, "%s %s\n", pvdc->display, 3804215976Sjmallett prettydate(&pvdc->v.lfp)); 3805215976Sjmallett break; 3806215976Sjmallett 3807215976Sjmallett case NTP_MODE: 3808215976Sjmallett atouint(pvdc->v.str, &ul); 3809215976Sjmallett fprintf(fp, "%s %s\n", pvdc->display, 3810215976Sjmallett modetoa((int)ul)); 3811215976Sjmallett break; 3812215976Sjmallett 3813215976Sjmallett case NTP_2BIT: 3814215976Sjmallett atouint(pvdc->v.str, &ul); 3815215976Sjmallett fprintf(fp, "%s %s\n", pvdc->display, 3816215976Sjmallett leapbits[ul & 0x3]); 3817215976Sjmallett break; 3818215976Sjmallett 3819215976Sjmallett default: 3820215976Sjmallett fprintf(stderr, "unexpected vdc type %d for %s\n", 3821215976Sjmallett pvdc->type, pvdc->tag); 3822215976Sjmallett break; 3823215976Sjmallett } 3824215976Sjmallett } 3825215976Sjmallett} 3826215976Sjmallett 3827215976Sjmallett 3828215976Sjmallett/* 3829215976Sjmallett * sysstats - implements ntpq -c sysstats modeled on ntpdc -c sysstats 3830215976Sjmallett */ 3831215976Sjmallettstatic void 3832215976Sjmallettsysstats( 3833215976Sjmallett struct parse *pcmd, 3834215976Sjmallett FILE *fp 3835215976Sjmallett ) 3836215976Sjmallett{ 3837215976Sjmallett static vdc sysstats_vdc[] = { 3838215976Sjmallett VDC_INIT("ss_uptime", "uptime: ", NTP_STR), 3839215976Sjmallett VDC_INIT("ss_reset", "sysstats reset: ", NTP_STR), 3840215976Sjmallett VDC_INIT("ss_received", "packets received: ", NTP_STR), 3841215976Sjmallett VDC_INIT("ss_thisver", "current version: ", NTP_STR), 3842215976Sjmallett VDC_INIT("ss_oldver", "older version: ", NTP_STR), 3843215976Sjmallett VDC_INIT("ss_badformat", "bad length or format: ", NTP_STR), 3844215976Sjmallett VDC_INIT("ss_badauth", "authentication failed:", NTP_STR), 3845215976Sjmallett VDC_INIT("ss_declined", "declined: ", NTP_STR), 3846215976Sjmallett VDC_INIT("ss_restricted", "restricted: ", NTP_STR), 3847215976Sjmallett VDC_INIT("ss_limited", "rate limited: ", NTP_STR), 3848215976Sjmallett VDC_INIT("ss_kodsent", "KoD responses: ", NTP_STR), 3849215976Sjmallett VDC_INIT("ss_processed", "processed for time: ", NTP_STR), 3850215976Sjmallett VDC_INIT(NULL, NULL, 0) 3851215976Sjmallett }; 3852215976Sjmallett 3853215976Sjmallett collect_display_vdc(0, sysstats_vdc, FALSE, fp); 3854215976Sjmallett} 3855215976Sjmallett 3856215976Sjmallett 3857215976Sjmallett/* 3858215976Sjmallett * sysinfo - modeled on ntpdc's sysinfo 3859215976Sjmallett */ 3860215976Sjmallettstatic void 3861215976Sjmallettsysinfo( 3862215976Sjmallett struct parse *pcmd, 3863215976Sjmallett FILE *fp 3864215976Sjmallett ) 3865215976Sjmallett{ 3866215976Sjmallett static vdc sysinfo_vdc[] = { 3867215976Sjmallett VDC_INIT("peeradr", "system peer: ", NTP_ADP), 3868215976Sjmallett VDC_INIT("peermode", "system peer mode: ", NTP_MODE), 3869215976Sjmallett VDC_INIT("leap", "leap indicator: ", NTP_2BIT), 3870215976Sjmallett VDC_INIT("stratum", "stratum: ", NTP_STR), 3871215976Sjmallett VDC_INIT("precision", "log2 precision: ", NTP_STR), 3872215976Sjmallett VDC_INIT("rootdelay", "root delay: ", NTP_STR), 3873215976Sjmallett VDC_INIT("rootdisp", "root dispersion: ", NTP_STR), 3874215976Sjmallett VDC_INIT("refid", "reference ID: ", NTP_STR), 3875215976Sjmallett VDC_INIT("reftime", "reference time: ", NTP_LFP), 3876215976Sjmallett VDC_INIT("sys_jitter", "system jitter: ", NTP_STR), 3877215976Sjmallett VDC_INIT("clk_jitter", "clock jitter: ", NTP_STR), 3878215976Sjmallett VDC_INIT("clk_wander", "clock wander: ", NTP_STR), 3879215976Sjmallett VDC_INIT("bcastdelay", "broadcast delay: ", NTP_STR), 3880215976Sjmallett VDC_INIT("authdelay", "symm. auth. delay:", NTP_STR), 3881215976Sjmallett VDC_INIT(NULL, NULL, 0) 3882215976Sjmallett }; 3883215976Sjmallett 3884215976Sjmallett collect_display_vdc(0, sysinfo_vdc, TRUE, fp); 3885215976Sjmallett} 3886215976Sjmallett 3887215976Sjmallett 3888215976Sjmallett/* 3889215976Sjmallett * kerninfo - modeled on ntpdc's kerninfo 3890215976Sjmallett */ 3891215976Sjmallettstatic void 3892215976Sjmallettkerninfo( 3893215976Sjmallett struct parse *pcmd, 3894215976Sjmallett FILE *fp 3895215976Sjmallett ) 3896215976Sjmallett{ 3897215976Sjmallett static vdc kerninfo_vdc[] = { 3898215976Sjmallett VDC_INIT("koffset", "pll offset: ", NTP_STR), 3899215976Sjmallett VDC_INIT("kfreq", "pll frequency: ", NTP_STR), 3900215976Sjmallett VDC_INIT("kmaxerr", "maximum error: ", NTP_STR), 3901215976Sjmallett VDC_INIT("kesterr", "estimated error: ", NTP_STR), 3902215976Sjmallett VDC_INIT("kstflags", "kernel status: ", NTP_STR), 3903215976Sjmallett VDC_INIT("ktimeconst", "pll time constant: ", NTP_STR), 3904215976Sjmallett VDC_INIT("kprecis", "precision: ", NTP_STR), 3905215976Sjmallett VDC_INIT("kfreqtol", "frequency tolerance: ", NTP_STR), 3906215976Sjmallett VDC_INIT("kppsfreq", "pps frequency: ", NTP_STR), 3907215976Sjmallett VDC_INIT("kppsstab", "pps stability: ", NTP_STR), 3908215976Sjmallett VDC_INIT("kppsjitter", "pps jitter: ", NTP_STR), 3909215976Sjmallett VDC_INIT("kppscalibdur", "calibration interval ", NTP_STR), 3910215976Sjmallett VDC_INIT("kppscalibs", "calibration cycles: ", NTP_STR), 3911215976Sjmallett VDC_INIT("kppsjitexc", "jitter exceeded: ", NTP_STR), 3912215976Sjmallett VDC_INIT("kppsstbexc", "stability exceeded: ", NTP_STR), 3913215976Sjmallett VDC_INIT("kppscaliberrs", "calibration errors: ", NTP_STR), 3914215976Sjmallett VDC_INIT(NULL, NULL, 0) 3915215976Sjmallett }; 3916215976Sjmallett 3917215976Sjmallett collect_display_vdc(0, kerninfo_vdc, TRUE, fp); 3918215976Sjmallett} 3919215976Sjmallett 3920215976Sjmallett 3921215976Sjmallett/* 3922215976Sjmallett * monstats - implements ntpq -c monstats 3923215976Sjmallett */ 3924215976Sjmallettstatic void 3925215976Sjmallettmonstats( 3926215976Sjmallett struct parse *pcmd, 3927215976Sjmallett FILE *fp 3928215976Sjmallett ) 3929215976Sjmallett{ 3930215976Sjmallett static vdc monstats_vdc[] = { 3931215976Sjmallett VDC_INIT("mru_enabled", "enabled: ", NTP_STR), 3932215976Sjmallett VDC_INIT("mru_depth", "addresses: ", NTP_STR), 3933215976Sjmallett VDC_INIT("mru_deepest", "peak addresses: ", NTP_STR), 3934215976Sjmallett VDC_INIT("mru_maxdepth", "maximum addresses: ", NTP_STR), 3935215976Sjmallett VDC_INIT("mru_mindepth", "reclaim above count:", NTP_STR), 3936215976Sjmallett VDC_INIT("mru_maxage", "reclaim older than: ", NTP_STR), 3937215976Sjmallett VDC_INIT("mru_mem", "kilobytes: ", NTP_STR), 3938215976Sjmallett VDC_INIT("mru_maxmem", "maximum kilobytes: ", NTP_STR), 3939215976Sjmallett VDC_INIT(NULL, NULL, 0) 3940215976Sjmallett }; 3941215976Sjmallett 3942215976Sjmallett collect_display_vdc(0, monstats_vdc, FALSE, fp); 3943215976Sjmallett} 3944215976Sjmallett 3945215976Sjmallett 3946215976Sjmallett/* 3947215976Sjmallett * iostats - ntpq -c iostats - network input and output counters 3948215976Sjmallett */ 3949215976Sjmallettstatic void 3950215976Sjmallettiostats( 3951215976Sjmallett struct parse *pcmd, 3952215976Sjmallett FILE *fp 3953215976Sjmallett ) 3954215976Sjmallett{ 3955215976Sjmallett static vdc iostats_vdc[] = { 3956215976Sjmallett VDC_INIT("iostats_reset", "time since reset: ", NTP_STR), 3957215976Sjmallett VDC_INIT("total_rbuf", "receive buffers: ", NTP_STR), 3958215976Sjmallett VDC_INIT("free_rbuf", "free receive buffers: ", NTP_STR), 3959215976Sjmallett VDC_INIT("used_rbuf", "used receive buffers: ", NTP_STR), 3960215976Sjmallett VDC_INIT("rbuf_lowater", "low water refills: ", NTP_STR), 3961215976Sjmallett VDC_INIT("io_dropped", "dropped packets: ", NTP_STR), 3962215976Sjmallett VDC_INIT("io_ignored", "ignored packets: ", NTP_STR), 3963215976Sjmallett VDC_INIT("io_received", "received packets: ", NTP_STR), 3964215976Sjmallett VDC_INIT("io_sent", "packets sent: ", NTP_STR), 3965215976Sjmallett VDC_INIT("io_sendfailed", "packet send failures: ", NTP_STR), 3966215976Sjmallett VDC_INIT("io_wakeups", "input wakeups: ", NTP_STR), 3967215976Sjmallett VDC_INIT("io_goodwakeups", "useful input wakeups: ", NTP_STR), 3968215976Sjmallett VDC_INIT(NULL, NULL, 0) 3969215976Sjmallett }; 3970215976Sjmallett 3971215976Sjmallett collect_display_vdc(0, iostats_vdc, FALSE, fp); 3972215976Sjmallett} 3973215976Sjmallett 3974215976Sjmallett 3975215976Sjmallett/* 3976215976Sjmallett * timerstats - ntpq -c timerstats - interval timer counters 3977215976Sjmallett */ 3978215976Sjmallettstatic void 3979215976Sjmalletttimerstats( 3980215976Sjmallett struct parse *pcmd, 3981215976Sjmallett FILE *fp 3982215976Sjmallett ) 3983215976Sjmallett{ 3984215976Sjmallett static vdc timerstats_vdc[] = { 3985215976Sjmallett VDC_INIT("timerstats_reset", "time since reset: ", NTP_STR), 3986215976Sjmallett VDC_INIT("timer_overruns", "timer overruns: ", NTP_STR), 3987215976Sjmallett VDC_INIT("timer_xmts", "calls to transmit: ", NTP_STR), 3988215976Sjmallett VDC_INIT(NULL, NULL, 0) 3989215976Sjmallett }; 3990215976Sjmallett 3991215976Sjmallett collect_display_vdc(0, timerstats_vdc, FALSE, fp); 3992215976Sjmallett} 3993215976Sjmallett 3994215976Sjmallett 3995215976Sjmallett/* 3996215976Sjmallett * authinfo - implements ntpq -c authinfo 3997215976Sjmallett */ 3998215976Sjmallettstatic void 3999215976Sjmallettauthinfo( 4000215976Sjmallett struct parse *pcmd, 4001215976Sjmallett FILE *fp 4002215976Sjmallett ) 4003215976Sjmallett{ 4004215976Sjmallett static vdc authinfo_vdc[] = { 4005215976Sjmallett VDC_INIT("authreset", "time since reset:", NTP_STR), 4006215976Sjmallett VDC_INIT("authkeys", "stored keys: ", NTP_STR), 4007215976Sjmallett VDC_INIT("authfreek", "free keys: ", NTP_STR), 4008215976Sjmallett VDC_INIT("authklookups", "key lookups: ", NTP_STR), 4009215976Sjmallett VDC_INIT("authknotfound", "keys not found: ", NTP_STR), 4010215976Sjmallett VDC_INIT("authkuncached", "uncached keys: ", NTP_STR), 4011215976Sjmallett VDC_INIT("authkexpired", "expired keys: ", NTP_STR), 4012215976Sjmallett VDC_INIT("authencrypts", "encryptions: ", NTP_STR), 4013215976Sjmallett VDC_INIT("authdecrypts", "decryptions: ", NTP_STR), 4014215976Sjmallett VDC_INIT(NULL, NULL, 0) 4015215976Sjmallett }; 4016215976Sjmallett 4017215976Sjmallett collect_display_vdc(0, authinfo_vdc, FALSE, fp); 4018215976Sjmallett} 4019215976Sjmallett 4020215976Sjmallett 4021215976Sjmallett/* 4022215976Sjmallett * pstats - show statistics for a peer 4023215976Sjmallett */ 4024215976Sjmallettstatic void 4025215976Sjmallettpstats( 4026215976Sjmallett struct parse *pcmd, 4027215976Sjmallett FILE *fp 4028215976Sjmallett ) 4029215976Sjmallett{ 4030215976Sjmallett static vdc pstats_vdc[] = { 4031215976Sjmallett VDC_INIT("src", "remote host: ", NTP_ADD), 4032215976Sjmallett VDC_INIT("dst", "local address: ", NTP_ADD), 4033215976Sjmallett VDC_INIT("timerec", "time last received: ", NTP_STR), 4034215976Sjmallett VDC_INIT("timer", "time until next send:", NTP_STR), 4035215976Sjmallett VDC_INIT("timereach", "reachability change: ", NTP_STR), 4036215976Sjmallett VDC_INIT("sent", "packets sent: ", NTP_STR), 4037215976Sjmallett VDC_INIT("received", "packets received: ", NTP_STR), 4038215976Sjmallett VDC_INIT("badauth", "bad authentication: ", NTP_STR), 4039215976Sjmallett VDC_INIT("bogusorg", "bogus origin: ", NTP_STR), 4040215976Sjmallett VDC_INIT("oldpkt", "duplicate: ", NTP_STR), 4041215976Sjmallett VDC_INIT("seldisp", "bad dispersion: ", NTP_STR), 4042215976Sjmallett VDC_INIT("selbroken", "bad reference time: ", NTP_STR), 4043215976Sjmallett VDC_INIT("candidate", "candidate order: ", NTP_STR), 4044215976Sjmallett VDC_INIT(NULL, NULL, 0) 4045215976Sjmallett }; 4046215976Sjmallett associd_t associd; 4047215976Sjmallett 4048215976Sjmallett associd = checkassocid(pcmd->argval[0].uval); 4049215976Sjmallett if (0 == associd) 4050215976Sjmallett return; 4051215976Sjmallett 4052215976Sjmallett collect_display_vdc(associd, pstats_vdc, TRUE, fp); 4053215976Sjmallett} 4054215976Sjmallett