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