1 1.11 christos /* $NetBSD: ntpdc_ops.c,v 1.11 2020/05/25 20:47:26 christos Exp $ */ 2 1.1 kardel 3 1.1 kardel /* 4 1.1 kardel * ntpdc_ops.c - subroutines which are called to perform operations by 5 1.1 kardel * ntpdc 6 1.1 kardel */ 7 1.1 kardel 8 1.1 kardel #ifdef HAVE_CONFIG_H 9 1.1 kardel # include <config.h> 10 1.1 kardel #endif 11 1.1 kardel 12 1.1 kardel #include <stdio.h> 13 1.1 kardel #include <stddef.h> 14 1.1 kardel 15 1.1 kardel #include "ntpdc.h" 16 1.1 kardel #include "ntp_net.h" 17 1.1 kardel #include "ntp_control.h" 18 1.1 kardel #include "ntp_refclock.h" 19 1.1 kardel #include "ntp_stdlib.h" 20 1.1 kardel 21 1.1 kardel #include <ctype.h> 22 1.1 kardel #ifdef HAVE_SYS_TIMEX_H 23 1.1 kardel # include <sys/timex.h> 24 1.1 kardel #endif 25 1.1 kardel #if !defined(__bsdi__) && !defined(apollo) 26 1.1 kardel #ifdef HAVE_NETINET_IN_H 27 1.1 kardel #include <netinet/in.h> 28 1.1 kardel #endif 29 1.1 kardel #endif 30 1.1 kardel 31 1.1 kardel #include <arpa/inet.h> 32 1.1 kardel 33 1.1 kardel /* 34 1.1 kardel * utility functions 35 1.1 kardel */ 36 1.8 christos static int checkitems (size_t, FILE *); 37 1.8 christos static int checkitemsize (size_t, size_t); 38 1.8 christos static int check1item (size_t, FILE *); 39 1.1 kardel 40 1.1 kardel /* 41 1.1 kardel * Declarations for command handlers in here 42 1.1 kardel */ 43 1.1 kardel static void peerlist (struct parse *, FILE *); 44 1.1 kardel static void peers (struct parse *, FILE *); 45 1.11 christos static void doconfig (struct parse *pcmd, FILE *fp, int mode, int refc); 46 1.1 kardel static void dmpeers (struct parse *, FILE *); 47 1.1 kardel static void dopeers (struct parse *, FILE *, int); 48 1.1 kardel static void printpeer (struct info_peer *, FILE *); 49 1.1 kardel static void showpeer (struct parse *, FILE *); 50 1.1 kardel static void peerstats (struct parse *, FILE *); 51 1.1 kardel static void loopinfo (struct parse *, FILE *); 52 1.1 kardel static void sysinfo (struct parse *, FILE *); 53 1.1 kardel static void sysstats (struct parse *, FILE *); 54 1.1 kardel static void iostats (struct parse *, FILE *); 55 1.1 kardel static void memstats (struct parse *, FILE *); 56 1.1 kardel static void timerstats (struct parse *, FILE *); 57 1.1 kardel static void addpeer (struct parse *, FILE *); 58 1.1 kardel static void addserver (struct parse *, FILE *); 59 1.1 kardel static void addrefclock (struct parse *, FILE *); 60 1.1 kardel static void broadcast (struct parse *, FILE *); 61 1.1 kardel static void doconfig (struct parse *, FILE *, int, int); 62 1.1 kardel static void unconfig (struct parse *, FILE *); 63 1.1 kardel static void set (struct parse *, FILE *); 64 1.1 kardel static void sys_clear (struct parse *, FILE *); 65 1.1 kardel static void doset (struct parse *, FILE *, int); 66 1.1 kardel static void reslist (struct parse *, FILE *); 67 1.1 kardel static void new_restrict (struct parse *, FILE *); 68 1.1 kardel static void unrestrict (struct parse *, FILE *); 69 1.1 kardel static void delrestrict (struct parse *, FILE *); 70 1.1 kardel static void do_restrict (struct parse *, FILE *, int); 71 1.1 kardel static void monlist (struct parse *, FILE *); 72 1.1 kardel static void reset (struct parse *, FILE *); 73 1.1 kardel static void preset (struct parse *, FILE *); 74 1.1 kardel static void readkeys (struct parse *, FILE *); 75 1.1 kardel static void trustkey (struct parse *, FILE *); 76 1.1 kardel static void untrustkey (struct parse *, FILE *); 77 1.1 kardel static void do_trustkey (struct parse *, FILE *, int); 78 1.1 kardel static void authinfo (struct parse *, FILE *); 79 1.1 kardel static void traps (struct parse *, FILE *); 80 1.1 kardel static void addtrap (struct parse *, FILE *); 81 1.1 kardel static void clrtrap (struct parse *, FILE *); 82 1.1 kardel static void do_addclr_trap (struct parse *, FILE *, int); 83 1.1 kardel static void requestkey (struct parse *, FILE *); 84 1.1 kardel static void controlkey (struct parse *, FILE *); 85 1.1 kardel static void do_changekey (struct parse *, FILE *, int); 86 1.1 kardel static void ctlstats (struct parse *, FILE *); 87 1.1 kardel static void clockstat (struct parse *, FILE *); 88 1.1 kardel static void fudge (struct parse *, FILE *); 89 1.1 kardel static void clkbug (struct parse *, FILE *); 90 1.1 kardel static void kerninfo (struct parse *, FILE *); 91 1.4 christos static void get_if_stats (struct parse *, FILE *); 92 1.4 christos static void do_if_reload (struct parse *, FILE *); 93 1.1 kardel 94 1.1 kardel /* 95 1.1 kardel * Commands we understand. Ntpdc imports this. 96 1.1 kardel */ 97 1.1 kardel struct xcmd opcmds[] = { 98 1.1 kardel { "listpeers", peerlist, { OPT|IP_VERSION, NO, NO, NO }, 99 1.1 kardel { "-4|-6", "", "", "" }, 100 1.1 kardel "display list of peers the server knows about [IP Version]" }, 101 1.1 kardel { "peers", peers, { OPT|IP_VERSION, NO, NO, NO }, 102 1.1 kardel { "-4|-6", "", "", "" }, 103 1.1 kardel "display peer summary information [IP Version]" }, 104 1.1 kardel { "dmpeers", dmpeers, { OPT|IP_VERSION, NO, NO, NO }, 105 1.1 kardel { "-4|-6", "", "", "" }, 106 1.1 kardel "display peer summary info the way Dave Mills likes it (IP Version)" }, 107 1.1 kardel { "showpeer", showpeer, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD}, 108 1.1 kardel { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 109 1.1 kardel "display detailed information for one or more peers" }, 110 1.1 kardel { "pstats", peerstats, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 111 1.1 kardel { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 112 1.1 kardel "display statistical information for one or more peers" }, 113 1.1 kardel { "loopinfo", loopinfo, { OPT|NTP_STR, NO, NO, NO }, 114 1.1 kardel { "oneline|multiline", "", "", "" }, 115 1.1 kardel "display loop filter information" }, 116 1.1 kardel { "sysinfo", sysinfo, { NO, NO, NO, NO }, 117 1.1 kardel { "", "", "", "" }, 118 1.1 kardel "display local server information" }, 119 1.1 kardel { "sysstats", sysstats, { NO, NO, NO, NO }, 120 1.1 kardel { "", "", "", "" }, 121 1.1 kardel "display local server statistics" }, 122 1.1 kardel { "memstats", memstats, { NO, NO, NO, NO }, 123 1.1 kardel { "", "", "", "" }, 124 1.1 kardel "display peer memory usage statistics" }, 125 1.1 kardel { "iostats", iostats, { NO, NO, NO, NO }, 126 1.1 kardel { "", "", "", "" }, 127 1.1 kardel "display I/O subsystem statistics" }, 128 1.1 kardel { "timerstats", timerstats, { NO, NO, NO, NO }, 129 1.1 kardel { "", "", "", "" }, 130 1.1 kardel "display event timer subsystem statistics" }, 131 1.1 kardel { "addpeer", addpeer, { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 132 1.1 kardel { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." }, 133 1.1 kardel "configure a new peer association" }, 134 1.1 kardel { "addserver", addserver, { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 135 1.1 kardel { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." }, 136 1.1 kardel "configure a new server" }, 137 1.1 kardel { "addrefclock",addrefclock, { NTP_ADD, OPT|NTP_UINT, OPT|NTP_STR, OPT|NTP_STR }, 138 1.1 kardel { "addr", "mode", "minpoll|prefer", "minpoll|prefer" }, 139 1.1 kardel "configure a new server" }, 140 1.1 kardel { "broadcast", broadcast, { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 141 1.1 kardel { "addr", "keyid", "version", "minpoll" }, 142 1.1 kardel "configure broadcasting time service" }, 143 1.1 kardel { "unconfig", unconfig, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 144 1.1 kardel { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 145 1.1 kardel "unconfigure existing peer assocations" }, 146 1.1 kardel { "enable", set, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 147 1.1 kardel { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." }, 148 1.1 kardel "set a system flag (auth, bclient, monitor, pll, kernel, stats)" }, 149 1.4 christos { "disable", sys_clear, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 150 1.1 kardel { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." }, 151 1.1 kardel "clear a system flag (auth, bclient, monitor, pll, kernel, stats)" }, 152 1.1 kardel { "reslist", reslist, {OPT|IP_VERSION, NO, NO, NO }, 153 1.1 kardel { "-4|-6", "", "", "" }, 154 1.1 kardel "display the server's restrict list" }, 155 1.1 kardel { "restrict", new_restrict, { NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR }, 156 1.1 kardel { "address", "mask", 157 1.1 kardel "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod", 158 1.1 kardel "..." }, 159 1.1 kardel "create restrict entry/add flags to entry" }, 160 1.1 kardel { "unrestrict", unrestrict, { NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR }, 161 1.1 kardel { "address", "mask", 162 1.1 kardel "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod", 163 1.1 kardel "..." }, 164 1.1 kardel "remove flags from a restrict entry" }, 165 1.1 kardel { "delrestrict", delrestrict, { NTP_ADD, NTP_ADD, OPT|NTP_STR, NO }, 166 1.1 kardel { "address", "mask", "ntpport", "" }, 167 1.1 kardel "delete a restrict entry" }, 168 1.1 kardel { "monlist", monlist, { OPT|NTP_INT, NO, NO, NO }, 169 1.1 kardel { "version", "", "", "" }, 170 1.1 kardel "display data the server's monitor routines have collected" }, 171 1.1 kardel { "reset", reset, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR }, 172 1.4 christos { "io|sys|mem|timer|auth|ctl|allpeers", "...", "...", "..." }, 173 1.1 kardel "reset various subsystem statistics counters" }, 174 1.1 kardel { "preset", preset, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 175 1.1 kardel { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" }, 176 1.1 kardel "reset stat counters associated with particular peer(s)" }, 177 1.1 kardel { "readkeys", readkeys, { NO, NO, NO, NO }, 178 1.1 kardel { "", "", "", "" }, 179 1.1 kardel "request a reread of the keys file and re-init of system keys" }, 180 1.1 kardel { "trustedkey", trustkey, { NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT }, 181 1.1 kardel { "keyid", "keyid", "keyid", "keyid" }, 182 1.1 kardel "add one or more key ID's to the trusted list" }, 183 1.1 kardel { "untrustedkey", untrustkey, { NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT }, 184 1.1 kardel { "keyid", "keyid", "keyid", "keyid" }, 185 1.1 kardel "remove one or more key ID's from the trusted list" }, 186 1.1 kardel { "authinfo", authinfo, { NO, NO, NO, NO }, 187 1.1 kardel { "", "", "", "" }, 188 1.1 kardel "display the state of the authentication code" }, 189 1.1 kardel { "traps", traps, { NO, NO, NO, NO }, 190 1.1 kardel { "", "", "", "" }, 191 1.1 kardel "display the traps set in the server" }, 192 1.1 kardel { "addtrap", addtrap, { NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO }, 193 1.1 kardel { "address", "port", "interface", "" }, 194 1.1 kardel "configure a trap in the server" }, 195 1.1 kardel { "clrtrap", clrtrap, { NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO }, 196 1.1 kardel { "address", "port", "interface", "" }, 197 1.1 kardel "remove a trap (configured or otherwise) from the server" }, 198 1.1 kardel { "requestkey", requestkey, { NTP_UINT, NO, NO, NO }, 199 1.1 kardel { "keyid", "", "", "" }, 200 1.1 kardel "change the keyid the server uses to authenticate requests" }, 201 1.1 kardel { "controlkey", controlkey, { NTP_UINT, NO, NO, NO }, 202 1.1 kardel { "keyid", "", "", "" }, 203 1.1 kardel "change the keyid the server uses to authenticate control messages" }, 204 1.1 kardel { "ctlstats", ctlstats, { NO, NO, NO, NO }, 205 1.1 kardel { "", "", "", "" }, 206 1.1 kardel "display packet count statistics from the control module" }, 207 1.1 kardel { "clockstat", clockstat, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 208 1.1 kardel { "address", "address", "address", "address" }, 209 1.1 kardel "display clock status information" }, 210 1.1 kardel { "fudge", fudge, { NTP_ADD, NTP_STR, NTP_STR, NO }, 211 1.1 kardel { "address", "time1|time2|val1|val2|flags", "value", "" }, 212 1.1 kardel "set/change one of a clock's fudge factors" }, 213 1.1 kardel { "clkbug", clkbug, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD }, 214 1.1 kardel { "address", "address", "address", "address" }, 215 1.1 kardel "display clock debugging information" }, 216 1.1 kardel { "kerninfo", kerninfo, { NO, NO, NO, NO }, 217 1.1 kardel { "", "", "", "" }, 218 1.1 kardel "display the kernel pll/pps variables" }, 219 1.1 kardel { "ifstats", get_if_stats, { NO, NO, NO, NO }, 220 1.1 kardel { "", "", "", "" }, 221 1.1 kardel "list interface statistics" }, 222 1.1 kardel { "ifreload", do_if_reload, { NO, NO, NO, NO }, 223 1.1 kardel { "", "", "", "" }, 224 1.1 kardel "reload interface configuration" }, 225 1.1 kardel { 0, 0, { NO, NO, NO, NO }, 226 1.1 kardel { "", "", "", "" }, "" } 227 1.1 kardel }; 228 1.1 kardel 229 1.1 kardel /* 230 1.1 kardel * For quick string comparisons 231 1.1 kardel */ 232 1.1 kardel #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) 233 1.1 kardel 234 1.1 kardel /* 235 1.1 kardel * SET_SS_LEN_IF_PRESENT - used by SET_ADDR, SET_ADDRS macros 236 1.1 kardel */ 237 1.1 kardel 238 1.1 kardel #ifdef ISC_PLATFORM_HAVESALEN 239 1.1 kardel #define SET_SS_LEN_IF_PRESENT(psau) \ 240 1.1 kardel do { \ 241 1.3 kardel (psau)->sa.sa_len = SOCKLEN(psau); \ 242 1.1 kardel } while (0) 243 1.1 kardel #else 244 1.1 kardel #define SET_SS_LEN_IF_PRESENT(psau) do { } while (0) 245 1.1 kardel #endif 246 1.1 kardel 247 1.1 kardel /* 248 1.1 kardel * SET_ADDR - setup address for v4/v6 as needed 249 1.1 kardel */ 250 1.1 kardel #define SET_ADDR(address, v6flag, v4addr, v6addr) \ 251 1.1 kardel do { \ 252 1.4 christos ZERO(address); \ 253 1.1 kardel if (v6flag) { \ 254 1.1 kardel AF(&(address)) = AF_INET6; \ 255 1.1 kardel SOCK_ADDR6(&(address)) = (v6addr); \ 256 1.1 kardel } else { \ 257 1.1 kardel AF(&(address)) = AF_INET; \ 258 1.1 kardel NSRCADR(&(address)) = (v4addr); \ 259 1.1 kardel } \ 260 1.1 kardel SET_SS_LEN_IF_PRESENT(&(address)); \ 261 1.1 kardel } while (0) 262 1.1 kardel 263 1.1 kardel 264 1.1 kardel /* 265 1.11 christos * SET_ADDRS - setup source and destination addresses for 266 1.1 kardel * v4/v6 as needed 267 1.1 kardel */ 268 1.1 kardel #define SET_ADDRS(a1, a2, info, a1prefix, a2prefix) \ 269 1.1 kardel do { \ 270 1.4 christos ZERO(a1); \ 271 1.4 christos ZERO(a2); \ 272 1.1 kardel if ((info)->v6_flag) { \ 273 1.1 kardel AF(&(a1)) = AF_INET6; \ 274 1.1 kardel AF(&(a2)) = AF_INET6; \ 275 1.1 kardel SOCK_ADDR6(&(a1)) = (info)->a1prefix##6; \ 276 1.1 kardel SOCK_ADDR6(&(a2)) = (info)->a2prefix##6; \ 277 1.1 kardel } else { \ 278 1.1 kardel AF(&(a1)) = AF_INET; \ 279 1.1 kardel AF(&(a2)) = AF_INET; \ 280 1.1 kardel NSRCADR(&(a1)) = (info)->a1prefix; \ 281 1.1 kardel NSRCADR(&(a2)) = (info)->a2prefix; \ 282 1.1 kardel } \ 283 1.1 kardel SET_SS_LEN_IF_PRESENT(&(a1)); \ 284 1.1 kardel SET_SS_LEN_IF_PRESENT(&(a2)); \ 285 1.1 kardel } while (0) 286 1.1 kardel 287 1.1 kardel 288 1.1 kardel /* 289 1.1 kardel * checkitems - utility to print a message if no items were returned 290 1.1 kardel */ 291 1.1 kardel static int 292 1.1 kardel checkitems( 293 1.8 christos size_t items, 294 1.1 kardel FILE *fp 295 1.1 kardel ) 296 1.1 kardel { 297 1.1 kardel if (items == 0) { 298 1.1 kardel (void) fprintf(fp, "No data returned in response to query\n"); 299 1.1 kardel return 0; 300 1.1 kardel } 301 1.1 kardel return 1; 302 1.1 kardel } 303 1.1 kardel 304 1.1 kardel 305 1.1 kardel /* 306 1.1 kardel * checkitemsize - utility to print a message if the item size is wrong 307 1.1 kardel */ 308 1.1 kardel static int 309 1.1 kardel checkitemsize( 310 1.8 christos size_t itemsize, 311 1.8 christos size_t expected 312 1.1 kardel ) 313 1.1 kardel { 314 1.1 kardel if (itemsize != expected) { 315 1.1 kardel (void) fprintf(stderr, 316 1.8 christos "***Incorrect item size returned by remote host (%lu should be %lu)\n", 317 1.8 christos (u_long)itemsize, (u_long)expected); 318 1.1 kardel return 0; 319 1.1 kardel } 320 1.1 kardel return 1; 321 1.1 kardel } 322 1.1 kardel 323 1.1 kardel 324 1.1 kardel /* 325 1.1 kardel * check1item - check to make sure we have exactly one item 326 1.1 kardel */ 327 1.1 kardel static int 328 1.1 kardel check1item( 329 1.8 christos size_t items, 330 1.1 kardel FILE *fp 331 1.1 kardel ) 332 1.1 kardel { 333 1.1 kardel if (items == 0) { 334 1.1 kardel (void) fprintf(fp, "No data returned in response to query\n"); 335 1.1 kardel return 0; 336 1.1 kardel } 337 1.1 kardel if (items > 1) { 338 1.8 christos (void) fprintf(fp, "Expected one item in response, got %lu\n", 339 1.8 christos (u_long)items); 340 1.1 kardel return 0; 341 1.1 kardel } 342 1.1 kardel return 1; 343 1.1 kardel } 344 1.1 kardel 345 1.1 kardel 346 1.1 kardel /* 347 1.1 kardel * peerlist - get a short list of peers 348 1.1 kardel */ 349 1.1 kardel /*ARGSUSED*/ 350 1.1 kardel static void 351 1.1 kardel peerlist( 352 1.1 kardel struct parse *pcmd, 353 1.1 kardel FILE *fp 354 1.1 kardel ) 355 1.1 kardel { 356 1.1 kardel struct info_peer_list *plist; 357 1.1 kardel sockaddr_u paddr; 358 1.8 christos size_t items; 359 1.8 christos size_t itemsize; 360 1.1 kardel int res; 361 1.1 kardel 362 1.1 kardel again: 363 1.1 kardel res = doquery(impl_ver, REQ_PEER_LIST, 0, 0, 0, (char *)NULL, &items, 364 1.11 christos &itemsize, (void *)&plist, 0, 365 1.1 kardel sizeof(struct info_peer_list)); 366 1.11 christos 367 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 368 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 369 1.1 kardel goto again; 370 1.1 kardel } 371 1.1 kardel 372 1.1 kardel if (res != 0) 373 1.1 kardel return; 374 1.1 kardel 375 1.1 kardel if (!checkitems(items, fp)) 376 1.1 kardel return; 377 1.1 kardel 378 1.1 kardel if (!checkitemsize(itemsize, sizeof(struct info_peer_list)) && 379 1.1 kardel !checkitemsize(itemsize, v4sizeof(struct info_peer_list))) 380 1.1 kardel return; 381 1.1 kardel 382 1.1 kardel while (items > 0) { 383 1.1 kardel SET_ADDR(paddr, plist->v6_flag, plist->addr, plist->addr6); 384 1.1 kardel if ((pcmd->nargs == 0) || 385 1.1 kardel ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) || 386 1.1 kardel ((pcmd->argval->ival == 4) && (plist->v6_flag == 0))) 387 1.11 christos { 388 1.11 christos const char *strhost = nntohost(&paddr); 389 1.11 christos const char *straddr = stoa(&paddr); 390 1.11 christos (void) fprintf(fp, "%-12s %s", 391 1.11 christos modetoa(plist->hmode), strhost); 392 1.11 christos if (strcmp(strhost,straddr)) 393 1.11 christos (void) fprintf(fp, " (%s)\n", straddr); 394 1.11 christos else 395 1.11 christos (void) fprintf(fp, "\n"); 396 1.11 christos } 397 1.1 kardel plist++; 398 1.1 kardel items--; 399 1.1 kardel } 400 1.1 kardel } 401 1.1 kardel 402 1.1 kardel 403 1.1 kardel /* 404 1.1 kardel * peers - show peer summary 405 1.1 kardel */ 406 1.1 kardel static void 407 1.1 kardel peers( 408 1.1 kardel struct parse *pcmd, 409 1.1 kardel FILE *fp 410 1.1 kardel ) 411 1.1 kardel { 412 1.1 kardel dopeers(pcmd, fp, 0); 413 1.1 kardel } 414 1.1 kardel 415 1.1 kardel /* 416 1.1 kardel * dmpeers - show peer summary, Dave Mills style 417 1.1 kardel */ 418 1.1 kardel static void 419 1.1 kardel dmpeers( 420 1.1 kardel struct parse *pcmd, 421 1.1 kardel FILE *fp 422 1.1 kardel ) 423 1.1 kardel { 424 1.1 kardel dopeers(pcmd, fp, 1); 425 1.1 kardel } 426 1.1 kardel 427 1.1 kardel 428 1.1 kardel /* 429 1.1 kardel * peers - show peer summary 430 1.1 kardel */ 431 1.1 kardel /*ARGSUSED*/ 432 1.1 kardel static void 433 1.1 kardel dopeers( 434 1.1 kardel struct parse *pcmd, 435 1.1 kardel FILE *fp, 436 1.1 kardel int dmstyle 437 1.1 kardel ) 438 1.1 kardel { 439 1.1 kardel struct info_peer_summary *plist; 440 1.1 kardel sockaddr_u dstadr; 441 1.1 kardel sockaddr_u srcadr; 442 1.8 christos size_t items; 443 1.8 christos size_t itemsize; 444 1.1 kardel int ntp_poll; 445 1.1 kardel int res; 446 1.1 kardel int c; 447 1.1 kardel l_fp tempts; 448 1.1 kardel 449 1.1 kardel again: 450 1.1 kardel res = doquery(impl_ver, REQ_PEER_LIST_SUM, 0, 0, 0, (char *)NULL, 451 1.11 christos &items, &itemsize, (void *)&plist, 0, 452 1.1 kardel sizeof(struct info_peer_summary)); 453 1.11 christos 454 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 455 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 456 1.1 kardel goto again; 457 1.1 kardel } 458 1.1 kardel 459 1.1 kardel if (res != 0) 460 1.1 kardel return; 461 1.1 kardel 462 1.1 kardel if (!checkitems(items, fp)) 463 1.1 kardel return; 464 1.1 kardel 465 1.1 kardel if (!checkitemsize(itemsize, sizeof(struct info_peer_summary)) && 466 1.1 kardel !checkitemsize(itemsize, v4sizeof(struct info_peer_summary))) 467 1.1 kardel return; 468 1.1 kardel 469 1.1 kardel (void) fprintf(fp, 470 1.1 kardel " remote local st poll reach delay offset disp\n"); 471 1.1 kardel (void) fprintf(fp, 472 1.1 kardel "=======================================================================\n"); 473 1.1 kardel while (items > 0) { 474 1.1 kardel if (!dmstyle) { 475 1.1 kardel if (plist->flags & INFO_FLAG_SYSPEER) 476 1.1 kardel c = '*'; 477 1.1 kardel else if (plist->hmode == MODE_ACTIVE) 478 1.1 kardel c = '+'; 479 1.1 kardel else if (plist->hmode == MODE_PASSIVE) 480 1.1 kardel c = '-'; 481 1.1 kardel else if (plist->hmode == MODE_CLIENT) 482 1.1 kardel c = '='; 483 1.1 kardel else if (plist->hmode == MODE_BROADCAST) 484 1.1 kardel c = '^'; 485 1.1 kardel else if (plist->hmode == MODE_BCLIENT) 486 1.1 kardel c = '~'; 487 1.1 kardel else 488 1.1 kardel c = ' '; 489 1.1 kardel } else { 490 1.1 kardel if (plist->flags & INFO_FLAG_SYSPEER) 491 1.1 kardel c = '*'; 492 1.1 kardel else if (plist->flags & INFO_FLAG_SHORTLIST) 493 1.1 kardel c = '+'; 494 1.1 kardel else if (plist->flags & INFO_FLAG_SEL_CANDIDATE) 495 1.1 kardel c = '.'; 496 1.1 kardel else 497 1.1 kardel c = ' '; 498 1.1 kardel } 499 1.1 kardel NTOHL_FP(&(plist->offset), &tempts); 500 1.1 kardel ntp_poll = 1<<max(min3(plist->ppoll, plist->hpoll, NTP_MAXPOLL), 501 1.1 kardel NTP_MINPOLL); 502 1.1 kardel SET_ADDRS(dstadr, srcadr, plist, dstadr, srcadr); 503 1.1 kardel if ((pcmd->nargs == 0) || 504 1.1 kardel ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) || 505 1.1 kardel ((pcmd->argval->ival == 4) && (plist->v6_flag == 0))) 506 1.1 kardel (void) fprintf(fp, 507 1.3 kardel "%c%-15.15s %-15.15s %2u %4d %3o %7.7s %9.9s %7.7s\n", 508 1.1 kardel c, nntohost(&srcadr), stoa(&dstadr), 509 1.1 kardel plist->stratum, ntp_poll, plist->reach, 510 1.1 kardel fptoa(NTOHS_FP(plist->delay), 5), 511 1.1 kardel lfptoa(&tempts, 6), 512 1.1 kardel ufptoa(NTOHS_FP(plist->dispersion), 5)); 513 1.1 kardel plist++; 514 1.1 kardel items--; 515 1.1 kardel } 516 1.1 kardel } 517 1.1 kardel 518 1.1 kardel /* Convert a refid & stratum (in host order) to a string */ 519 1.4 christos static char * 520 1.1 kardel refid_string( 521 1.1 kardel u_int32 refid, 522 1.1 kardel int stratum 523 1.1 kardel ) 524 1.1 kardel { 525 1.1 kardel if (stratum <= 1) { 526 1.1 kardel static char junk[5]; 527 1.1 kardel junk[4] = 0; 528 1.4 christos memcpy(junk, &refid, 4); 529 1.1 kardel return junk; 530 1.1 kardel } 531 1.1 kardel 532 1.1 kardel return numtoa(refid); 533 1.1 kardel } 534 1.1 kardel 535 1.1 kardel static void 536 1.1 kardel print_pflag( 537 1.4 christos FILE * fp, 538 1.4 christos u_int32 flags 539 1.4 christos ) 540 1.1 kardel { 541 1.4 christos static const char none[] = ""; 542 1.4 christos static const char comma[] = ","; 543 1.4 christos const char *dlim; 544 1.1 kardel 545 1.4 christos if (0 == flags) { 546 1.4 christos fprintf(fp, " none\n"); 547 1.4 christos return; 548 1.4 christos } 549 1.4 christos dlim = none; 550 1.4 christos if (flags & INFO_FLAG_SYSPEER) { 551 1.4 christos fprintf(fp, " system_peer"); 552 1.4 christos dlim = comma; 553 1.4 christos } 554 1.4 christos if (flags & INFO_FLAG_CONFIG) { 555 1.4 christos fprintf(fp, "%s config", dlim); 556 1.4 christos dlim = comma; 557 1.4 christos } 558 1.4 christos if (flags & INFO_FLAG_REFCLOCK) { 559 1.4 christos fprintf(fp, "%s refclock", dlim); 560 1.4 christos dlim = comma; 561 1.4 christos } 562 1.4 christos if (flags & INFO_FLAG_AUTHENABLE) { 563 1.4 christos fprintf(fp, "%s auth", dlim); 564 1.4 christos dlim = comma; 565 1.4 christos } 566 1.4 christos if (flags & INFO_FLAG_PREFER) { 567 1.4 christos fprintf(fp, "%s prefer", dlim); 568 1.4 christos dlim = comma; 569 1.4 christos } 570 1.4 christos if (flags & INFO_FLAG_IBURST) { 571 1.4 christos fprintf(fp, "%s iburst", dlim); 572 1.4 christos dlim = comma; 573 1.4 christos } 574 1.4 christos if (flags & INFO_FLAG_BURST) { 575 1.4 christos fprintf(fp, "%s burst", dlim); 576 1.4 christos dlim = comma; 577 1.4 christos } 578 1.4 christos if (flags & INFO_FLAG_SEL_CANDIDATE) { 579 1.4 christos fprintf(fp, "%s candidate", dlim); 580 1.4 christos dlim = comma; 581 1.4 christos } 582 1.4 christos if (flags & INFO_FLAG_SHORTLIST) { 583 1.4 christos fprintf(fp, "%s shortlist", dlim); 584 1.4 christos dlim = comma; 585 1.1 kardel } 586 1.4 christos fprintf(fp, "\n"); 587 1.1 kardel } 588 1.1 kardel /* 589 1.1 kardel * printpeer - print detail information for a peer 590 1.1 kardel */ 591 1.1 kardel static void 592 1.1 kardel printpeer( 593 1.1 kardel register struct info_peer *pp, 594 1.1 kardel FILE *fp 595 1.1 kardel ) 596 1.1 kardel { 597 1.1 kardel register int i; 598 1.1 kardel l_fp tempts; 599 1.1 kardel sockaddr_u srcadr, dstadr; 600 1.11 christos 601 1.1 kardel SET_ADDRS(dstadr, srcadr, pp, dstadr, srcadr); 602 1.11 christos 603 1.1 kardel (void) fprintf(fp, "remote %s, local %s\n", 604 1.1 kardel stoa(&srcadr), stoa(&dstadr)); 605 1.1 kardel (void) fprintf(fp, "hmode %s, pmode %s, stratum %d, precision %d\n", 606 1.1 kardel modetoa(pp->hmode), modetoa(pp->pmode), 607 1.1 kardel pp->stratum, pp->precision); 608 1.11 christos 609 1.1 kardel (void) fprintf(fp, 610 1.1 kardel "leap %c%c, refid [%s], rootdistance %s, rootdispersion %s\n", 611 1.1 kardel pp->leap & 0x2 ? '1' : '0', 612 1.1 kardel pp->leap & 0x1 ? '1' : '0', 613 1.11 christos refid_string(pp->refid, 614 1.11 christos (pp->flags & INFO_FLAG_REFCLOCK ? 0 : pp->stratum)), 615 1.11 christos fptoa(NTOHS_FP(pp->rootdelay), 5), 616 1.1 kardel ufptoa(NTOHS_FP(pp->rootdispersion), 5)); 617 1.11 christos 618 1.1 kardel (void) fprintf(fp, 619 1.1 kardel "ppoll %d, hpoll %d, keyid %lu, version %d, association %u\n", 620 1.1 kardel pp->ppoll, pp->hpoll, (u_long)pp->keyid, pp->version, ntohs(pp->associd)); 621 1.1 kardel 622 1.1 kardel (void) fprintf(fp, 623 1.1 kardel "reach %03o, unreach %d, flash 0x%04x, ", 624 1.1 kardel pp->reach, pp->unreach, pp->flash2); 625 1.1 kardel 626 1.1 kardel (void) fprintf(fp, "boffset %s, ttl/mode %d\n", 627 1.1 kardel fptoa(NTOHS_FP(pp->estbdelay), 5), pp->ttl); 628 1.11 christos 629 1.1 kardel (void) fprintf(fp, "timer %lds, flags", (long)ntohl(pp->timer)); 630 1.11 christos print_pflag(fp, pp->flags); 631 1.1 kardel 632 1.1 kardel NTOHL_FP(&pp->reftime, &tempts); 633 1.1 kardel (void) fprintf(fp, "reference time: %s\n", 634 1.1 kardel prettydate(&tempts)); 635 1.1 kardel NTOHL_FP(&pp->org, &tempts); 636 1.1 kardel (void) fprintf(fp, "originate timestamp: %s\n", 637 1.1 kardel prettydate(&tempts)); 638 1.1 kardel NTOHL_FP(&pp->rec, &tempts); 639 1.1 kardel (void) fprintf(fp, "receive timestamp: %s\n", 640 1.1 kardel prettydate(&tempts)); 641 1.1 kardel NTOHL_FP(&pp->xmt, &tempts); 642 1.1 kardel (void) fprintf(fp, "transmit timestamp: %s\n", 643 1.1 kardel prettydate(&tempts)); 644 1.11 christos 645 1.1 kardel (void) fprintf(fp, "filter delay: "); 646 1.1 kardel for (i = 0; i < NTP_SHIFT; i++) { 647 1.1 kardel (void) fprintf(fp, " %-8.8s", 648 1.1 kardel fptoa(NTOHS_FP(pp->filtdelay[i]), 5)); 649 1.1 kardel if (i == (NTP_SHIFT>>1)-1) 650 1.1 kardel (void) fprintf(fp, "\n "); 651 1.1 kardel } 652 1.1 kardel (void) fprintf(fp, "\n"); 653 1.1 kardel 654 1.1 kardel (void) fprintf(fp, "filter offset:"); 655 1.1 kardel for (i = 0; i < NTP_SHIFT; i++) { 656 1.1 kardel NTOHL_FP(&pp->filtoffset[i], &tempts); 657 1.1 kardel (void) fprintf(fp, " %-8.8s", lfptoa(&tempts, 6)); 658 1.1 kardel if (i == (NTP_SHIFT>>1)-1) 659 1.1 kardel (void) fprintf(fp, "\n "); 660 1.1 kardel } 661 1.1 kardel (void) fprintf(fp, "\n"); 662 1.1 kardel 663 1.1 kardel (void) fprintf(fp, "filter order: "); 664 1.1 kardel for (i = 0; i < NTP_SHIFT; i++) { 665 1.1 kardel (void) fprintf(fp, " %-8d", pp->order[i]); 666 1.1 kardel if (i == (NTP_SHIFT>>1)-1) 667 1.1 kardel (void) fprintf(fp, "\n "); 668 1.1 kardel } 669 1.1 kardel (void) fprintf(fp, "\n"); 670 1.11 christos 671 1.1 kardel 672 1.1 kardel NTOHL_FP(&pp->offset, &tempts); 673 1.1 kardel (void) fprintf(fp, 674 1.1 kardel "offset %s, delay %s, error bound %s, filter error %s\n", 675 1.1 kardel lfptoa(&tempts, 6), fptoa(NTOHS_FP(pp->delay), 5), 676 1.1 kardel ufptoa(NTOHS_FP(pp->dispersion), 5), 677 1.1 kardel ufptoa(NTOHS_FP(pp->selectdisp), 5)); 678 1.1 kardel } 679 1.1 kardel 680 1.1 kardel 681 1.1 kardel /* 682 1.1 kardel * showpeer - show detailed information for a peer 683 1.1 kardel */ 684 1.1 kardel static void 685 1.1 kardel showpeer( 686 1.1 kardel struct parse *pcmd, 687 1.1 kardel FILE *fp 688 1.1 kardel ) 689 1.1 kardel { 690 1.1 kardel struct info_peer *pp; 691 1.1 kardel /* 4 is the maximum number of peers which will fit in a packet */ 692 1.1 kardel struct info_peer_list *pl, plist[min(MAXARGS, 4)]; 693 1.8 christos size_t qitemlim; 694 1.8 christos size_t qitems; 695 1.8 christos size_t items; 696 1.8 christos size_t itemsize; 697 1.1 kardel int res; 698 1.1 kardel int sendsize; 699 1.1 kardel 700 1.1 kardel again: 701 1.1 kardel if (impl_ver == IMPL_XNTPD) 702 1.1 kardel sendsize = sizeof(struct info_peer_list); 703 1.1 kardel else 704 1.1 kardel sendsize = v4sizeof(struct info_peer_list); 705 1.1 kardel 706 1.1 kardel qitemlim = min(pcmd->nargs, COUNTOF(plist)); 707 1.1 kardel for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) { 708 1.1 kardel if (IS_IPV4(&pcmd->argval[qitems].netnum)) { 709 1.1 kardel pl->addr = NSRCADR(&pcmd->argval[qitems].netnum); 710 1.1 kardel if (impl_ver == IMPL_XNTPD) 711 1.1 kardel pl->v6_flag = 0; 712 1.1 kardel } else { 713 1.1 kardel if (impl_ver == IMPL_XNTPD_OLD) { 714 1.1 kardel fprintf(stderr, 715 1.1 kardel "***Server doesn't understand IPv6 addresses\n"); 716 1.1 kardel return; 717 1.1 kardel } 718 1.1 kardel pl->addr6 = SOCK_ADDR6(&pcmd->argval[qitems].netnum); 719 1.1 kardel pl->v6_flag = 1; 720 1.1 kardel } 721 1.1 kardel pl->port = (u_short)s_port; 722 1.1 kardel pl->hmode = pl->flags = 0; 723 1.4 christos pl = (void *)((char *)pl + sendsize); 724 1.1 kardel } 725 1.1 kardel 726 1.1 kardel res = doquery(impl_ver, REQ_PEER_INFO, 0, qitems, 727 1.1 kardel sendsize, (char *)plist, &items, 728 1.1 kardel &itemsize, (void *)&pp, 0, sizeof(struct info_peer)); 729 1.11 christos 730 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 731 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 732 1.1 kardel goto again; 733 1.1 kardel } 734 1.1 kardel 735 1.1 kardel if (res != 0) 736 1.4 christos return; 737 1.1 kardel 738 1.1 kardel if (!checkitems(items, fp)) 739 1.4 christos return; 740 1.1 kardel 741 1.1 kardel if (!checkitemsize(itemsize, sizeof(struct info_peer)) && 742 1.1 kardel !checkitemsize(itemsize, v4sizeof(struct info_peer))) 743 1.4 christos return; 744 1.1 kardel 745 1.1 kardel while (items-- > 0) { 746 1.1 kardel printpeer(pp, fp); 747 1.1 kardel if (items > 0) 748 1.4 christos fprintf(fp, "\n"); 749 1.1 kardel pp++; 750 1.1 kardel } 751 1.1 kardel } 752 1.1 kardel 753 1.1 kardel 754 1.1 kardel /* 755 1.1 kardel * peerstats - return statistics for a peer 756 1.1 kardel */ 757 1.1 kardel static void 758 1.1 kardel peerstats( 759 1.1 kardel struct parse *pcmd, 760 1.1 kardel FILE *fp 761 1.1 kardel ) 762 1.1 kardel { 763 1.1 kardel struct info_peer_stats *pp; 764 1.1 kardel /* 4 is the maximum number of peers which will fit in a packet */ 765 1.1 kardel struct info_peer_list *pl, plist[min(MAXARGS, 4)]; 766 1.1 kardel sockaddr_u src, dst; 767 1.8 christos size_t qitemlim; 768 1.8 christos size_t qitems; 769 1.8 christos size_t items; 770 1.8 christos size_t itemsize; 771 1.1 kardel int res; 772 1.8 christos size_t sendsize; 773 1.1 kardel 774 1.1 kardel again: 775 1.1 kardel if (impl_ver == IMPL_XNTPD) 776 1.1 kardel sendsize = sizeof(struct info_peer_list); 777 1.1 kardel else 778 1.1 kardel sendsize = v4sizeof(struct info_peer_list); 779 1.1 kardel 780 1.4 christos ZERO(plist); 781 1.1 kardel 782 1.1 kardel qitemlim = min(pcmd->nargs, COUNTOF(plist)); 783 1.1 kardel for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) { 784 1.1 kardel if (IS_IPV4(&pcmd->argval[qitems].netnum)) { 785 1.1 kardel pl->addr = NSRCADR(&pcmd->argval[qitems].netnum); 786 1.1 kardel if (impl_ver == IMPL_XNTPD) 787 1.1 kardel pl->v6_flag = 0; 788 1.1 kardel } else { 789 1.1 kardel if (impl_ver == IMPL_XNTPD_OLD) { 790 1.1 kardel fprintf(stderr, 791 1.1 kardel "***Server doesn't understand IPv6 addresses\n"); 792 1.1 kardel return; 793 1.1 kardel } 794 1.1 kardel pl->addr6 = SOCK_ADDR6(&pcmd->argval[qitems].netnum); 795 1.1 kardel pl->v6_flag = 1; 796 1.1 kardel } 797 1.1 kardel pl->port = (u_short)s_port; 798 1.1 kardel pl->hmode = plist[qitems].flags = 0; 799 1.4 christos pl = (void *)((char *)pl + sendsize); 800 1.1 kardel } 801 1.1 kardel 802 1.1 kardel res = doquery(impl_ver, REQ_PEER_STATS, 0, qitems, 803 1.1 kardel sendsize, (char *)plist, &items, 804 1.11 christos &itemsize, (void *)&pp, 0, 805 1.1 kardel sizeof(struct info_peer_stats)); 806 1.11 christos 807 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 808 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 809 1.1 kardel goto again; 810 1.1 kardel } 811 1.1 kardel 812 1.1 kardel if (res != 0) 813 1.4 christos return; 814 1.1 kardel 815 1.1 kardel if (!checkitems(items, fp)) 816 1.1 kardel return; 817 1.1 kardel 818 1.1 kardel if (!checkitemsize(itemsize, sizeof(struct info_peer_stats)) && 819 1.1 kardel !checkitemsize(itemsize, v4sizeof(struct info_peer_stats))) 820 1.1 kardel return; 821 1.1 kardel 822 1.1 kardel while (items-- > 0) { 823 1.1 kardel ZERO_SOCK(&dst); 824 1.1 kardel ZERO_SOCK(&src); 825 1.1 kardel if (pp->v6_flag != 0) { 826 1.1 kardel AF(&dst) = AF_INET6; 827 1.1 kardel AF(&src) = AF_INET6; 828 1.1 kardel SOCK_ADDR6(&dst) = pp->dstadr6; 829 1.1 kardel SOCK_ADDR6(&src) = pp->srcadr6; 830 1.1 kardel } else { 831 1.1 kardel AF(&dst) = AF_INET; 832 1.1 kardel AF(&src) = AF_INET; 833 1.1 kardel NSRCADR(&dst) = pp->dstadr; 834 1.1 kardel NSRCADR(&src) = pp->srcadr; 835 1.1 kardel } 836 1.1 kardel #ifdef ISC_PLATFORM_HAVESALEN 837 1.3 kardel src.sa.sa_len = SOCKLEN(&src); 838 1.3 kardel dst.sa.sa_len = SOCKLEN(&dst); 839 1.1 kardel #endif 840 1.3 kardel fprintf(fp, "remote host: %s\n", 841 1.3 kardel nntohost(&src)); 842 1.3 kardel fprintf(fp, "local interface: %s\n", 843 1.3 kardel stoa(&dst)); 844 1.3 kardel fprintf(fp, "time last received: %lus\n", 845 1.3 kardel (u_long)ntohl(pp->timereceived)); 846 1.3 kardel fprintf(fp, "time until next send: %lus\n", 847 1.3 kardel (u_long)ntohl(pp->timetosend)); 848 1.3 kardel fprintf(fp, "reachability change: %lus\n", 849 1.3 kardel (u_long)ntohl(pp->timereachable)); 850 1.3 kardel fprintf(fp, "packets sent: %lu\n", 851 1.3 kardel (u_long)ntohl(pp->sent)); 852 1.3 kardel fprintf(fp, "packets received: %lu\n", 853 1.3 kardel (u_long)ntohl(pp->processed)); 854 1.3 kardel fprintf(fp, "bad authentication: %lu\n", 855 1.3 kardel (u_long)ntohl(pp->badauth)); 856 1.3 kardel fprintf(fp, "bogus origin: %lu\n", 857 1.3 kardel (u_long)ntohl(pp->bogusorg)); 858 1.3 kardel fprintf(fp, "duplicate: %lu\n", 859 1.3 kardel (u_long)ntohl(pp->oldpkt)); 860 1.3 kardel fprintf(fp, "bad dispersion: %lu\n", 861 1.3 kardel (u_long)ntohl(pp->seldisp)); 862 1.3 kardel fprintf(fp, "bad reference time: %lu\n", 863 1.3 kardel (u_long)ntohl(pp->selbroken)); 864 1.3 kardel fprintf(fp, "candidate order: %u\n", 865 1.3 kardel pp->candidate); 866 1.1 kardel if (items > 0) 867 1.3 kardel fprintf(fp, "\n"); 868 1.3 kardel fprintf(fp, "flags: "); 869 1.1 kardel print_pflag(fp, ntohs(pp->flags)); 870 1.3 kardel pp++; 871 1.1 kardel } 872 1.1 kardel } 873 1.1 kardel 874 1.1 kardel 875 1.1 kardel /* 876 1.1 kardel * loopinfo - show loop filter information 877 1.1 kardel */ 878 1.1 kardel static void 879 1.1 kardel loopinfo( 880 1.1 kardel struct parse *pcmd, 881 1.1 kardel FILE *fp 882 1.1 kardel ) 883 1.1 kardel { 884 1.1 kardel struct info_loop *il; 885 1.8 christos size_t items; 886 1.8 christos size_t itemsize; 887 1.1 kardel int oneline = 0; 888 1.1 kardel int res; 889 1.1 kardel l_fp tempts; 890 1.1 kardel 891 1.1 kardel if (pcmd->nargs > 0) { 892 1.1 kardel if (STREQ(pcmd->argval[0].string, "oneline")) 893 1.1 kardel oneline = 1; 894 1.1 kardel else if (STREQ(pcmd->argval[0].string, "multiline")) 895 1.1 kardel oneline = 0; 896 1.1 kardel else { 897 1.1 kardel (void) fprintf(stderr, "How many lines?\n"); 898 1.1 kardel return; 899 1.1 kardel } 900 1.1 kardel } 901 1.1 kardel 902 1.1 kardel again: 903 1.1 kardel res = doquery(impl_ver, REQ_LOOP_INFO, 0, 0, 0, (char *)NULL, 904 1.11 christos &items, &itemsize, (void *)&il, 0, 905 1.1 kardel sizeof(struct info_loop)); 906 1.11 christos 907 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 908 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 909 1.1 kardel goto again; 910 1.1 kardel } 911 1.1 kardel 912 1.1 kardel if (res != 0) 913 1.1 kardel return; 914 1.1 kardel 915 1.1 kardel if (!check1item(items, fp)) 916 1.1 kardel return; 917 1.1 kardel 918 1.1 kardel if (!checkitemsize(itemsize, sizeof(struct info_loop))) 919 1.1 kardel return; 920 1.1 kardel 921 1.1 kardel if (oneline) { 922 1.1 kardel l_fp temp2ts; 923 1.1 kardel 924 1.1 kardel NTOHL_FP(&il->last_offset, &tempts); 925 1.1 kardel NTOHL_FP(&il->drift_comp, &temp2ts); 926 1.1 kardel 927 1.1 kardel (void) fprintf(fp, 928 1.1 kardel "offset %s, frequency %s, time_const %ld, watchdog %ld\n", 929 1.1 kardel lfptoa(&tempts, 6), 930 1.1 kardel lfptoa(&temp2ts, 3), 931 1.1 kardel (long)(int32)ntohl((u_long)il->compliance), 932 1.1 kardel (u_long)ntohl((u_long)il->watchdog_timer)); 933 1.1 kardel } else { 934 1.1 kardel NTOHL_FP(&il->last_offset, &tempts); 935 1.1 kardel (void) fprintf(fp, "offset: %s s\n", 936 1.1 kardel lfptoa(&tempts, 6)); 937 1.1 kardel NTOHL_FP(&il->drift_comp, &tempts); 938 1.1 kardel (void) fprintf(fp, "frequency: %s ppm\n", 939 1.1 kardel lfptoa(&tempts, 3)); 940 1.1 kardel (void) fprintf(fp, "poll adjust: %ld\n", 941 1.1 kardel (long)(int32)ntohl(il->compliance)); 942 1.1 kardel (void) fprintf(fp, "watchdog timer: %ld s\n", 943 1.1 kardel (u_long)ntohl(il->watchdog_timer)); 944 1.1 kardel } 945 1.1 kardel } 946 1.1 kardel 947 1.1 kardel 948 1.1 kardel /* 949 1.1 kardel * sysinfo - show current system state 950 1.1 kardel */ 951 1.1 kardel /*ARGSUSED*/ 952 1.1 kardel static void 953 1.1 kardel sysinfo( 954 1.1 kardel struct parse *pcmd, 955 1.1 kardel FILE *fp 956 1.1 kardel ) 957 1.1 kardel { 958 1.1 kardel struct info_sys *is; 959 1.1 kardel sockaddr_u peeraddr; 960 1.8 christos size_t items; 961 1.8 christos size_t itemsize; 962 1.1 kardel int res; 963 1.1 kardel l_fp tempts; 964 1.1 kardel 965 1.1 kardel again: 966 1.1 kardel res = doquery(impl_ver, REQ_SYS_INFO, 0, 0, 0, (char *)NULL, 967 1.1 kardel &items, &itemsize, (void *)&is, 0, 968 1.1 kardel sizeof(struct info_sys)); 969 1.11 christos 970 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 971 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 972 1.1 kardel goto again; 973 1.1 kardel } 974 1.1 kardel 975 1.1 kardel if (res != 0) 976 1.1 kardel return; 977 1.1 kardel 978 1.1 kardel if (!check1item(items, fp)) 979 1.1 kardel return; 980 1.1 kardel 981 1.1 kardel if (!checkitemsize(itemsize, sizeof(struct info_sys)) && 982 1.1 kardel !checkitemsize(itemsize, v4sizeof(struct info_sys))) 983 1.1 kardel return; 984 1.1 kardel 985 1.1 kardel SET_ADDR(peeraddr, is->v6_flag, is->peer, is->peer6); 986 1.1 kardel 987 1.1 kardel (void) fprintf(fp, "system peer: %s\n", nntohost(&peeraddr)); 988 1.1 kardel (void) fprintf(fp, "system peer mode: %s\n", modetoa(is->peer_mode)); 989 1.1 kardel (void) fprintf(fp, "leap indicator: %c%c\n", 990 1.1 kardel is->leap & 0x2 ? '1' : '0', 991 1.1 kardel is->leap & 0x1 ? '1' : '0'); 992 1.1 kardel (void) fprintf(fp, "stratum: %d\n", (int)is->stratum); 993 1.1 kardel (void) fprintf(fp, "precision: %d\n", (int)is->precision); 994 1.1 kardel (void) fprintf(fp, "root distance: %s s\n", 995 1.1 kardel fptoa(NTOHS_FP(is->rootdelay), 5)); 996 1.1 kardel (void) fprintf(fp, "root dispersion: %s s\n", 997 1.1 kardel ufptoa(NTOHS_FP(is->rootdispersion), 5)); 998 1.1 kardel (void) fprintf(fp, "reference ID: [%s]\n", 999 1.1 kardel refid_string(is->refid, is->stratum)); 1000 1.1 kardel NTOHL_FP(&is->reftime, &tempts); 1001 1.1 kardel (void) fprintf(fp, "reference time: %s\n", prettydate(&tempts)); 1002 1.1 kardel 1003 1.1 kardel (void) fprintf(fp, "system flags: "); 1004 1.1 kardel if ((is->flags & (INFO_FLAG_BCLIENT | INFO_FLAG_AUTHENABLE | 1005 1.1 kardel INFO_FLAG_NTP | INFO_FLAG_KERNEL| INFO_FLAG_CAL | 1006 1.1 kardel INFO_FLAG_PPS_SYNC | INFO_FLAG_MONITOR | INFO_FLAG_FILEGEN)) == 0) { 1007 1.1 kardel (void) fprintf(fp, "none\n"); 1008 1.1 kardel } else { 1009 1.1 kardel if (is->flags & INFO_FLAG_BCLIENT) 1010 1.1 kardel (void) fprintf(fp, "bclient "); 1011 1.1 kardel if (is->flags & INFO_FLAG_AUTHENTICATE) 1012 1.1 kardel (void) fprintf(fp, "auth "); 1013 1.1 kardel if (is->flags & INFO_FLAG_MONITOR) 1014 1.1 kardel (void) fprintf(fp, "monitor "); 1015 1.1 kardel if (is->flags & INFO_FLAG_NTP) 1016 1.1 kardel (void) fprintf(fp, "ntp "); 1017 1.1 kardel if (is->flags & INFO_FLAG_KERNEL) 1018 1.1 kardel (void) fprintf(fp, "kernel "); 1019 1.1 kardel if (is->flags & INFO_FLAG_FILEGEN) 1020 1.1 kardel (void) fprintf(fp, "stats "); 1021 1.1 kardel if (is->flags & INFO_FLAG_CAL) 1022 1.1 kardel (void) fprintf(fp, "calibrate "); 1023 1.1 kardel if (is->flags & INFO_FLAG_PPS_SYNC) 1024 1.1 kardel (void) fprintf(fp, "pps "); 1025 1.1 kardel (void) fprintf(fp, "\n"); 1026 1.1 kardel } 1027 1.1 kardel (void) fprintf(fp, "jitter: %s s\n", 1028 1.1 kardel fptoa(ntohl(is->frequency), 6)); 1029 1.1 kardel (void) fprintf(fp, "stability: %s ppm\n", 1030 1.1 kardel ufptoa(ntohl(is->stability), 3)); 1031 1.1 kardel (void) fprintf(fp, "broadcastdelay: %s s\n", 1032 1.1 kardel fptoa(NTOHS_FP(is->bdelay), 6)); 1033 1.1 kardel NTOHL_FP(&is->authdelay, &tempts); 1034 1.1 kardel (void) fprintf(fp, "authdelay: %s s\n", lfptoa(&tempts, 6)); 1035 1.1 kardel } 1036 1.1 kardel 1037 1.1 kardel 1038 1.1 kardel /* 1039 1.1 kardel * sysstats - print system statistics 1040 1.1 kardel */ 1041 1.1 kardel /*ARGSUSED*/ 1042 1.1 kardel static void 1043 1.1 kardel sysstats( 1044 1.1 kardel struct parse *pcmd, 1045 1.1 kardel FILE *fp 1046 1.1 kardel ) 1047 1.1 kardel { 1048 1.1 kardel struct info_sys_stats *ss; 1049 1.8 christos size_t items; 1050 1.8 christos size_t itemsize; 1051 1.1 kardel int res; 1052 1.1 kardel 1053 1.1 kardel again: 1054 1.1 kardel res = doquery(impl_ver, REQ_SYS_STATS, 0, 0, 0, (char *)NULL, 1055 1.11 christos &items, &itemsize, (void *)&ss, 0, 1056 1.1 kardel sizeof(struct info_sys_stats)); 1057 1.11 christos 1058 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1059 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 1060 1.1 kardel goto again; 1061 1.1 kardel } 1062 1.1 kardel 1063 1.1 kardel if (res != 0) 1064 1.1 kardel return; 1065 1.1 kardel 1066 1.1 kardel if (!check1item(items, fp)) 1067 1.1 kardel return; 1068 1.1 kardel 1069 1.1 kardel if (itemsize != sizeof(struct info_sys_stats) && 1070 1.1 kardel itemsize != sizeof(struct old_info_sys_stats)) { 1071 1.1 kardel /* issue warning according to new structure size */ 1072 1.1 kardel checkitemsize(itemsize, sizeof(struct info_sys_stats)); 1073 1.1 kardel return; 1074 1.1 kardel } 1075 1.3 kardel fprintf(fp, "time since restart: %lu\n", 1076 1.3 kardel (u_long)ntohl(ss->timeup)); 1077 1.3 kardel fprintf(fp, "time since reset: %lu\n", 1078 1.1 kardel (u_long)ntohl(ss->timereset)); 1079 1.3 kardel fprintf(fp, "packets received: %lu\n", 1080 1.1 kardel (u_long)ntohl(ss->received)); 1081 1.3 kardel fprintf(fp, "packets processed: %lu\n", 1082 1.1 kardel (u_long)ntohl(ss->processed)); 1083 1.3 kardel fprintf(fp, "current version: %lu\n", 1084 1.3 kardel (u_long)ntohl(ss->newversionpkt)); 1085 1.3 kardel fprintf(fp, "previous version: %lu\n", 1086 1.3 kardel (u_long)ntohl(ss->oldversionpkt)); 1087 1.3 kardel fprintf(fp, "declined: %lu\n", 1088 1.3 kardel (u_long)ntohl(ss->unknownversion)); 1089 1.3 kardel fprintf(fp, "access denied: %lu\n", 1090 1.1 kardel (u_long)ntohl(ss->denied)); 1091 1.3 kardel fprintf(fp, "bad length or format: %lu\n", 1092 1.3 kardel (u_long)ntohl(ss->badlength)); 1093 1.3 kardel fprintf(fp, "bad authentication: %lu\n", 1094 1.3 kardel (u_long)ntohl(ss->badauth)); 1095 1.1 kardel if (itemsize != sizeof(struct info_sys_stats)) 1096 1.1 kardel return; 1097 1.11 christos 1098 1.3 kardel fprintf(fp, "rate exceeded: %lu\n", 1099 1.1 kardel (u_long)ntohl(ss->limitrejected)); 1100 1.1 kardel } 1101 1.1 kardel 1102 1.1 kardel 1103 1.1 kardel 1104 1.1 kardel /* 1105 1.1 kardel * iostats - print I/O statistics 1106 1.1 kardel */ 1107 1.1 kardel /*ARGSUSED*/ 1108 1.1 kardel static void 1109 1.1 kardel iostats( 1110 1.1 kardel struct parse *pcmd, 1111 1.1 kardel FILE *fp 1112 1.1 kardel ) 1113 1.1 kardel { 1114 1.1 kardel struct info_io_stats *io; 1115 1.8 christos size_t items; 1116 1.8 christos size_t itemsize; 1117 1.1 kardel int res; 1118 1.1 kardel 1119 1.1 kardel again: 1120 1.3 kardel res = doquery(impl_ver, REQ_IO_STATS, 0, 0, 0, NULL, &items, 1121 1.3 kardel &itemsize, (void *)&io, 0, sizeof(*io)); 1122 1.11 christos 1123 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1124 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 1125 1.1 kardel goto again; 1126 1.1 kardel } 1127 1.1 kardel 1128 1.1 kardel if (res != 0) 1129 1.3 kardel return; 1130 1.1 kardel 1131 1.1 kardel if (!check1item(items, fp)) 1132 1.3 kardel return; 1133 1.1 kardel 1134 1.3 kardel if (!checkitemsize(itemsize, sizeof(*io))) 1135 1.3 kardel return; 1136 1.1 kardel 1137 1.3 kardel fprintf(fp, "time since reset: %lu\n", 1138 1.3 kardel (u_long)ntohl(io->timereset)); 1139 1.3 kardel fprintf(fp, "receive buffers: %u\n", 1140 1.3 kardel (u_int)ntohs(io->totalrecvbufs)); 1141 1.3 kardel fprintf(fp, "free receive buffers: %u\n", 1142 1.3 kardel (u_int)ntohs(io->freerecvbufs)); 1143 1.3 kardel fprintf(fp, "used receive buffers: %u\n", 1144 1.3 kardel (u_int)ntohs(io->fullrecvbufs)); 1145 1.3 kardel fprintf(fp, "low water refills: %u\n", 1146 1.3 kardel (u_int)ntohs(io->lowwater)); 1147 1.3 kardel fprintf(fp, "dropped packets: %lu\n", 1148 1.3 kardel (u_long)ntohl(io->dropped)); 1149 1.3 kardel fprintf(fp, "ignored packets: %lu\n", 1150 1.3 kardel (u_long)ntohl(io->ignored)); 1151 1.3 kardel fprintf(fp, "received packets: %lu\n", 1152 1.3 kardel (u_long)ntohl(io->received)); 1153 1.3 kardel fprintf(fp, "packets sent: %lu\n", 1154 1.3 kardel (u_long)ntohl(io->sent)); 1155 1.3 kardel fprintf(fp, "packets not sent: %lu\n", 1156 1.3 kardel (u_long)ntohl(io->notsent)); 1157 1.3 kardel fprintf(fp, "interrupts handled: %lu\n", 1158 1.3 kardel (u_long)ntohl(io->interrupts)); 1159 1.3 kardel fprintf(fp, "received by int: %lu\n", 1160 1.3 kardel (u_long)ntohl(io->int_received)); 1161 1.1 kardel } 1162 1.1 kardel 1163 1.1 kardel 1164 1.1 kardel /* 1165 1.1 kardel * memstats - print peer memory statistics 1166 1.1 kardel */ 1167 1.1 kardel /*ARGSUSED*/ 1168 1.1 kardel static void 1169 1.1 kardel memstats( 1170 1.1 kardel struct parse *pcmd, 1171 1.1 kardel FILE *fp 1172 1.1 kardel ) 1173 1.1 kardel { 1174 1.1 kardel struct info_mem_stats *mem; 1175 1.1 kardel int i; 1176 1.8 christos size_t items; 1177 1.8 christos size_t itemsize; 1178 1.1 kardel int res; 1179 1.1 kardel 1180 1.1 kardel again: 1181 1.3 kardel res = doquery(impl_ver, REQ_MEM_STATS, 0, 0, 0, NULL, &items, 1182 1.3 kardel &itemsize, (void *)&mem, 0, sizeof(*mem)); 1183 1.11 christos 1184 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1185 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 1186 1.1 kardel goto again; 1187 1.1 kardel } 1188 1.1 kardel 1189 1.1 kardel if (res != 0) 1190 1.3 kardel return; 1191 1.1 kardel 1192 1.1 kardel if (!check1item(items, fp)) 1193 1.3 kardel return; 1194 1.1 kardel 1195 1.3 kardel if (!checkitemsize(itemsize, sizeof(*mem))) 1196 1.3 kardel return; 1197 1.1 kardel 1198 1.3 kardel fprintf(fp, "time since reset: %lu\n", 1199 1.3 kardel (u_long)ntohl(mem->timereset)); 1200 1.3 kardel fprintf(fp, "total peer memory: %u\n", 1201 1.3 kardel (u_int)ntohs(mem->totalpeermem)); 1202 1.3 kardel fprintf(fp, "free peer memory: %u\n", 1203 1.3 kardel (u_int)ntohs(mem->freepeermem)); 1204 1.3 kardel fprintf(fp, "calls to findpeer: %lu\n", 1205 1.3 kardel (u_long)ntohl(mem->findpeer_calls)); 1206 1.3 kardel fprintf(fp, "new peer allocations: %lu\n", 1207 1.3 kardel (u_long)ntohl(mem->allocations)); 1208 1.3 kardel fprintf(fp, "peer demobilizations: %lu\n", 1209 1.3 kardel (u_long)ntohl(mem->demobilizations)); 1210 1.1 kardel 1211 1.3 kardel fprintf(fp, "hash table counts: "); 1212 1.1 kardel for (i = 0; i < NTP_HASH_SIZE; i++) { 1213 1.3 kardel fprintf(fp, "%4d", (int)mem->hashcount[i]); 1214 1.3 kardel if ((i % 8) == 7 && i != (NTP_HASH_SIZE-1)) 1215 1.3 kardel fprintf(fp, "\n "); 1216 1.1 kardel } 1217 1.3 kardel fprintf(fp, "\n"); 1218 1.1 kardel } 1219 1.1 kardel 1220 1.1 kardel 1221 1.1 kardel 1222 1.1 kardel /* 1223 1.1 kardel * timerstats - print timer statistics 1224 1.1 kardel */ 1225 1.1 kardel /*ARGSUSED*/ 1226 1.1 kardel static void 1227 1.1 kardel timerstats( 1228 1.1 kardel struct parse *pcmd, 1229 1.1 kardel FILE *fp 1230 1.1 kardel ) 1231 1.1 kardel { 1232 1.1 kardel struct info_timer_stats *tim; 1233 1.8 christos size_t items; 1234 1.8 christos size_t itemsize; 1235 1.1 kardel int res; 1236 1.1 kardel 1237 1.1 kardel again: 1238 1.3 kardel res = doquery(impl_ver, REQ_TIMER_STATS, 0, 0, 0, NULL, &items, 1239 1.3 kardel &itemsize, (void *)&tim, 0, sizeof(*tim)); 1240 1.11 christos 1241 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1242 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 1243 1.1 kardel goto again; 1244 1.1 kardel } 1245 1.1 kardel 1246 1.1 kardel if (res != 0) 1247 1.3 kardel return; 1248 1.1 kardel 1249 1.1 kardel if (!check1item(items, fp)) 1250 1.3 kardel return; 1251 1.1 kardel 1252 1.3 kardel if (!checkitemsize(itemsize, sizeof(*tim))) 1253 1.3 kardel return; 1254 1.1 kardel 1255 1.3 kardel fprintf(fp, "time since reset: %lu\n", 1256 1.3 kardel (u_long)ntohl(tim->timereset)); 1257 1.3 kardel fprintf(fp, "alarms handled: %lu\n", 1258 1.3 kardel (u_long)ntohl(tim->alarms)); 1259 1.3 kardel fprintf(fp, "alarm overruns: %lu\n", 1260 1.3 kardel (u_long)ntohl(tim->overflows)); 1261 1.3 kardel fprintf(fp, "calls to transmit: %lu\n", 1262 1.3 kardel (u_long)ntohl(tim->xmtcalls)); 1263 1.1 kardel } 1264 1.1 kardel 1265 1.1 kardel 1266 1.1 kardel /* 1267 1.1 kardel * addpeer - configure an active mode association 1268 1.1 kardel */ 1269 1.1 kardel static void 1270 1.1 kardel addpeer( 1271 1.1 kardel struct parse *pcmd, 1272 1.1 kardel FILE *fp 1273 1.1 kardel ) 1274 1.1 kardel { 1275 1.1 kardel doconfig(pcmd, fp, MODE_ACTIVE, 0); 1276 1.1 kardel } 1277 1.1 kardel 1278 1.1 kardel 1279 1.1 kardel /* 1280 1.1 kardel * addserver - configure a client mode association 1281 1.1 kardel */ 1282 1.1 kardel static void 1283 1.1 kardel addserver( 1284 1.1 kardel struct parse *pcmd, 1285 1.1 kardel FILE *fp 1286 1.1 kardel ) 1287 1.1 kardel { 1288 1.1 kardel doconfig(pcmd, fp, MODE_CLIENT, 0); 1289 1.1 kardel } 1290 1.1 kardel 1291 1.1 kardel /* 1292 1.1 kardel * addrefclock - configure a reference clock association 1293 1.1 kardel */ 1294 1.1 kardel static void 1295 1.1 kardel addrefclock( 1296 1.1 kardel struct parse *pcmd, 1297 1.1 kardel FILE *fp 1298 1.1 kardel ) 1299 1.1 kardel { 1300 1.1 kardel doconfig(pcmd, fp, MODE_CLIENT, 1); 1301 1.1 kardel } 1302 1.1 kardel 1303 1.1 kardel /* 1304 1.1 kardel * broadcast - configure a broadcast mode association 1305 1.1 kardel */ 1306 1.1 kardel static void 1307 1.1 kardel broadcast( 1308 1.1 kardel struct parse *pcmd, 1309 1.1 kardel FILE *fp 1310 1.1 kardel ) 1311 1.1 kardel { 1312 1.1 kardel doconfig(pcmd, fp, MODE_BROADCAST, 0); 1313 1.1 kardel } 1314 1.1 kardel 1315 1.1 kardel 1316 1.1 kardel /* 1317 1.1 kardel * config - configure a new peer association 1318 1.1 kardel */ 1319 1.1 kardel static void 1320 1.1 kardel doconfig( 1321 1.1 kardel struct parse *pcmd, 1322 1.1 kardel FILE *fp, 1323 1.1 kardel int mode, 1324 1.1 kardel int refc 1325 1.1 kardel ) 1326 1.1 kardel { 1327 1.1 kardel struct conf_peer cpeer; 1328 1.8 christos size_t items; 1329 1.8 christos size_t itemsize; 1330 1.8 christos const char *dummy; 1331 1.1 kardel u_long keyid; 1332 1.1 kardel u_int version; 1333 1.1 kardel u_char minpoll; 1334 1.1 kardel u_char maxpoll; 1335 1.1 kardel u_int flags; 1336 1.1 kardel u_char cmode; 1337 1.1 kardel int res; 1338 1.1 kardel int sendsize; 1339 1.1 kardel int numtyp; 1340 1.3 kardel long val; 1341 1.1 kardel 1342 1.1 kardel again: 1343 1.1 kardel keyid = 0; 1344 1.1 kardel version = 3; 1345 1.1 kardel flags = 0; 1346 1.3 kardel res = FALSE; 1347 1.1 kardel cmode = 0; 1348 1.1 kardel minpoll = NTP_MINDPOLL; 1349 1.1 kardel maxpoll = NTP_MAXDPOLL; 1350 1.1 kardel numtyp = 1; 1351 1.1 kardel if (refc) 1352 1.1 kardel numtyp = 5; 1353 1.1 kardel 1354 1.1 kardel if (impl_ver == IMPL_XNTPD) 1355 1.1 kardel sendsize = sizeof(struct conf_peer); 1356 1.1 kardel else 1357 1.1 kardel sendsize = v4sizeof(struct conf_peer); 1358 1.1 kardel 1359 1.1 kardel items = 1; 1360 1.2 christos while (pcmd->nargs > (size_t)items) { 1361 1.1 kardel if (STREQ(pcmd->argval[items].string, "prefer")) 1362 1.3 kardel flags |= CONF_FLAG_PREFER; 1363 1.1 kardel else if (STREQ(pcmd->argval[items].string, "burst")) 1364 1.3 kardel flags |= CONF_FLAG_BURST; 1365 1.1 kardel else if (STREQ(pcmd->argval[items].string, "iburst")) 1366 1.3 kardel flags |= CONF_FLAG_IBURST; 1367 1.1 kardel else if (!refc && STREQ(pcmd->argval[items].string, "keyid")) 1368 1.3 kardel numtyp = 1; 1369 1.1 kardel else if (!refc && STREQ(pcmd->argval[items].string, "version")) 1370 1.3 kardel numtyp = 2; 1371 1.1 kardel else if (STREQ(pcmd->argval[items].string, "minpoll")) 1372 1.3 kardel numtyp = 3; 1373 1.1 kardel else if (STREQ(pcmd->argval[items].string, "maxpoll")) 1374 1.3 kardel numtyp = 4; 1375 1.1 kardel else { 1376 1.1 kardel if (!atoint(pcmd->argval[items].string, &val)) 1377 1.3 kardel numtyp = 0; 1378 1.1 kardel switch (numtyp) { 1379 1.1 kardel case 1: 1380 1.3 kardel keyid = val; 1381 1.3 kardel numtyp = 2; 1382 1.3 kardel break; 1383 1.3 kardel 1384 1.1 kardel case 2: 1385 1.3 kardel version = (u_int)val; 1386 1.3 kardel numtyp = 0; 1387 1.3 kardel break; 1388 1.1 kardel 1389 1.1 kardel case 3: 1390 1.3 kardel minpoll = (u_char)val; 1391 1.3 kardel numtyp = 0; 1392 1.3 kardel break; 1393 1.1 kardel 1394 1.1 kardel case 4: 1395 1.3 kardel maxpoll = (u_char)val; 1396 1.3 kardel numtyp = 0; 1397 1.3 kardel break; 1398 1.1 kardel 1399 1.1 kardel case 5: 1400 1.3 kardel cmode = (u_char)val; 1401 1.3 kardel numtyp = 0; 1402 1.3 kardel break; 1403 1.1 kardel 1404 1.1 kardel default: 1405 1.3 kardel fprintf(fp, "*** '%s' not understood\n", 1406 1.3 kardel pcmd->argval[items].string); 1407 1.3 kardel res = TRUE; 1408 1.3 kardel numtyp = 0; 1409 1.1 kardel } 1410 1.1 kardel if (val < 0) { 1411 1.3 kardel fprintf(stderr, 1412 1.3 kardel "*** Value '%s' should be unsigned\n", 1413 1.3 kardel pcmd->argval[items].string); 1414 1.3 kardel res = TRUE; 1415 1.1 kardel } 1416 1.3 kardel } 1417 1.3 kardel items++; 1418 1.1 kardel } 1419 1.1 kardel if (keyid > 0) 1420 1.3 kardel flags |= CONF_FLAG_AUTHENABLE; 1421 1.3 kardel if (version > NTP_VERSION || version < NTP_OLDVERSION) { 1422 1.3 kardel fprintf(fp, "***invalid version number: %u\n", 1423 1.3 kardel version); 1424 1.3 kardel res = TRUE; 1425 1.1 kardel } 1426 1.11 christos if (minpoll < NTP_MINPOLL || minpoll > NTP_MAXPOLL || 1427 1.11 christos maxpoll < NTP_MINPOLL || maxpoll > NTP_MAXPOLL || 1428 1.1 kardel minpoll > maxpoll) { 1429 1.3 kardel fprintf(fp, "***min/max-poll must be within %d..%d\n", 1430 1.3 kardel NTP_MINPOLL, NTP_MAXPOLL); 1431 1.3 kardel res = TRUE; 1432 1.11 christos } 1433 1.1 kardel 1434 1.1 kardel if (res) 1435 1.3 kardel return; 1436 1.1 kardel 1437 1.4 christos ZERO(cpeer); 1438 1.1 kardel 1439 1.1 kardel if (IS_IPV4(&pcmd->argval[0].netnum)) { 1440 1.1 kardel cpeer.peeraddr = NSRCADR(&pcmd->argval[0].netnum); 1441 1.1 kardel if (impl_ver == IMPL_XNTPD) 1442 1.1 kardel cpeer.v6_flag = 0; 1443 1.1 kardel } else { 1444 1.1 kardel if (impl_ver == IMPL_XNTPD_OLD) { 1445 1.1 kardel fprintf(stderr, 1446 1.1 kardel "***Server doesn't understand IPv6 addresses\n"); 1447 1.1 kardel return; 1448 1.1 kardel } 1449 1.1 kardel cpeer.peeraddr6 = SOCK_ADDR6(&pcmd->argval[0].netnum); 1450 1.1 kardel cpeer.v6_flag = 1; 1451 1.1 kardel } 1452 1.1 kardel cpeer.hmode = (u_char) mode; 1453 1.1 kardel cpeer.keyid = keyid; 1454 1.1 kardel cpeer.version = (u_char) version; 1455 1.1 kardel cpeer.minpoll = minpoll; 1456 1.1 kardel cpeer.maxpoll = maxpoll; 1457 1.1 kardel cpeer.flags = (u_char)flags; 1458 1.1 kardel cpeer.ttl = cmode; 1459 1.1 kardel 1460 1.1 kardel res = doquery(impl_ver, REQ_CONFIG, 1, 1, 1461 1.1 kardel sendsize, (char *)&cpeer, &items, 1462 1.1 kardel &itemsize, &dummy, 0, sizeof(struct conf_peer)); 1463 1.11 christos 1464 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1465 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 1466 1.1 kardel goto again; 1467 1.1 kardel } 1468 1.1 kardel 1469 1.1 kardel if (res == INFO_ERR_FMT) { 1470 1.1 kardel (void) fprintf(fp, 1471 1.1 kardel "***Retrying command with old conf_peer size\n"); 1472 1.1 kardel res = doquery(impl_ver, REQ_CONFIG, 1, 1, 1473 1.1 kardel sizeof(struct old_conf_peer), (char *)&cpeer, 1474 1.1 kardel &items, &itemsize, &dummy, 0, 1475 1.1 kardel sizeof(struct conf_peer)); 1476 1.1 kardel } 1477 1.1 kardel if (res == 0) 1478 1.1 kardel (void) fprintf(fp, "done!\n"); 1479 1.1 kardel return; 1480 1.1 kardel } 1481 1.1 kardel 1482 1.1 kardel 1483 1.1 kardel /* 1484 1.1 kardel * unconfig - unconfigure some associations 1485 1.1 kardel */ 1486 1.1 kardel static void 1487 1.1 kardel unconfig( 1488 1.1 kardel struct parse *pcmd, 1489 1.1 kardel FILE *fp 1490 1.1 kardel ) 1491 1.1 kardel { 1492 1.1 kardel /* 8 is the maximum number of peers which will fit in a packet */ 1493 1.1 kardel struct conf_unpeer *pl, plist[min(MAXARGS, 8)]; 1494 1.8 christos size_t qitemlim; 1495 1.8 christos size_t qitems; 1496 1.8 christos size_t items; 1497 1.8 christos size_t itemsize; 1498 1.8 christos const char *dummy; 1499 1.1 kardel int res; 1500 1.8 christos size_t sendsize; 1501 1.1 kardel 1502 1.1 kardel again: 1503 1.1 kardel if (impl_ver == IMPL_XNTPD) 1504 1.1 kardel sendsize = sizeof(struct conf_unpeer); 1505 1.1 kardel else 1506 1.1 kardel sendsize = v4sizeof(struct conf_unpeer); 1507 1.1 kardel 1508 1.1 kardel qitemlim = min(pcmd->nargs, COUNTOF(plist)); 1509 1.1 kardel for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) { 1510 1.1 kardel if (IS_IPV4(&pcmd->argval[0].netnum)) { 1511 1.1 kardel pl->peeraddr = NSRCADR(&pcmd->argval[qitems].netnum); 1512 1.1 kardel if (impl_ver == IMPL_XNTPD) 1513 1.1 kardel pl->v6_flag = 0; 1514 1.1 kardel } else { 1515 1.1 kardel if (impl_ver == IMPL_XNTPD_OLD) { 1516 1.1 kardel fprintf(stderr, 1517 1.1 kardel "***Server doesn't understand IPv6 addresses\n"); 1518 1.1 kardel return; 1519 1.1 kardel } 1520 1.1 kardel pl->peeraddr6 = 1521 1.1 kardel SOCK_ADDR6(&pcmd->argval[qitems].netnum); 1522 1.1 kardel pl->v6_flag = 1; 1523 1.1 kardel } 1524 1.4 christos pl = (void *)((char *)pl + sendsize); 1525 1.1 kardel } 1526 1.1 kardel 1527 1.1 kardel res = doquery(impl_ver, REQ_UNCONFIG, 1, qitems, 1528 1.1 kardel sendsize, (char *)plist, &items, 1529 1.1 kardel &itemsize, &dummy, 0, sizeof(struct conf_unpeer)); 1530 1.11 christos 1531 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1532 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 1533 1.1 kardel goto again; 1534 1.1 kardel } 1535 1.1 kardel 1536 1.1 kardel if (res == 0) 1537 1.1 kardel (void) fprintf(fp, "done!\n"); 1538 1.1 kardel } 1539 1.1 kardel 1540 1.1 kardel 1541 1.1 kardel /* 1542 1.1 kardel * set - set some system flags 1543 1.1 kardel */ 1544 1.1 kardel static void 1545 1.1 kardel set( 1546 1.1 kardel struct parse *pcmd, 1547 1.1 kardel FILE *fp 1548 1.1 kardel ) 1549 1.1 kardel { 1550 1.1 kardel doset(pcmd, fp, REQ_SET_SYS_FLAG); 1551 1.1 kardel } 1552 1.1 kardel 1553 1.1 kardel 1554 1.1 kardel /* 1555 1.1 kardel * clear - clear some system flags 1556 1.1 kardel */ 1557 1.1 kardel static void 1558 1.1 kardel sys_clear( 1559 1.1 kardel struct parse *pcmd, 1560 1.1 kardel FILE *fp 1561 1.1 kardel ) 1562 1.1 kardel { 1563 1.1 kardel doset(pcmd, fp, REQ_CLR_SYS_FLAG); 1564 1.1 kardel } 1565 1.1 kardel 1566 1.1 kardel 1567 1.1 kardel /* 1568 1.1 kardel * doset - set/clear system flags 1569 1.1 kardel */ 1570 1.1 kardel static void 1571 1.1 kardel doset( 1572 1.1 kardel struct parse *pcmd, 1573 1.1 kardel FILE *fp, 1574 1.1 kardel int req 1575 1.1 kardel ) 1576 1.1 kardel { 1577 1.1 kardel struct conf_sys_flags sys; 1578 1.8 christos size_t items; 1579 1.8 christos size_t itemsize; 1580 1.8 christos const char *dummy; 1581 1.1 kardel int res; 1582 1.1 kardel 1583 1.1 kardel sys.flags = 0; 1584 1.1 kardel res = 0; 1585 1.2 christos for (items = 0; (size_t)items < pcmd->nargs; items++) { 1586 1.1 kardel if (STREQ(pcmd->argval[items].string, "auth")) 1587 1.1 kardel sys.flags |= SYS_FLAG_AUTH; 1588 1.1 kardel else if (STREQ(pcmd->argval[items].string, "bclient")) 1589 1.1 kardel sys.flags |= SYS_FLAG_BCLIENT; 1590 1.1 kardel else if (STREQ(pcmd->argval[items].string, "calibrate")) 1591 1.1 kardel sys.flags |= SYS_FLAG_CAL; 1592 1.1 kardel else if (STREQ(pcmd->argval[items].string, "kernel")) 1593 1.1 kardel sys.flags |= SYS_FLAG_KERNEL; 1594 1.1 kardel else if (STREQ(pcmd->argval[items].string, "monitor")) 1595 1.1 kardel sys.flags |= SYS_FLAG_MONITOR; 1596 1.1 kardel else if (STREQ(pcmd->argval[items].string, "ntp")) 1597 1.1 kardel sys.flags |= SYS_FLAG_NTP; 1598 1.1 kardel else if (STREQ(pcmd->argval[items].string, "pps")) 1599 1.1 kardel sys.flags |= SYS_FLAG_PPS; 1600 1.1 kardel else if (STREQ(pcmd->argval[items].string, "stats")) 1601 1.1 kardel sys.flags |= SYS_FLAG_FILEGEN; 1602 1.1 kardel else { 1603 1.1 kardel (void) fprintf(fp, "Unknown flag %s\n", 1604 1.1 kardel pcmd->argval[items].string); 1605 1.1 kardel res = 1; 1606 1.1 kardel } 1607 1.1 kardel } 1608 1.1 kardel 1609 1.1 kardel sys.flags = htonl(sys.flags); 1610 1.1 kardel if (res || sys.flags == 0) 1611 1.1 kardel return; 1612 1.1 kardel 1613 1.1 kardel again: 1614 1.1 kardel res = doquery(impl_ver, req, 1, 1, 1615 1.1 kardel sizeof(struct conf_sys_flags), (char *)&sys, &items, 1616 1.1 kardel &itemsize, &dummy, 0, sizeof(struct conf_sys_flags)); 1617 1.11 christos 1618 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1619 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 1620 1.1 kardel goto again; 1621 1.1 kardel } 1622 1.1 kardel 1623 1.1 kardel if (res == 0) 1624 1.1 kardel (void) fprintf(fp, "done!\n"); 1625 1.1 kardel } 1626 1.1 kardel 1627 1.1 kardel 1628 1.1 kardel /* 1629 1.1 kardel * data for printing/interrpreting the restrict flags 1630 1.1 kardel */ 1631 1.1 kardel struct resflags { 1632 1.1 kardel const char *str; 1633 1.1 kardel int bit; 1634 1.1 kardel }; 1635 1.1 kardel 1636 1.1 kardel /* XXX: HMS: we apparently don't report set bits we do not recognize. */ 1637 1.1 kardel 1638 1.1 kardel static struct resflags resflagsV2[] = { 1639 1.1 kardel { "ignore", 0x001 }, 1640 1.1 kardel { "noserve", 0x002 }, 1641 1.1 kardel { "notrust", 0x004 }, 1642 1.1 kardel { "noquery", 0x008 }, 1643 1.1 kardel { "nomodify", 0x010 }, 1644 1.1 kardel { "nopeer", 0x020 }, 1645 1.1 kardel { "notrap", 0x040 }, 1646 1.1 kardel { "lptrap", 0x080 }, 1647 1.1 kardel { "limited", 0x100 }, 1648 1.1 kardel { "", 0 } 1649 1.1 kardel }; 1650 1.1 kardel 1651 1.1 kardel static struct resflags resflagsV3[] = { 1652 1.1 kardel { "ignore", RES_IGNORE }, 1653 1.1 kardel { "noserve", RES_DONTSERVE }, 1654 1.1 kardel { "notrust", RES_DONTTRUST }, 1655 1.1 kardel { "noquery", RES_NOQUERY }, 1656 1.1 kardel { "nomodify", RES_NOMODIFY }, 1657 1.1 kardel { "nopeer", RES_NOPEER }, 1658 1.1 kardel { "notrap", RES_NOTRAP }, 1659 1.1 kardel { "lptrap", RES_LPTRAP }, 1660 1.1 kardel { "limited", RES_LIMITED }, 1661 1.1 kardel { "version", RES_VERSION }, 1662 1.1 kardel { "kod", RES_KOD }, 1663 1.4 christos { "flake", RES_FLAKE }, 1664 1.1 kardel 1665 1.1 kardel { "", 0 } 1666 1.1 kardel }; 1667 1.1 kardel 1668 1.1 kardel static struct resflags resmflags[] = { 1669 1.1 kardel { "ntpport", RESM_NTPONLY }, 1670 1.1 kardel { "interface", RESM_INTERFACE }, 1671 1.4 christos { "source", RESM_SOURCE }, 1672 1.1 kardel { "", 0 } 1673 1.1 kardel }; 1674 1.1 kardel 1675 1.1 kardel 1676 1.1 kardel /* 1677 1.1 kardel * reslist - obtain and print the server's restrict list 1678 1.1 kardel */ 1679 1.1 kardel /*ARGSUSED*/ 1680 1.1 kardel static void 1681 1.1 kardel reslist( 1682 1.1 kardel struct parse *pcmd, 1683 1.1 kardel FILE *fp 1684 1.1 kardel ) 1685 1.1 kardel { 1686 1.1 kardel struct info_restrict *rl; 1687 1.1 kardel sockaddr_u resaddr; 1688 1.1 kardel sockaddr_u maskaddr; 1689 1.8 christos size_t items; 1690 1.8 christos size_t itemsize; 1691 1.1 kardel int res; 1692 1.1 kardel int skip; 1693 1.4 christos const char *addr; 1694 1.4 christos const char *mask; 1695 1.1 kardel struct resflags *rf; 1696 1.1 kardel u_int32 count; 1697 1.10 christos u_short rflags; 1698 1.1 kardel u_short mflags; 1699 1.1 kardel char flagstr[300]; 1700 1.1 kardel static const char *comma = ", "; 1701 1.1 kardel 1702 1.1 kardel again: 1703 1.1 kardel res = doquery(impl_ver, REQ_GET_RESTRICT, 0, 0, 0, (char *)NULL, 1704 1.11 christos &items, &itemsize, (void *)&rl, 0, 1705 1.1 kardel sizeof(struct info_restrict)); 1706 1.11 christos 1707 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1708 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 1709 1.1 kardel goto again; 1710 1.1 kardel } 1711 1.1 kardel 1712 1.1 kardel if (res != 0) 1713 1.4 christos return; 1714 1.1 kardel 1715 1.1 kardel if (!checkitems(items, fp)) 1716 1.4 christos return; 1717 1.1 kardel 1718 1.1 kardel if (!checkitemsize(itemsize, sizeof(struct info_restrict)) && 1719 1.1 kardel !checkitemsize(itemsize, v4sizeof(struct info_restrict))) 1720 1.4 christos return; 1721 1.1 kardel 1722 1.4 christos fprintf(fp, 1723 1.4 christos " address mask count flags\n"); 1724 1.4 christos fprintf(fp, 1725 1.4 christos "=====================================================================\n"); 1726 1.1 kardel 1727 1.1 kardel while (items > 0) { 1728 1.1 kardel SET_ADDRS(resaddr, maskaddr, rl, addr, mask); 1729 1.1 kardel if (rl->v6_flag != 0) { 1730 1.1 kardel addr = nntohost(&resaddr); 1731 1.1 kardel } else { 1732 1.4 christos if (rl->mask == (u_int32)0xffffffff) 1733 1.1 kardel addr = nntohost(&resaddr); 1734 1.1 kardel else 1735 1.1 kardel addr = stoa(&resaddr); 1736 1.1 kardel } 1737 1.1 kardel mask = stoa(&maskaddr); 1738 1.1 kardel skip = 1; 1739 1.1 kardel if ((pcmd->nargs == 0) || 1740 1.1 kardel ((pcmd->argval->ival == 6) && (rl->v6_flag != 0)) || 1741 1.1 kardel ((pcmd->argval->ival == 4) && (rl->v6_flag == 0))) 1742 1.1 kardel skip = 0; 1743 1.1 kardel count = ntohl(rl->count); 1744 1.10 christos rflags = ntohs(rl->rflags); 1745 1.1 kardel mflags = ntohs(rl->mflags); 1746 1.1 kardel flagstr[0] = '\0'; 1747 1.1 kardel 1748 1.1 kardel res = 1; 1749 1.1 kardel rf = &resmflags[0]; 1750 1.1 kardel while (rf->bit != 0) { 1751 1.1 kardel if (mflags & rf->bit) { 1752 1.1 kardel if (!res) 1753 1.4 christos strlcat(flagstr, comma, 1754 1.4 christos sizeof(flagstr)); 1755 1.1 kardel res = 0; 1756 1.4 christos strlcat(flagstr, rf->str, 1757 1.4 christos sizeof(flagstr)); 1758 1.1 kardel } 1759 1.1 kardel rf++; 1760 1.1 kardel } 1761 1.1 kardel 1762 1.1 kardel rf = (impl_ver == IMPL_XNTPD_OLD) 1763 1.4 christos ? &resflagsV2[0] 1764 1.4 christos : &resflagsV3[0]; 1765 1.4 christos 1766 1.1 kardel while (rf->bit != 0) { 1767 1.10 christos if (rflags & rf->bit) { 1768 1.1 kardel if (!res) 1769 1.4 christos strlcat(flagstr, comma, 1770 1.4 christos sizeof(flagstr)); 1771 1.1 kardel res = 0; 1772 1.4 christos strlcat(flagstr, rf->str, 1773 1.4 christos sizeof(flagstr)); 1774 1.1 kardel } 1775 1.1 kardel rf++; 1776 1.1 kardel } 1777 1.1 kardel 1778 1.1 kardel if (flagstr[0] == '\0') 1779 1.4 christos strlcpy(flagstr, "none", sizeof(flagstr)); 1780 1.1 kardel 1781 1.1 kardel if (!skip) 1782 1.3 kardel fprintf(fp, "%-15.15s %-15.15s %9lu %s\n", 1783 1.3 kardel addr, mask, (u_long)count, flagstr); 1784 1.1 kardel rl++; 1785 1.1 kardel items--; 1786 1.1 kardel } 1787 1.1 kardel } 1788 1.1 kardel 1789 1.1 kardel 1790 1.1 kardel 1791 1.1 kardel /* 1792 1.1 kardel * new_restrict - create/add a set of restrictions 1793 1.1 kardel */ 1794 1.1 kardel static void 1795 1.1 kardel new_restrict( 1796 1.1 kardel struct parse *pcmd, 1797 1.1 kardel FILE *fp 1798 1.1 kardel ) 1799 1.1 kardel { 1800 1.1 kardel do_restrict(pcmd, fp, REQ_RESADDFLAGS); 1801 1.1 kardel } 1802 1.1 kardel 1803 1.1 kardel 1804 1.1 kardel /* 1805 1.1 kardel * unrestrict - remove restriction flags from existing entry 1806 1.1 kardel */ 1807 1.1 kardel static void 1808 1.1 kardel unrestrict( 1809 1.1 kardel struct parse *pcmd, 1810 1.1 kardel FILE *fp 1811 1.1 kardel ) 1812 1.1 kardel { 1813 1.1 kardel do_restrict(pcmd, fp, REQ_RESSUBFLAGS); 1814 1.1 kardel } 1815 1.1 kardel 1816 1.1 kardel 1817 1.1 kardel /* 1818 1.1 kardel * delrestrict - delete an existing restriction 1819 1.1 kardel */ 1820 1.1 kardel static void 1821 1.1 kardel delrestrict( 1822 1.1 kardel struct parse *pcmd, 1823 1.1 kardel FILE *fp 1824 1.1 kardel ) 1825 1.1 kardel { 1826 1.1 kardel do_restrict(pcmd, fp, REQ_UNRESTRICT); 1827 1.1 kardel } 1828 1.1 kardel 1829 1.1 kardel 1830 1.1 kardel /* 1831 1.1 kardel * do_restrict - decode commandline restrictions and make the request 1832 1.1 kardel */ 1833 1.1 kardel static void 1834 1.1 kardel do_restrict( 1835 1.1 kardel struct parse *pcmd, 1836 1.1 kardel FILE *fp, 1837 1.1 kardel int req_code 1838 1.1 kardel ) 1839 1.1 kardel { 1840 1.1 kardel struct conf_restrict cres; 1841 1.8 christos size_t items; 1842 1.8 christos size_t itemsize; 1843 1.8 christos const char *dummy; 1844 1.1 kardel u_int32 num; 1845 1.1 kardel u_long bit; 1846 1.1 kardel int i; 1847 1.2 christos size_t res; 1848 1.1 kardel int err; 1849 1.1 kardel int sendsize; 1850 1.1 kardel 1851 1.1 kardel /* Initialize cres */ 1852 1.1 kardel cres.addr = 0; 1853 1.1 kardel cres.mask = 0; 1854 1.1 kardel cres.flags = 0; 1855 1.1 kardel cres.mflags = 0; 1856 1.1 kardel cres.v6_flag = 0; 1857 1.1 kardel 1858 1.1 kardel again: 1859 1.1 kardel if (impl_ver == IMPL_XNTPD) 1860 1.1 kardel sendsize = sizeof(struct conf_restrict); 1861 1.1 kardel else 1862 1.1 kardel sendsize = v4sizeof(struct conf_restrict); 1863 1.1 kardel 1864 1.1 kardel if (IS_IPV4(&pcmd->argval[0].netnum)) { 1865 1.1 kardel cres.addr = NSRCADR(&pcmd->argval[0].netnum); 1866 1.1 kardel cres.mask = NSRCADR(&pcmd->argval[1].netnum); 1867 1.1 kardel if (impl_ver == IMPL_XNTPD) 1868 1.1 kardel cres.v6_flag = 0; 1869 1.1 kardel } else { 1870 1.1 kardel if (impl_ver == IMPL_XNTPD_OLD) { 1871 1.1 kardel fprintf(stderr, 1872 1.3 kardel "***Server doesn't understand IPv6 addresses\n"); 1873 1.1 kardel return; 1874 1.1 kardel } 1875 1.1 kardel cres.addr6 = SOCK_ADDR6(&pcmd->argval[0].netnum); 1876 1.1 kardel cres.v6_flag = 1; 1877 1.1 kardel } 1878 1.1 kardel cres.flags = 0; 1879 1.1 kardel cres.mflags = 0; 1880 1.3 kardel err = FALSE; 1881 1.1 kardel for (res = 2; res < pcmd->nargs; res++) { 1882 1.1 kardel if (STREQ(pcmd->argval[res].string, "ntpport")) { 1883 1.1 kardel cres.mflags |= RESM_NTPONLY; 1884 1.1 kardel } else { 1885 1.1 kardel for (i = 0; resflagsV3[i].bit != 0; i++) { 1886 1.1 kardel if (STREQ(pcmd->argval[res].string, 1887 1.1 kardel resflagsV3[i].str)) 1888 1.3 kardel break; 1889 1.1 kardel } 1890 1.1 kardel if (resflagsV3[i].bit != 0) { 1891 1.1 kardel cres.flags |= resflagsV3[i].bit; 1892 1.1 kardel if (req_code == REQ_UNRESTRICT) { 1893 1.3 kardel fprintf(fp, 1894 1.3 kardel "Flag %s inappropriate\n", 1895 1.3 kardel resflagsV3[i].str); 1896 1.3 kardel err = TRUE; 1897 1.1 kardel } 1898 1.1 kardel } else { 1899 1.3 kardel fprintf(fp, "Unknown flag %s\n", 1900 1.3 kardel pcmd->argval[res].string); 1901 1.3 kardel err = TRUE; 1902 1.1 kardel } 1903 1.1 kardel } 1904 1.1 kardel } 1905 1.1 kardel cres.flags = htons(cres.flags); 1906 1.1 kardel cres.mflags = htons(cres.mflags); 1907 1.1 kardel 1908 1.1 kardel /* 1909 1.1 kardel * Make sure mask for default address is zero. Otherwise, 1910 1.1 kardel * make sure mask bits are contiguous. 1911 1.1 kardel */ 1912 1.1 kardel if (IS_IPV4(&pcmd->argval[0].netnum)) { 1913 1.1 kardel if (cres.addr == 0) { 1914 1.1 kardel cres.mask = 0; 1915 1.1 kardel } else { 1916 1.1 kardel num = ntohl(cres.mask); 1917 1.1 kardel for (bit = 0x80000000; bit != 0; bit >>= 1) 1918 1.3 kardel if ((num & bit) == 0) 1919 1.3 kardel break; 1920 1.1 kardel for ( ; bit != 0; bit >>= 1) 1921 1.3 kardel if ((num & bit) != 0) 1922 1.3 kardel break; 1923 1.1 kardel if (bit != 0) { 1924 1.3 kardel fprintf(fp, "Invalid mask %s\n", 1925 1.3 kardel numtoa(cres.mask)); 1926 1.3 kardel err = TRUE; 1927 1.1 kardel } 1928 1.1 kardel } 1929 1.1 kardel } else { 1930 1.1 kardel /* XXX IPv6 sanity checking stuff */ 1931 1.1 kardel } 1932 1.1 kardel 1933 1.1 kardel if (err) 1934 1.3 kardel return; 1935 1.1 kardel 1936 1.3 kardel res = doquery(impl_ver, req_code, 1, 1, sendsize, (char *)&cres, 1937 1.3 kardel &items, &itemsize, &dummy, 0, sizeof(cres)); 1938 1.11 christos 1939 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1940 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 1941 1.1 kardel goto again; 1942 1.1 kardel } 1943 1.1 kardel 1944 1.1 kardel if (res == 0) 1945 1.1 kardel (void) fprintf(fp, "done!\n"); 1946 1.1 kardel return; 1947 1.1 kardel } 1948 1.1 kardel 1949 1.1 kardel 1950 1.1 kardel /* 1951 1.1 kardel * monlist - obtain and print the server's monitor data 1952 1.1 kardel */ 1953 1.1 kardel /*ARGSUSED*/ 1954 1.1 kardel static void 1955 1.1 kardel monlist( 1956 1.1 kardel struct parse *pcmd, 1957 1.1 kardel FILE *fp 1958 1.1 kardel ) 1959 1.1 kardel { 1960 1.8 christos const char *struct_star; 1961 1.8 christos const struct info_monitor *ml; 1962 1.8 christos const struct info_monitor_1 *m1; 1963 1.8 christos const struct old_info_monitor *oml; 1964 1.1 kardel sockaddr_u addr; 1965 1.1 kardel sockaddr_u dstadr; 1966 1.8 christos size_t items; 1967 1.8 christos size_t itemsize; 1968 1.1 kardel int res; 1969 1.1 kardel int version = -1; 1970 1.1 kardel 1971 1.4 christos if (pcmd->nargs > 0) 1972 1.1 kardel version = pcmd->argval[0].ival; 1973 1.1 kardel 1974 1.1 kardel again: 1975 1.1 kardel res = doquery(impl_ver, 1976 1.1 kardel (version == 1 || version == -1) ? REQ_MON_GETLIST_1 : 1977 1.4 christos REQ_MON_GETLIST, 0, 0, 0, NULL, 1978 1.1 kardel &items, &itemsize, &struct_star, 1979 1.11 christos (version < 0) ? (1 << INFO_ERR_REQ) : 0, 1980 1.1 kardel sizeof(struct info_monitor_1)); 1981 1.1 kardel 1982 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 1983 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 1984 1.1 kardel goto again; 1985 1.1 kardel } 1986 1.1 kardel 1987 1.11 christos if (res == INFO_ERR_REQ && version < 0) 1988 1.4 christos res = doquery(impl_ver, REQ_MON_GETLIST, 0, 0, 0, NULL, 1989 1.4 christos &items, &itemsize, &struct_star, 0, 1990 1.4 christos sizeof(struct info_monitor)); 1991 1.11 christos 1992 1.1 kardel if (res != 0) 1993 1.4 christos return; 1994 1.1 kardel 1995 1.1 kardel if (!checkitems(items, fp)) 1996 1.4 christos return; 1997 1.1 kardel 1998 1.1 kardel if (itemsize == sizeof(struct info_monitor_1) || 1999 1.1 kardel itemsize == v4sizeof(struct info_monitor_1)) { 2000 1.1 kardel 2001 1.8 christos m1 = (const void*)struct_star; 2002 1.4 christos fprintf(fp, 2003 1.4 christos "remote address port local address count m ver rstr avgint lstint\n"); 2004 1.4 christos fprintf(fp, 2005 1.4 christos "===============================================================================\n"); 2006 1.1 kardel while (items > 0) { 2007 1.4 christos SET_ADDRS(dstadr, addr, m1, daddr, addr); 2008 1.1 kardel if ((pcmd->nargs == 0) || 2009 1.4 christos ((pcmd->argval->ival == 6) && (m1->v6_flag != 0)) || 2010 1.4 christos ((pcmd->argval->ival == 4) && (m1->v6_flag == 0))) 2011 1.11 christos fprintf(fp, 2012 1.3 kardel "%-22.22s %5d %-15s %8lu %1u %1u %6lx %6lu %7lu\n", 2013 1.11 christos nntohost(&addr), 2014 1.4 christos ntohs(m1->port), 2015 1.1 kardel stoa(&dstadr), 2016 1.4 christos (u_long)ntohl(m1->count), 2017 1.4 christos m1->mode, 2018 1.4 christos m1->version, 2019 1.4 christos (u_long)ntohl(m1->restr), 2020 1.4 christos (u_long)ntohl(m1->avg_int), 2021 1.4 christos (u_long)ntohl(m1->last_int)); 2022 1.4 christos m1++; 2023 1.1 kardel items--; 2024 1.1 kardel } 2025 1.1 kardel } else if (itemsize == sizeof(struct info_monitor) || 2026 1.1 kardel itemsize == v4sizeof(struct info_monitor)) { 2027 1.1 kardel 2028 1.8 christos ml = (const void *)struct_star; 2029 1.4 christos fprintf(fp, 2030 1.4 christos " address port count mode ver rstr avgint lstint\n"); 2031 1.4 christos fprintf(fp, 2032 1.4 christos "===============================================================================\n"); 2033 1.1 kardel while (items > 0) { 2034 1.1 kardel SET_ADDR(dstadr, ml->v6_flag, ml->addr, ml->addr6); 2035 1.1 kardel if ((pcmd->nargs == 0) || 2036 1.1 kardel ((pcmd->argval->ival == 6) && (ml->v6_flag != 0)) || 2037 1.1 kardel ((pcmd->argval->ival == 4) && (ml->v6_flag == 0))) 2038 1.4 christos fprintf(fp, 2039 1.3 kardel "%-25.25s %5u %9lu %4u %2u %9lx %9lu %9lu\n", 2040 1.1 kardel nntohost(&dstadr), 2041 1.1 kardel ntohs(ml->port), 2042 1.1 kardel (u_long)ntohl(ml->count), 2043 1.1 kardel ml->mode, 2044 1.1 kardel ml->version, 2045 1.1 kardel (u_long)ntohl(ml->restr), 2046 1.4 christos (u_long)ntohl(ml->avg_int), 2047 1.4 christos (u_long)ntohl(ml->last_int)); 2048 1.1 kardel ml++; 2049 1.1 kardel items--; 2050 1.1 kardel } 2051 1.1 kardel } else if (itemsize == sizeof(struct old_info_monitor)) { 2052 1.4 christos 2053 1.8 christos oml = (const void *)struct_star; 2054 1.4 christos fprintf(fp, 2055 1.4 christos " address port count mode version lasttime firsttime\n"); 2056 1.4 christos fprintf(fp, 2057 1.4 christos "======================================================================\n"); 2058 1.1 kardel while (items > 0) { 2059 1.1 kardel SET_ADDR(dstadr, oml->v6_flag, oml->addr, oml->addr6); 2060 1.4 christos fprintf(fp, "%-20.20s %5u %9lu %4u %3u %9lu %9lu\n", 2061 1.4 christos nntohost(&dstadr), 2062 1.4 christos ntohs(oml->port), 2063 1.4 christos (u_long)ntohl(oml->count), 2064 1.4 christos oml->mode, 2065 1.4 christos oml->version, 2066 1.4 christos (u_long)ntohl(oml->lasttime), 2067 1.4 christos (u_long)ntohl(oml->firsttime)); 2068 1.1 kardel oml++; 2069 1.1 kardel items--; 2070 1.1 kardel } 2071 1.1 kardel } else { 2072 1.1 kardel /* issue warning according to new info_monitor size */ 2073 1.1 kardel checkitemsize(itemsize, sizeof(struct info_monitor)); 2074 1.1 kardel } 2075 1.1 kardel } 2076 1.1 kardel 2077 1.1 kardel 2078 1.1 kardel /* 2079 1.1 kardel * Mapping between command line strings and stat reset flags 2080 1.1 kardel */ 2081 1.1 kardel struct statreset { 2082 1.4 christos const char * const str; 2083 1.4 christos const int flag; 2084 1.1 kardel } sreset[] = { 2085 1.4 christos { "allpeers", RESET_FLAG_ALLPEERS }, 2086 1.1 kardel { "io", RESET_FLAG_IO }, 2087 1.1 kardel { "sys", RESET_FLAG_SYS }, 2088 1.1 kardel { "mem", RESET_FLAG_MEM }, 2089 1.1 kardel { "timer", RESET_FLAG_TIMER }, 2090 1.1 kardel { "auth", RESET_FLAG_AUTH }, 2091 1.4 christos { "ctl", RESET_FLAG_CTL }, 2092 1.1 kardel { "", 0 } 2093 1.1 kardel }; 2094 1.1 kardel 2095 1.1 kardel /* 2096 1.1 kardel * reset - reset statistic counters 2097 1.1 kardel */ 2098 1.1 kardel static void 2099 1.1 kardel reset( 2100 1.1 kardel struct parse *pcmd, 2101 1.1 kardel FILE *fp 2102 1.1 kardel ) 2103 1.1 kardel { 2104 1.1 kardel struct reset_flags rflags; 2105 1.8 christos size_t items; 2106 1.8 christos size_t itemsize; 2107 1.8 christos const char *dummy; 2108 1.1 kardel int i; 2109 1.2 christos size_t res; 2110 1.1 kardel int err; 2111 1.1 kardel 2112 1.1 kardel err = 0; 2113 1.1 kardel rflags.flags = 0; 2114 1.1 kardel for (res = 0; res < pcmd->nargs; res++) { 2115 1.1 kardel for (i = 0; sreset[i].flag != 0; i++) { 2116 1.1 kardel if (STREQ(pcmd->argval[res].string, sreset[i].str)) 2117 1.4 christos break; 2118 1.1 kardel } 2119 1.1 kardel if (sreset[i].flag == 0) { 2120 1.4 christos fprintf(fp, "Flag %s unknown\n", 2121 1.4 christos pcmd->argval[res].string); 2122 1.9 christos err = 1; 2123 1.1 kardel } else { 2124 1.1 kardel rflags.flags |= sreset[i].flag; 2125 1.1 kardel } 2126 1.1 kardel } 2127 1.1 kardel rflags.flags = htonl(rflags.flags); 2128 1.1 kardel 2129 1.1 kardel if (err) { 2130 1.1 kardel (void) fprintf(fp, "Not done due to errors\n"); 2131 1.1 kardel return; 2132 1.1 kardel } 2133 1.1 kardel 2134 1.1 kardel again: 2135 1.1 kardel res = doquery(impl_ver, REQ_RESET_STATS, 1, 1, 2136 1.1 kardel sizeof(struct reset_flags), (char *)&rflags, &items, 2137 1.1 kardel &itemsize, &dummy, 0, sizeof(struct reset_flags)); 2138 1.11 christos 2139 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2140 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 2141 1.1 kardel goto again; 2142 1.1 kardel } 2143 1.1 kardel 2144 1.1 kardel if (res == 0) 2145 1.1 kardel (void) fprintf(fp, "done!\n"); 2146 1.1 kardel return; 2147 1.1 kardel } 2148 1.1 kardel 2149 1.1 kardel 2150 1.1 kardel 2151 1.1 kardel /* 2152 1.1 kardel * preset - reset stat counters for particular peers 2153 1.1 kardel */ 2154 1.1 kardel static void 2155 1.1 kardel preset( 2156 1.1 kardel struct parse *pcmd, 2157 1.1 kardel FILE *fp 2158 1.1 kardel ) 2159 1.1 kardel { 2160 1.1 kardel /* 8 is the maximum number of peers which will fit in a packet */ 2161 1.1 kardel struct conf_unpeer *pl, plist[min(MAXARGS, 8)]; 2162 1.8 christos size_t qitemlim; 2163 1.8 christos size_t qitems; 2164 1.8 christos size_t items; 2165 1.8 christos size_t itemsize; 2166 1.8 christos const char *dummy; 2167 1.1 kardel int res; 2168 1.8 christos size_t sendsize; 2169 1.1 kardel 2170 1.1 kardel again: 2171 1.1 kardel if (impl_ver == IMPL_XNTPD) 2172 1.1 kardel sendsize = sizeof(struct conf_unpeer); 2173 1.1 kardel else 2174 1.1 kardel sendsize = v4sizeof(struct conf_unpeer); 2175 1.1 kardel 2176 1.1 kardel qitemlim = min(pcmd->nargs, COUNTOF(plist)); 2177 1.1 kardel for (qitems = 0, pl = plist; qitems < qitemlim; qitems++) { 2178 1.1 kardel if (IS_IPV4(&pcmd->argval[qitems].netnum)) { 2179 1.1 kardel pl->peeraddr = NSRCADR(&pcmd->argval[qitems].netnum); 2180 1.1 kardel if (impl_ver == IMPL_XNTPD) 2181 1.1 kardel pl->v6_flag = 0; 2182 1.1 kardel } else { 2183 1.1 kardel if (impl_ver == IMPL_XNTPD_OLD) { 2184 1.1 kardel fprintf(stderr, 2185 1.1 kardel "***Server doesn't understand IPv6 addresses\n"); 2186 1.1 kardel return; 2187 1.1 kardel } 2188 1.1 kardel pl->peeraddr6 = 2189 1.1 kardel SOCK_ADDR6(&pcmd->argval[qitems].netnum); 2190 1.1 kardel pl->v6_flag = 1; 2191 1.1 kardel } 2192 1.4 christos pl = (void *)((char *)pl + sendsize); 2193 1.1 kardel } 2194 1.1 kardel 2195 1.1 kardel res = doquery(impl_ver, REQ_RESET_PEER, 1, qitems, 2196 1.1 kardel sendsize, (char *)plist, &items, 2197 1.1 kardel &itemsize, &dummy, 0, sizeof(struct conf_unpeer)); 2198 1.11 christos 2199 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2200 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 2201 1.1 kardel goto again; 2202 1.1 kardel } 2203 1.1 kardel 2204 1.1 kardel if (res == 0) 2205 1.1 kardel (void) fprintf(fp, "done!\n"); 2206 1.1 kardel } 2207 1.1 kardel 2208 1.1 kardel 2209 1.1 kardel /* 2210 1.1 kardel * readkeys - request the server to reread the keys file 2211 1.1 kardel */ 2212 1.1 kardel /*ARGSUSED*/ 2213 1.1 kardel static void 2214 1.1 kardel readkeys( 2215 1.1 kardel struct parse *pcmd, 2216 1.1 kardel FILE *fp 2217 1.1 kardel ) 2218 1.1 kardel { 2219 1.8 christos size_t items; 2220 1.8 christos size_t itemsize; 2221 1.8 christos const char *dummy; 2222 1.1 kardel int res; 2223 1.1 kardel 2224 1.1 kardel again: 2225 1.1 kardel res = doquery(impl_ver, REQ_REREAD_KEYS, 1, 0, 0, (char *)0, 2226 1.1 kardel &items, &itemsize, &dummy, 0, sizeof(dummy)); 2227 1.11 christos 2228 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2229 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 2230 1.1 kardel goto again; 2231 1.1 kardel } 2232 1.1 kardel 2233 1.1 kardel if (res == 0) 2234 1.1 kardel (void) fprintf(fp, "done!\n"); 2235 1.1 kardel return; 2236 1.1 kardel } 2237 1.1 kardel 2238 1.1 kardel 2239 1.1 kardel /* 2240 1.1 kardel * trustkey - add some keys to the trusted key list 2241 1.1 kardel */ 2242 1.1 kardel static void 2243 1.1 kardel trustkey( 2244 1.1 kardel struct parse *pcmd, 2245 1.1 kardel FILE *fp 2246 1.1 kardel ) 2247 1.1 kardel { 2248 1.1 kardel do_trustkey(pcmd, fp, REQ_TRUSTKEY); 2249 1.1 kardel } 2250 1.1 kardel 2251 1.1 kardel 2252 1.1 kardel /* 2253 1.1 kardel * untrustkey - remove some keys from the trusted key list 2254 1.1 kardel */ 2255 1.1 kardel static void 2256 1.1 kardel untrustkey( 2257 1.1 kardel struct parse *pcmd, 2258 1.1 kardel FILE *fp 2259 1.1 kardel ) 2260 1.1 kardel { 2261 1.1 kardel do_trustkey(pcmd, fp, REQ_UNTRUSTKEY); 2262 1.1 kardel } 2263 1.1 kardel 2264 1.1 kardel 2265 1.1 kardel /* 2266 1.1 kardel * do_trustkey - do grunge work of adding/deleting keys 2267 1.1 kardel */ 2268 1.1 kardel static void 2269 1.1 kardel do_trustkey( 2270 1.1 kardel struct parse *pcmd, 2271 1.1 kardel FILE *fp, 2272 1.1 kardel int req 2273 1.1 kardel ) 2274 1.1 kardel { 2275 1.1 kardel u_long keyids[MAXARGS]; 2276 1.2 christos size_t i; 2277 1.8 christos size_t items; 2278 1.8 christos size_t itemsize; 2279 1.8 christos const char *dummy; 2280 1.1 kardel int ritems; 2281 1.1 kardel int res; 2282 1.1 kardel 2283 1.1 kardel ritems = 0; 2284 1.1 kardel for (i = 0; i < pcmd->nargs; i++) { 2285 1.1 kardel keyids[ritems++] = pcmd->argval[i].uval; 2286 1.1 kardel } 2287 1.1 kardel 2288 1.1 kardel again: 2289 1.1 kardel res = doquery(impl_ver, req, 1, ritems, sizeof(u_long), 2290 1.11 christos (char *)keyids, &items, &itemsize, &dummy, 0, 2291 1.1 kardel sizeof(dummy)); 2292 1.11 christos 2293 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2294 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 2295 1.1 kardel goto again; 2296 1.1 kardel } 2297 1.1 kardel 2298 1.1 kardel if (res == 0) 2299 1.1 kardel (void) fprintf(fp, "done!\n"); 2300 1.1 kardel return; 2301 1.1 kardel } 2302 1.1 kardel 2303 1.1 kardel 2304 1.1 kardel 2305 1.1 kardel /* 2306 1.1 kardel * authinfo - obtain and print info about authentication 2307 1.1 kardel */ 2308 1.1 kardel /*ARGSUSED*/ 2309 1.1 kardel static void 2310 1.1 kardel authinfo( 2311 1.1 kardel struct parse *pcmd, 2312 1.1 kardel FILE *fp 2313 1.1 kardel ) 2314 1.1 kardel { 2315 1.1 kardel struct info_auth *ia; 2316 1.8 christos size_t items; 2317 1.8 christos size_t itemsize; 2318 1.1 kardel int res; 2319 1.1 kardel 2320 1.1 kardel again: 2321 1.3 kardel res = doquery(impl_ver, REQ_AUTHINFO, 0, 0, 0, NULL, &items, 2322 1.3 kardel &itemsize, (void *)&ia, 0, sizeof(*ia)); 2323 1.11 christos 2324 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2325 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 2326 1.1 kardel goto again; 2327 1.1 kardel } 2328 1.1 kardel 2329 1.1 kardel if (res != 0) 2330 1.3 kardel return; 2331 1.1 kardel 2332 1.1 kardel if (!check1item(items, fp)) 2333 1.3 kardel return; 2334 1.1 kardel 2335 1.3 kardel if (!checkitemsize(itemsize, sizeof(*ia))) 2336 1.3 kardel return; 2337 1.1 kardel 2338 1.3 kardel fprintf(fp, "time since reset: %lu\n", 2339 1.3 kardel (u_long)ntohl(ia->timereset)); 2340 1.3 kardel fprintf(fp, "stored keys: %lu\n", 2341 1.3 kardel (u_long)ntohl(ia->numkeys)); 2342 1.3 kardel fprintf(fp, "free keys: %lu\n", 2343 1.3 kardel (u_long)ntohl(ia->numfreekeys)); 2344 1.3 kardel fprintf(fp, "key lookups: %lu\n", 2345 1.3 kardel (u_long)ntohl(ia->keylookups)); 2346 1.3 kardel fprintf(fp, "keys not found: %lu\n", 2347 1.3 kardel (u_long)ntohl(ia->keynotfound)); 2348 1.3 kardel fprintf(fp, "uncached keys: %lu\n", 2349 1.3 kardel (u_long)ntohl(ia->keyuncached)); 2350 1.3 kardel fprintf(fp, "encryptions: %lu\n", 2351 1.3 kardel (u_long)ntohl(ia->encryptions)); 2352 1.3 kardel fprintf(fp, "decryptions: %lu\n", 2353 1.3 kardel (u_long)ntohl(ia->decryptions)); 2354 1.3 kardel fprintf(fp, "expired keys: %lu\n", 2355 1.3 kardel (u_long)ntohl(ia->expired)); 2356 1.1 kardel } 2357 1.1 kardel 2358 1.1 kardel 2359 1.1 kardel 2360 1.1 kardel /* 2361 1.1 kardel * traps - obtain and print a list of traps 2362 1.1 kardel */ 2363 1.1 kardel /*ARGSUSED*/ 2364 1.1 kardel static void 2365 1.1 kardel traps( 2366 1.1 kardel struct parse *pcmd, 2367 1.1 kardel FILE *fp 2368 1.1 kardel ) 2369 1.1 kardel { 2370 1.8 christos size_t i; 2371 1.1 kardel struct info_trap *it; 2372 1.1 kardel sockaddr_u trap_addr, local_addr; 2373 1.8 christos size_t items; 2374 1.8 christos size_t itemsize; 2375 1.1 kardel int res; 2376 1.1 kardel 2377 1.1 kardel again: 2378 1.4 christos res = doquery(impl_ver, REQ_TRAPS, 0, 0, 0, NULL, &items, 2379 1.4 christos &itemsize, (void *)&it, 0, sizeof(*it)); 2380 1.11 christos 2381 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2382 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 2383 1.1 kardel goto again; 2384 1.1 kardel } 2385 1.1 kardel 2386 1.1 kardel if (res != 0) 2387 1.4 christos return; 2388 1.1 kardel 2389 1.1 kardel if (!checkitems(items, fp)) 2390 1.4 christos return; 2391 1.1 kardel 2392 1.1 kardel if (!checkitemsize(itemsize, sizeof(struct info_trap)) && 2393 1.1 kardel !checkitemsize(itemsize, v4sizeof(struct info_trap))) 2394 1.4 christos return; 2395 1.1 kardel 2396 1.1 kardel for (i = 0; i < items; i++ ) { 2397 1.1 kardel SET_ADDRS(trap_addr, local_addr, it, trap_address, local_address); 2398 1.4 christos fprintf(fp, "%saddress %s, port %d\n", 2399 1.4 christos (0 == i) 2400 1.4 christos ? "" 2401 1.4 christos : "\n", 2402 1.4 christos stoa(&trap_addr), ntohs(it->trap_port)); 2403 1.4 christos fprintf(fp, "interface: %s, ", 2404 1.4 christos (0 == it->local_address) 2405 1.4 christos ? "wildcard" 2406 1.4 christos : stoa(&local_addr)); 2407 1.1 kardel if (ntohl(it->flags) & TRAP_CONFIGURED) 2408 1.4 christos fprintf(fp, "configured\n"); 2409 1.1 kardel else if (ntohl(it->flags) & TRAP_NONPRIO) 2410 1.4 christos fprintf(fp, "low priority\n"); 2411 1.1 kardel else 2412 1.4 christos fprintf(fp, "normal priority\n"); 2413 1.11 christos 2414 1.4 christos fprintf(fp, "set for %ld secs, last set %ld secs ago\n", 2415 1.4 christos (long)ntohl(it->origtime), 2416 1.4 christos (long)ntohl(it->settime)); 2417 1.4 christos fprintf(fp, "sequence %d, number of resets %ld\n", 2418 1.4 christos ntohs(it->sequence), (long)ntohl(it->resets)); 2419 1.1 kardel } 2420 1.1 kardel } 2421 1.1 kardel 2422 1.1 kardel 2423 1.1 kardel /* 2424 1.1 kardel * addtrap - configure a trap 2425 1.1 kardel */ 2426 1.1 kardel static void 2427 1.1 kardel addtrap( 2428 1.1 kardel struct parse *pcmd, 2429 1.1 kardel FILE *fp 2430 1.1 kardel ) 2431 1.1 kardel { 2432 1.1 kardel do_addclr_trap(pcmd, fp, REQ_ADD_TRAP); 2433 1.1 kardel } 2434 1.1 kardel 2435 1.1 kardel 2436 1.1 kardel /* 2437 1.1 kardel * clrtrap - clear a trap from the server 2438 1.1 kardel */ 2439 1.1 kardel static void 2440 1.1 kardel clrtrap( 2441 1.1 kardel struct parse *pcmd, 2442 1.1 kardel FILE *fp 2443 1.1 kardel ) 2444 1.1 kardel { 2445 1.1 kardel do_addclr_trap(pcmd, fp, REQ_CLR_TRAP); 2446 1.1 kardel } 2447 1.1 kardel 2448 1.1 kardel 2449 1.1 kardel /* 2450 1.1 kardel * do_addclr_trap - do grunge work of adding/deleting traps 2451 1.1 kardel */ 2452 1.1 kardel static void 2453 1.1 kardel do_addclr_trap( 2454 1.1 kardel struct parse *pcmd, 2455 1.1 kardel FILE *fp, 2456 1.1 kardel int req 2457 1.1 kardel ) 2458 1.1 kardel { 2459 1.1 kardel struct conf_trap ctrap; 2460 1.8 christos size_t items; 2461 1.8 christos size_t itemsize; 2462 1.8 christos const char *dummy; 2463 1.1 kardel int res; 2464 1.1 kardel int sendsize; 2465 1.1 kardel 2466 1.1 kardel again: 2467 1.1 kardel if (impl_ver == IMPL_XNTPD) 2468 1.1 kardel sendsize = sizeof(struct conf_trap); 2469 1.1 kardel else 2470 1.1 kardel sendsize = v4sizeof(struct conf_trap); 2471 1.1 kardel 2472 1.1 kardel if (IS_IPV4(&pcmd->argval[0].netnum)) { 2473 1.1 kardel ctrap.trap_address = NSRCADR(&pcmd->argval[0].netnum); 2474 1.1 kardel if (impl_ver == IMPL_XNTPD) 2475 1.1 kardel ctrap.v6_flag = 0; 2476 1.1 kardel } else { 2477 1.1 kardel if (impl_ver == IMPL_XNTPD_OLD) { 2478 1.1 kardel fprintf(stderr, 2479 1.1 kardel "***Server doesn't understand IPv6 addresses\n"); 2480 1.1 kardel return; 2481 1.1 kardel } 2482 1.1 kardel ctrap.trap_address6 = SOCK_ADDR6(&pcmd->argval[0].netnum); 2483 1.1 kardel ctrap.v6_flag = 1; 2484 1.1 kardel } 2485 1.1 kardel ctrap.local_address = 0; 2486 1.1 kardel ctrap.trap_port = htons(TRAPPORT); 2487 1.1 kardel ctrap.unused = 0; 2488 1.1 kardel 2489 1.1 kardel if (pcmd->nargs > 1) { 2490 1.1 kardel ctrap.trap_port = htons((u_short)pcmd->argval[1].uval); 2491 1.1 kardel if (pcmd->nargs > 2) { 2492 1.1 kardel if (AF(&pcmd->argval[2].netnum) != 2493 1.1 kardel AF(&pcmd->argval[0].netnum)) { 2494 1.1 kardel fprintf(stderr, 2495 1.1 kardel "***Cannot mix IPv4 and IPv6 addresses\n"); 2496 1.1 kardel return; 2497 1.1 kardel } 2498 1.1 kardel if (IS_IPV4(&pcmd->argval[2].netnum)) 2499 1.1 kardel ctrap.local_address = NSRCADR(&pcmd->argval[2].netnum); 2500 1.1 kardel else 2501 1.1 kardel ctrap.local_address6 = SOCK_ADDR6(&pcmd->argval[2].netnum); 2502 1.1 kardel } 2503 1.1 kardel } 2504 1.1 kardel 2505 1.1 kardel res = doquery(impl_ver, req, 1, 1, sendsize, 2506 1.11 christos (char *)&ctrap, &items, &itemsize, &dummy, 0, 2507 1.1 kardel sizeof(struct conf_trap)); 2508 1.11 christos 2509 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2510 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 2511 1.1 kardel goto again; 2512 1.1 kardel } 2513 1.1 kardel 2514 1.1 kardel if (res == 0) 2515 1.1 kardel (void) fprintf(fp, "done!\n"); 2516 1.1 kardel return; 2517 1.1 kardel } 2518 1.1 kardel 2519 1.1 kardel 2520 1.1 kardel 2521 1.1 kardel /* 2522 1.1 kardel * requestkey - change the server's request key (a dangerous request) 2523 1.1 kardel */ 2524 1.1 kardel static void 2525 1.1 kardel requestkey( 2526 1.1 kardel struct parse *pcmd, 2527 1.1 kardel FILE *fp 2528 1.1 kardel ) 2529 1.1 kardel { 2530 1.1 kardel do_changekey(pcmd, fp, REQ_REQUEST_KEY); 2531 1.1 kardel } 2532 1.1 kardel 2533 1.1 kardel 2534 1.1 kardel /* 2535 1.1 kardel * controlkey - change the server's control key 2536 1.1 kardel */ 2537 1.1 kardel static void 2538 1.1 kardel controlkey( 2539 1.1 kardel struct parse *pcmd, 2540 1.1 kardel FILE *fp 2541 1.1 kardel ) 2542 1.1 kardel { 2543 1.1 kardel do_changekey(pcmd, fp, REQ_CONTROL_KEY); 2544 1.1 kardel } 2545 1.1 kardel 2546 1.1 kardel 2547 1.1 kardel 2548 1.1 kardel /* 2549 1.1 kardel * do_changekey - do grunge work of changing keys 2550 1.1 kardel */ 2551 1.1 kardel static void 2552 1.1 kardel do_changekey( 2553 1.1 kardel struct parse *pcmd, 2554 1.1 kardel FILE *fp, 2555 1.1 kardel int req 2556 1.1 kardel ) 2557 1.1 kardel { 2558 1.1 kardel u_long key; 2559 1.8 christos size_t items; 2560 1.8 christos size_t itemsize; 2561 1.8 christos const char *dummy; 2562 1.1 kardel int res; 2563 1.1 kardel 2564 1.1 kardel 2565 1.1 kardel key = htonl((u_int32)pcmd->argval[0].uval); 2566 1.1 kardel 2567 1.1 kardel again: 2568 1.1 kardel res = doquery(impl_ver, req, 1, 1, sizeof(u_int32), 2569 1.11 christos (char *)&key, &items, &itemsize, &dummy, 0, 2570 1.1 kardel sizeof(dummy)); 2571 1.11 christos 2572 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2573 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 2574 1.1 kardel goto again; 2575 1.1 kardel } 2576 1.1 kardel 2577 1.1 kardel if (res == 0) 2578 1.1 kardel (void) fprintf(fp, "done!\n"); 2579 1.1 kardel return; 2580 1.1 kardel } 2581 1.1 kardel 2582 1.1 kardel 2583 1.1 kardel 2584 1.1 kardel /* 2585 1.1 kardel * ctlstats - obtain and print info about authentication 2586 1.1 kardel */ 2587 1.1 kardel /*ARGSUSED*/ 2588 1.1 kardel static void 2589 1.1 kardel ctlstats( 2590 1.1 kardel struct parse *pcmd, 2591 1.1 kardel FILE *fp 2592 1.1 kardel ) 2593 1.1 kardel { 2594 1.1 kardel struct info_control *ic; 2595 1.8 christos size_t items; 2596 1.8 christos size_t itemsize; 2597 1.1 kardel int res; 2598 1.1 kardel 2599 1.1 kardel again: 2600 1.3 kardel res = doquery(impl_ver, REQ_GET_CTLSTATS, 0, 0, 0, NULL, &items, 2601 1.3 kardel &itemsize, (void *)&ic, 0, sizeof(*ic)); 2602 1.11 christos 2603 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2604 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 2605 1.1 kardel goto again; 2606 1.1 kardel } 2607 1.1 kardel 2608 1.1 kardel if (res != 0) 2609 1.3 kardel return; 2610 1.1 kardel 2611 1.1 kardel if (!check1item(items, fp)) 2612 1.3 kardel return; 2613 1.1 kardel 2614 1.3 kardel if (!checkitemsize(itemsize, sizeof(*ic))) 2615 1.3 kardel return; 2616 1.1 kardel 2617 1.3 kardel fprintf(fp, "time since reset: %lu\n", 2618 1.3 kardel (u_long)ntohl(ic->ctltimereset)); 2619 1.3 kardel fprintf(fp, "requests received: %lu\n", 2620 1.3 kardel (u_long)ntohl(ic->numctlreq)); 2621 1.3 kardel fprintf(fp, "responses sent: %lu\n", 2622 1.3 kardel (u_long)ntohl(ic->numctlresponses)); 2623 1.3 kardel fprintf(fp, "fragments sent: %lu\n", 2624 1.3 kardel (u_long)ntohl(ic->numctlfrags)); 2625 1.3 kardel fprintf(fp, "async messages sent: %lu\n", 2626 1.3 kardel (u_long)ntohl(ic->numasyncmsgs)); 2627 1.3 kardel fprintf(fp, "error msgs sent: %lu\n", 2628 1.3 kardel (u_long)ntohl(ic->numctlerrors)); 2629 1.3 kardel fprintf(fp, "total bad pkts: %lu\n", 2630 1.3 kardel (u_long)ntohl(ic->numctlbadpkts)); 2631 1.3 kardel fprintf(fp, "packet too short: %lu\n", 2632 1.3 kardel (u_long)ntohl(ic->numctltooshort)); 2633 1.3 kardel fprintf(fp, "response on input: %lu\n", 2634 1.3 kardel (u_long)ntohl(ic->numctlinputresp)); 2635 1.3 kardel fprintf(fp, "fragment on input: %lu\n", 2636 1.3 kardel (u_long)ntohl(ic->numctlinputfrag)); 2637 1.3 kardel fprintf(fp, "error set on input: %lu\n", 2638 1.3 kardel (u_long)ntohl(ic->numctlinputerr)); 2639 1.3 kardel fprintf(fp, "bad offset on input: %lu\n", 2640 1.3 kardel (u_long)ntohl(ic->numctlbadoffset)); 2641 1.3 kardel fprintf(fp, "bad version packets: %lu\n", 2642 1.3 kardel (u_long)ntohl(ic->numctlbadversion)); 2643 1.3 kardel fprintf(fp, "data in pkt too short: %lu\n", 2644 1.3 kardel (u_long)ntohl(ic->numctldatatooshort)); 2645 1.3 kardel fprintf(fp, "unknown op codes: %lu\n", 2646 1.3 kardel (u_long)ntohl(ic->numctlbadop)); 2647 1.1 kardel } 2648 1.1 kardel 2649 1.1 kardel 2650 1.1 kardel /* 2651 1.1 kardel * clockstat - get and print clock status information 2652 1.1 kardel */ 2653 1.1 kardel static void 2654 1.1 kardel clockstat( 2655 1.1 kardel struct parse *pcmd, 2656 1.1 kardel FILE *fp 2657 1.1 kardel ) 2658 1.1 kardel { 2659 1.1 kardel struct info_clock *cl; 2660 1.1 kardel /* 8 is the maximum number of clocks which will fit in a packet */ 2661 1.1 kardel u_long clist[min(MAXARGS, 8)]; 2662 1.8 christos size_t qitemlim; 2663 1.8 christos size_t qitems; 2664 1.8 christos size_t items; 2665 1.8 christos size_t itemsize; 2666 1.1 kardel int res; 2667 1.1 kardel l_fp ts; 2668 1.1 kardel struct clktype *clk; 2669 1.1 kardel 2670 1.1 kardel qitemlim = min(pcmd->nargs, COUNTOF(clist)); 2671 1.1 kardel for (qitems = 0; qitems < qitemlim; qitems++) 2672 1.1 kardel clist[qitems] = NSRCADR(&pcmd->argval[qitems].netnum); 2673 1.1 kardel 2674 1.1 kardel again: 2675 1.1 kardel res = doquery(impl_ver, REQ_GET_CLOCKINFO, 0, qitems, 2676 1.1 kardel sizeof(u_int32), (char *)clist, &items, 2677 1.1 kardel &itemsize, (void *)&cl, 0, sizeof(struct info_clock)); 2678 1.11 christos 2679 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2680 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 2681 1.1 kardel goto again; 2682 1.1 kardel } 2683 1.1 kardel 2684 1.1 kardel if (res != 0) 2685 1.1 kardel return; 2686 1.1 kardel 2687 1.1 kardel if (!checkitems(items, fp)) 2688 1.1 kardel return; 2689 1.1 kardel 2690 1.1 kardel if (!checkitemsize(itemsize, sizeof(struct info_clock))) 2691 1.1 kardel return; 2692 1.1 kardel 2693 1.1 kardel while (items-- > 0) { 2694 1.1 kardel (void) fprintf(fp, "clock address: %s\n", 2695 1.1 kardel numtoa(cl->clockadr)); 2696 1.1 kardel for (clk = clktypes; clk->code >= 0; clk++) 2697 1.1 kardel if (clk->code == cl->type) 2698 1.1 kardel break; 2699 1.1 kardel if (clk->code >= 0) 2700 1.1 kardel (void) fprintf(fp, "clock type: %s\n", 2701 1.1 kardel clk->clocktype); 2702 1.1 kardel else 2703 1.1 kardel (void) fprintf(fp, "clock type: unknown type (%d)\n", 2704 1.1 kardel cl->type); 2705 1.1 kardel (void) fprintf(fp, "last event: %d\n", 2706 1.1 kardel cl->lastevent); 2707 1.1 kardel (void) fprintf(fp, "current status: %d\n", 2708 1.1 kardel cl->currentstatus); 2709 1.1 kardel (void) fprintf(fp, "number of polls: %lu\n", 2710 1.1 kardel (u_long)ntohl(cl->polls)); 2711 1.1 kardel (void) fprintf(fp, "no response to poll: %lu\n", 2712 1.1 kardel (u_long)ntohl(cl->noresponse)); 2713 1.1 kardel (void) fprintf(fp, "bad format responses: %lu\n", 2714 1.1 kardel (u_long)ntohl(cl->badformat)); 2715 1.1 kardel (void) fprintf(fp, "bad data responses: %lu\n", 2716 1.1 kardel (u_long)ntohl(cl->baddata)); 2717 1.1 kardel (void) fprintf(fp, "running time: %lu\n", 2718 1.1 kardel (u_long)ntohl(cl->timestarted)); 2719 1.1 kardel NTOHL_FP(&cl->fudgetime1, &ts); 2720 1.1 kardel (void) fprintf(fp, "fudge time 1: %s\n", 2721 1.1 kardel lfptoa(&ts, 6)); 2722 1.1 kardel NTOHL_FP(&cl->fudgetime2, &ts); 2723 1.1 kardel (void) fprintf(fp, "fudge time 2: %s\n", 2724 1.1 kardel lfptoa(&ts, 6)); 2725 1.1 kardel (void) fprintf(fp, "stratum: %ld\n", 2726 1.1 kardel (u_long)ntohl(cl->fudgeval1)); 2727 1.11 christos /* [Bug3527] Backward Incompatible: cl->fudgeval2 is 2728 1.11 christos * a string, instantiated via memcpy() so there is no 2729 1.11 christos * endian issue to correct. 2730 1.11 christos */ 2731 1.11 christos #ifdef DISABLE_BUG3527_FIX 2732 1.1 kardel (void) fprintf(fp, "reference ID: %s\n", 2733 1.1 kardel refid_string(ntohl(cl->fudgeval2), 0)); 2734 1.11 christos #else 2735 1.11 christos (void) fprintf(fp, "reference ID: %s\n", 2736 1.11 christos refid_string(cl->fudgeval2, 0)); 2737 1.11 christos #endif 2738 1.1 kardel (void) fprintf(fp, "fudge flags: 0x%x\n", 2739 1.1 kardel cl->flags); 2740 1.1 kardel 2741 1.1 kardel if (items > 0) 2742 1.1 kardel (void) fprintf(fp, "\n"); 2743 1.1 kardel cl++; 2744 1.1 kardel } 2745 1.1 kardel } 2746 1.1 kardel 2747 1.1 kardel 2748 1.1 kardel /* 2749 1.1 kardel * fudge - set clock fudge factors 2750 1.1 kardel */ 2751 1.1 kardel static void 2752 1.1 kardel fudge( 2753 1.1 kardel struct parse *pcmd, 2754 1.1 kardel FILE *fp 2755 1.1 kardel ) 2756 1.1 kardel { 2757 1.1 kardel struct conf_fudge fudgedata; 2758 1.8 christos size_t items; 2759 1.8 christos size_t itemsize; 2760 1.8 christos const char *dummy; 2761 1.1 kardel l_fp ts; 2762 1.1 kardel int res; 2763 1.1 kardel long val; 2764 1.1 kardel u_long u_val; 2765 1.1 kardel int err; 2766 1.1 kardel 2767 1.1 kardel 2768 1.1 kardel err = 0; 2769 1.4 christos ZERO(fudgedata); 2770 1.1 kardel fudgedata.clockadr = NSRCADR(&pcmd->argval[0].netnum); 2771 1.1 kardel 2772 1.1 kardel if (STREQ(pcmd->argval[1].string, "time1")) { 2773 1.1 kardel fudgedata.which = htonl(FUDGE_TIME1); 2774 1.1 kardel if (!atolfp(pcmd->argval[2].string, &ts)) 2775 1.1 kardel err = 1; 2776 1.1 kardel else 2777 1.1 kardel NTOHL_FP(&ts, &fudgedata.fudgetime); 2778 1.1 kardel } else if (STREQ(pcmd->argval[1].string, "time2")) { 2779 1.1 kardel fudgedata.which = htonl(FUDGE_TIME2); 2780 1.1 kardel if (!atolfp(pcmd->argval[2].string, &ts)) 2781 1.1 kardel err = 1; 2782 1.1 kardel else 2783 1.1 kardel NTOHL_FP(&ts, &fudgedata.fudgetime); 2784 1.1 kardel } else if (STREQ(pcmd->argval[1].string, "val1")) { 2785 1.1 kardel fudgedata.which = htonl(FUDGE_VAL1); 2786 1.1 kardel if (!atoint(pcmd->argval[2].string, &val)) 2787 1.1 kardel err = 1; 2788 1.1 kardel else 2789 1.1 kardel fudgedata.fudgeval_flags = htonl(val); 2790 1.1 kardel } else if (STREQ(pcmd->argval[1].string, "val2")) { 2791 1.1 kardel fudgedata.which = htonl(FUDGE_VAL2); 2792 1.1 kardel if (!atoint(pcmd->argval[2].string, &val)) 2793 1.1 kardel err = 1; 2794 1.1 kardel else 2795 1.1 kardel fudgedata.fudgeval_flags = htonl((u_int32)val); 2796 1.1 kardel } else if (STREQ(pcmd->argval[1].string, "flags")) { 2797 1.1 kardel fudgedata.which = htonl(FUDGE_FLAGS); 2798 1.1 kardel if (!hextoint(pcmd->argval[2].string, &u_val)) 2799 1.1 kardel err = 1; 2800 1.1 kardel else 2801 1.1 kardel fudgedata.fudgeval_flags = htonl((u_int32)(u_val & 0xf)); 2802 1.1 kardel } else { 2803 1.1 kardel (void) fprintf(stderr, "What fudge is %s?\n", 2804 1.1 kardel pcmd->argval[1].string); 2805 1.1 kardel return; 2806 1.1 kardel } 2807 1.1 kardel 2808 1.1 kardel if (err) { 2809 1.1 kardel (void) fprintf(stderr, "Unknown fudge parameter %s\n", 2810 1.1 kardel pcmd->argval[2].string); 2811 1.1 kardel return; 2812 1.1 kardel } 2813 1.1 kardel 2814 1.1 kardel again: 2815 1.1 kardel res = doquery(impl_ver, REQ_SET_CLKFUDGE, 1, 1, 2816 1.1 kardel sizeof(struct conf_fudge), (char *)&fudgedata, &items, 2817 1.1 kardel &itemsize, &dummy, 0, sizeof(dummy)); 2818 1.1 kardel 2819 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2820 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 2821 1.1 kardel goto again; 2822 1.1 kardel } 2823 1.1 kardel 2824 1.1 kardel if (res == 0) 2825 1.1 kardel (void) fprintf(fp, "done!\n"); 2826 1.1 kardel return; 2827 1.1 kardel } 2828 1.1 kardel 2829 1.1 kardel /* 2830 1.1 kardel * clkbug - get and print clock debugging information 2831 1.1 kardel */ 2832 1.1 kardel static void 2833 1.1 kardel clkbug( 2834 1.1 kardel struct parse *pcmd, 2835 1.1 kardel FILE *fp 2836 1.1 kardel ) 2837 1.1 kardel { 2838 1.1 kardel register int i; 2839 1.1 kardel register int n; 2840 1.1 kardel register u_int32 s; 2841 1.1 kardel struct info_clkbug *cl; 2842 1.1 kardel /* 8 is the maximum number of clocks which will fit in a packet */ 2843 1.1 kardel u_long clist[min(MAXARGS, 8)]; 2844 1.1 kardel u_int32 ltemp; 2845 1.8 christos size_t qitemlim; 2846 1.8 christos size_t qitems; 2847 1.8 christos size_t items; 2848 1.8 christos size_t itemsize; 2849 1.1 kardel int res; 2850 1.1 kardel int needsp; 2851 1.1 kardel l_fp ts; 2852 1.1 kardel 2853 1.1 kardel qitemlim = min(pcmd->nargs, COUNTOF(clist)); 2854 1.1 kardel for (qitems = 0; qitems < qitemlim; qitems++) 2855 1.1 kardel clist[qitems] = NSRCADR(&pcmd->argval[qitems].netnum); 2856 1.1 kardel 2857 1.1 kardel again: 2858 1.1 kardel res = doquery(impl_ver, REQ_GET_CLKBUGINFO, 0, qitems, 2859 1.1 kardel sizeof(u_int32), (char *)clist, &items, 2860 1.1 kardel &itemsize, (void *)&cl, 0, sizeof(struct info_clkbug)); 2861 1.11 christos 2862 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2863 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 2864 1.1 kardel goto again; 2865 1.1 kardel } 2866 1.1 kardel 2867 1.1 kardel if (res != 0) 2868 1.1 kardel return; 2869 1.1 kardel 2870 1.1 kardel if (!checkitems(items, fp)) 2871 1.1 kardel return; 2872 1.1 kardel 2873 1.1 kardel if (!checkitemsize(itemsize, sizeof(struct info_clkbug))) 2874 1.1 kardel return; 2875 1.1 kardel 2876 1.1 kardel while (items-- > 0) { 2877 1.1 kardel (void) fprintf(fp, "clock address: %s\n", 2878 1.1 kardel numtoa(cl->clockadr)); 2879 1.1 kardel n = (int)cl->nvalues; 2880 1.1 kardel (void) fprintf(fp, "values: %d", n); 2881 1.1 kardel s = ntohs(cl->svalues); 2882 1.1 kardel if (n > NUMCBUGVALUES) 2883 1.1 kardel n = NUMCBUGVALUES; 2884 1.1 kardel for (i = 0; i < n; i++) { 2885 1.1 kardel ltemp = ntohl(cl->values[i]); 2886 1.1 kardel ltemp &= 0xffffffff; /* HMS: This does nothing now */ 2887 1.1 kardel if ((i & 0x3) == 0) 2888 1.1 kardel (void) fprintf(fp, "\n"); 2889 1.1 kardel if (s & (1 << i)) 2890 1.1 kardel (void) fprintf(fp, "%12ld", (u_long)ltemp); 2891 1.1 kardel else 2892 1.1 kardel (void) fprintf(fp, "%12lu", (u_long)ltemp); 2893 1.1 kardel } 2894 1.1 kardel (void) fprintf(fp, "\n"); 2895 1.1 kardel 2896 1.1 kardel n = (int)cl->ntimes; 2897 1.1 kardel (void) fprintf(fp, "times: %d", n); 2898 1.1 kardel s = ntohl(cl->stimes); 2899 1.1 kardel if (n > NUMCBUGTIMES) 2900 1.1 kardel n = NUMCBUGTIMES; 2901 1.1 kardel needsp = 0; 2902 1.1 kardel for (i = 0; i < n; i++) { 2903 1.1 kardel if ((i & 0x1) == 0) { 2904 1.1 kardel (void) fprintf(fp, "\n"); 2905 1.1 kardel } else { 2906 1.1 kardel for (;needsp > 0; needsp--) 2907 1.1 kardel putc(' ', fp); 2908 1.1 kardel } 2909 1.1 kardel NTOHL_FP(&cl->times[i], &ts); 2910 1.1 kardel if (s & (1 << i)) { 2911 1.1 kardel (void) fprintf(fp, "%17s", 2912 1.1 kardel lfptoa(&ts, 6)); 2913 1.1 kardel needsp = 22; 2914 1.1 kardel } else { 2915 1.1 kardel (void) fprintf(fp, "%37s", 2916 1.1 kardel uglydate(&ts)); 2917 1.1 kardel needsp = 2; 2918 1.1 kardel } 2919 1.1 kardel } 2920 1.1 kardel (void) fprintf(fp, "\n"); 2921 1.1 kardel if (items > 0) { 2922 1.1 kardel cl++; 2923 1.1 kardel (void) fprintf(fp, "\n"); 2924 1.1 kardel } 2925 1.1 kardel } 2926 1.1 kardel } 2927 1.1 kardel 2928 1.1 kardel 2929 1.1 kardel /* 2930 1.1 kardel * kerninfo - display the kernel pll/pps variables 2931 1.1 kardel */ 2932 1.1 kardel static void 2933 1.1 kardel kerninfo( 2934 1.1 kardel struct parse *pcmd, 2935 1.1 kardel FILE *fp 2936 1.1 kardel ) 2937 1.1 kardel { 2938 1.1 kardel struct info_kernel *ik; 2939 1.8 christos size_t items; 2940 1.8 christos size_t itemsize; 2941 1.1 kardel int res; 2942 1.1 kardel unsigned status; 2943 1.11 christos double tscale_usec = 1e-6, tscale_unano = 1e-6; 2944 1.1 kardel 2945 1.1 kardel again: 2946 1.1 kardel res = doquery(impl_ver, REQ_GET_KERNEL, 0, 0, 0, (char *)NULL, 2947 1.11 christos &items, &itemsize, (void *)&ik, 0, 2948 1.1 kardel sizeof(struct info_kernel)); 2949 1.1 kardel 2950 1.1 kardel if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) { 2951 1.1 kardel impl_ver = IMPL_XNTPD_OLD; 2952 1.1 kardel goto again; 2953 1.1 kardel } 2954 1.1 kardel 2955 1.1 kardel if (res != 0) 2956 1.1 kardel return; 2957 1.1 kardel if (!check1item(items, fp)) 2958 1.1 kardel return; 2959 1.1 kardel if (!checkitemsize(itemsize, sizeof(struct info_kernel))) 2960 1.1 kardel return; 2961 1.1 kardel 2962 1.1 kardel status = ntohs(ik->status) & 0xffff; 2963 1.1 kardel /* 2964 1.1 kardel * pll variables. We know more than we should about the NANO bit. 2965 1.1 kardel */ 2966 1.1 kardel #ifdef STA_NANO 2967 1.1 kardel if (status & STA_NANO) 2968 1.11 christos tscale_unano = 1e-9; 2969 1.1 kardel #endif 2970 1.1 kardel (void)fprintf(fp, "pll offset: %g s\n", 2971 1.11 christos (int32)ntohl(ik->offset) * tscale_unano); 2972 1.1 kardel (void)fprintf(fp, "pll frequency: %s ppm\n", 2973 1.1 kardel fptoa((s_fp)ntohl(ik->freq), 3)); 2974 1.1 kardel (void)fprintf(fp, "maximum error: %g s\n", 2975 1.11 christos (u_long)ntohl(ik->maxerror) * tscale_usec); 2976 1.1 kardel (void)fprintf(fp, "estimated error: %g s\n", 2977 1.11 christos (u_long)ntohl(ik->esterror) * tscale_usec); 2978 1.1 kardel (void)fprintf(fp, "status: %04x ", status); 2979 1.1 kardel #ifdef STA_PLL 2980 1.1 kardel if (status & STA_PLL) (void)fprintf(fp, " pll"); 2981 1.1 kardel #endif 2982 1.1 kardel #ifdef STA_PPSFREQ 2983 1.1 kardel if (status & STA_PPSFREQ) (void)fprintf(fp, " ppsfreq"); 2984 1.1 kardel #endif 2985 1.1 kardel #ifdef STA_PPSTIME 2986 1.1 kardel if (status & STA_PPSTIME) (void)fprintf(fp, " ppstime"); 2987 1.1 kardel #endif 2988 1.1 kardel #ifdef STA_FLL 2989 1.1 kardel if (status & STA_FLL) (void)fprintf(fp, " fll"); 2990 1.1 kardel #endif 2991 1.1 kardel #ifdef STA_INS 2992 1.1 kardel if (status & STA_INS) (void)fprintf(fp, " ins"); 2993 1.1 kardel #endif 2994 1.1 kardel #ifdef STA_DEL 2995 1.1 kardel if (status & STA_DEL) (void)fprintf(fp, " del"); 2996 1.1 kardel #endif 2997 1.1 kardel #ifdef STA_UNSYNC 2998 1.1 kardel if (status & STA_UNSYNC) (void)fprintf(fp, " unsync"); 2999 1.1 kardel #endif 3000 1.1 kardel #ifdef STA_FREQHOLD 3001 1.1 kardel if (status & STA_FREQHOLD) (void)fprintf(fp, " freqhold"); 3002 1.1 kardel #endif 3003 1.1 kardel #ifdef STA_PPSSIGNAL 3004 1.1 kardel if (status & STA_PPSSIGNAL) (void)fprintf(fp, " ppssignal"); 3005 1.1 kardel #endif 3006 1.1 kardel #ifdef STA_PPSJITTER 3007 1.1 kardel if (status & STA_PPSJITTER) (void)fprintf(fp, " ppsjitter"); 3008 1.1 kardel #endif 3009 1.1 kardel #ifdef STA_PPSWANDER 3010 1.1 kardel if (status & STA_PPSWANDER) (void)fprintf(fp, " ppswander"); 3011 1.1 kardel #endif 3012 1.1 kardel #ifdef STA_PPSERROR 3013 1.1 kardel if (status & STA_PPSERROR) (void)fprintf(fp, " ppserror"); 3014 1.1 kardel #endif 3015 1.1 kardel #ifdef STA_CLOCKERR 3016 1.1 kardel if (status & STA_CLOCKERR) (void)fprintf(fp, " clockerr"); 3017 1.1 kardel #endif 3018 1.1 kardel #ifdef STA_NANO 3019 1.1 kardel if (status & STA_NANO) (void)fprintf(fp, " nano"); 3020 1.1 kardel #endif 3021 1.1 kardel #ifdef STA_MODE 3022 1.1 kardel if (status & STA_MODE) (void)fprintf(fp, " mode=fll"); 3023 1.1 kardel #endif 3024 1.1 kardel #ifdef STA_CLK 3025 1.1 kardel if (status & STA_CLK) (void)fprintf(fp, " src=B"); 3026 1.1 kardel #endif 3027 1.1 kardel (void)fprintf(fp, "\n"); 3028 1.1 kardel (void)fprintf(fp, "pll time constant: %ld\n", 3029 1.1 kardel (u_long)ntohl(ik->constant)); 3030 1.1 kardel (void)fprintf(fp, "precision: %g s\n", 3031 1.11 christos (u_long)ntohl(ik->precision) * tscale_usec); 3032 1.1 kardel (void)fprintf(fp, "frequency tolerance: %s ppm\n", 3033 1.1 kardel fptoa((s_fp)ntohl(ik->tolerance), 0)); 3034 1.1 kardel 3035 1.1 kardel /* 3036 1.1 kardel * For backwards compatibility (ugh), we find the pps variables 3037 1.1 kardel * only if the shift member is nonzero. 3038 1.1 kardel */ 3039 1.1 kardel if (!ik->shift) 3040 1.1 kardel return; 3041 1.1 kardel 3042 1.1 kardel /* 3043 1.1 kardel * pps variables 3044 1.1 kardel */ 3045 1.1 kardel (void)fprintf(fp, "pps frequency: %s ppm\n", 3046 1.1 kardel fptoa((s_fp)ntohl(ik->ppsfreq), 3)); 3047 1.1 kardel (void)fprintf(fp, "pps stability: %s ppm\n", 3048 1.1 kardel fptoa((s_fp)ntohl(ik->stabil), 3)); 3049 1.1 kardel (void)fprintf(fp, "pps jitter: %g s\n", 3050 1.11 christos (u_long)ntohl(ik->jitter) * tscale_unano); 3051 1.1 kardel (void)fprintf(fp, "calibration interval: %d s\n", 3052 1.1 kardel 1 << ntohs(ik->shift)); 3053 1.1 kardel (void)fprintf(fp, "calibration cycles: %ld\n", 3054 1.1 kardel (u_long)ntohl(ik->calcnt)); 3055 1.1 kardel (void)fprintf(fp, "jitter exceeded: %ld\n", 3056 1.1 kardel (u_long)ntohl(ik->jitcnt)); 3057 1.1 kardel (void)fprintf(fp, "stability exceeded: %ld\n", 3058 1.1 kardel (u_long)ntohl(ik->stbcnt)); 3059 1.1 kardel (void)fprintf(fp, "calibration errors: %ld\n", 3060 1.1 kardel (u_long)ntohl(ik->errcnt)); 3061 1.1 kardel } 3062 1.1 kardel 3063 1.3 kardel #define IF_LIST_FMT "%2d %c %48s %c %c %12.12s %03lx %3lu %2lu %5lu %5lu %5lu %2lu %3lu %7lu\n" 3064 1.1 kardel #define IF_LIST_FMT_STR "%2s %c %48s %c %c %12.12s %3s %3s %2s %5s %5s %5s %2s %3s %7s\n" 3065 1.1 kardel #define IF_LIST_AFMT_STR " %48s %c\n" 3066 1.1 kardel #define IF_LIST_LABELS "#", 'A', "Address/Mask/Broadcast", 'T', 'E', "IF name", "Flg", "TL", "#M", "recv", "sent", "drop", "S", "PC", "uptime" 3067 1.1 kardel #define IF_LIST_LINE "==================================================================================================================\n" 3068 1.1 kardel 3069 1.1 kardel static void 3070 1.1 kardel iflist( 3071 1.1 kardel FILE *fp, 3072 1.1 kardel struct info_if_stats *ifs, 3073 1.8 christos size_t items, 3074 1.8 christos size_t itemsize, 3075 1.1 kardel int res 3076 1.1 kardel ) 3077 1.1 kardel { 3078 1.2 christos static const char *actions = "?.+-"; 3079 1.1 kardel sockaddr_u saddr; 3080 1.1 kardel 3081 1.1 kardel if (res != 0) 3082 1.1 kardel return; 3083 1.1 kardel 3084 1.1 kardel if (!checkitems(items, fp)) 3085 1.1 kardel return; 3086 1.1 kardel 3087 1.1 kardel if (!checkitemsize(itemsize, sizeof(struct info_if_stats))) 3088 1.1 kardel return; 3089 1.1 kardel 3090 1.1 kardel fprintf(fp, IF_LIST_FMT_STR, IF_LIST_LABELS); 3091 1.1 kardel fprintf(fp, IF_LIST_LINE); 3092 1.11 christos 3093 1.1 kardel while (items > 0) { 3094 1.11 christos SET_ADDR(saddr, ntohl(ifs->v6_flag), 3095 1.1 kardel ifs->unaddr.addr.s_addr, ifs->unaddr.addr6); 3096 1.1 kardel fprintf(fp, IF_LIST_FMT, 3097 1.1 kardel ntohl(ifs->ifnum), 3098 1.1 kardel actions[(ifs->action >= 1 && ifs->action < 4) ? ifs->action : 0], 3099 1.1 kardel stoa((&saddr)), 'A', 3100 1.1 kardel ifs->ignore_packets ? 'D' : 'E', 3101 1.1 kardel ifs->name, 3102 1.3 kardel (u_long)ntohl(ifs->flags), 3103 1.3 kardel (u_long)ntohl(ifs->last_ttl), 3104 1.3 kardel (u_long)ntohl(ifs->num_mcast), 3105 1.3 kardel (u_long)ntohl(ifs->received), 3106 1.3 kardel (u_long)ntohl(ifs->sent), 3107 1.3 kardel (u_long)ntohl(ifs->notsent), 3108 1.3 kardel (u_long)ntohl(ifs->scopeid), 3109 1.3 kardel (u_long)ntohl(ifs->peercnt), 3110 1.3 kardel (u_long)ntohl(ifs->uptime)); 3111 1.1 kardel 3112 1.11 christos SET_ADDR(saddr, ntohl(ifs->v6_flag), 3113 1.1 kardel ifs->unmask.addr.s_addr, ifs->unmask.addr6); 3114 1.1 kardel fprintf(fp, IF_LIST_AFMT_STR, stoa(&saddr), 'M'); 3115 1.1 kardel 3116 1.1 kardel if (!ntohl(ifs->v6_flag) && ntohl(ifs->flags) & (INT_BCASTOPEN)) { 3117 1.11 christos SET_ADDR(saddr, ntohl(ifs->v6_flag), 3118 1.1 kardel ifs->unbcast.addr.s_addr, ifs->unbcast.addr6); 3119 1.1 kardel fprintf(fp, IF_LIST_AFMT_STR, stoa(&saddr), 'B'); 3120 1.1 kardel 3121 1.1 kardel } 3122 1.1 kardel 3123 1.1 kardel ifs++; 3124 1.1 kardel items--; 3125 1.1 kardel } 3126 1.1 kardel } 3127 1.1 kardel 3128 1.1 kardel /*ARGSUSED*/ 3129 1.1 kardel static void 3130 1.1 kardel get_if_stats( 3131 1.1 kardel struct parse *pcmd, 3132 1.1 kardel FILE *fp 3133 1.1 kardel ) 3134 1.1 kardel { 3135 1.1 kardel struct info_if_stats *ifs; 3136 1.8 christos size_t items; 3137 1.8 christos size_t itemsize; 3138 1.1 kardel int res; 3139 1.1 kardel 3140 1.1 kardel res = doquery(impl_ver, REQ_IF_STATS, 1, 0, 0, (char *)NULL, &items, 3141 1.11 christos &itemsize, (void *)&ifs, 0, 3142 1.1 kardel sizeof(struct info_if_stats)); 3143 1.1 kardel iflist(fp, ifs, items, itemsize, res); 3144 1.1 kardel } 3145 1.1 kardel 3146 1.1 kardel /*ARGSUSED*/ 3147 1.1 kardel static void 3148 1.1 kardel do_if_reload( 3149 1.1 kardel struct parse *pcmd, 3150 1.1 kardel FILE *fp 3151 1.1 kardel ) 3152 1.1 kardel { 3153 1.1 kardel struct info_if_stats *ifs; 3154 1.8 christos size_t items; 3155 1.8 christos size_t itemsize; 3156 1.1 kardel int res; 3157 1.1 kardel 3158 1.1 kardel res = doquery(impl_ver, REQ_IF_RELOAD, 1, 0, 0, (char *)NULL, &items, 3159 1.11 christos &itemsize, (void *)&ifs, 0, 3160 1.1 kardel sizeof(struct info_if_stats)); 3161 1.1 kardel iflist(fp, ifs, items, itemsize, res); 3162 1.1 kardel } 3163