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