/contrib/ntp/ntpdc/ntpdc_ops.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 3204 lines · 2646 code · 348 blank · 210 comment · 641 complexity · 33377576bde5c816cdfcd6b3cbb75390 MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. * ntpdc_ops.c - subroutines which are called to perform operations by xntpdc
  3. */
  4. #ifdef HAVE_CONFIG_H
  5. # include <config.h>
  6. #endif
  7. #include <stdio.h>
  8. #include <stddef.h>
  9. #include "ntpdc.h"
  10. #include "ntp_control.h"
  11. #include "ntp_refclock.h"
  12. #include "ntp_stdlib.h"
  13. #include <ctype.h>
  14. #ifdef HAVE_SYS_TIMEX_H
  15. # include <sys/timex.h>
  16. #endif
  17. #if !defined(__bsdi__) && !defined(apollo)
  18. #include <netinet/in.h>
  19. #endif
  20. #include <arpa/inet.h>
  21. /*
  22. * Declarations for command handlers in here
  23. */
  24. static int checkitems P((int, FILE *));
  25. static int checkitemsize P((int, int));
  26. static int check1item P((int, FILE *));
  27. static void peerlist P((struct parse *, FILE *));
  28. static void peers P((struct parse *, FILE *));
  29. static void doconfig P((struct parse *pcmd, FILE *fp, int mode, int refc));
  30. static void dmpeers P((struct parse *, FILE *));
  31. static void dopeers P((struct parse *, FILE *, int));
  32. static void printpeer P((struct info_peer *, FILE *));
  33. static void showpeer P((struct parse *, FILE *));
  34. static void peerstats P((struct parse *, FILE *));
  35. static void loopinfo P((struct parse *, FILE *));
  36. static void sysinfo P((struct parse *, FILE *));
  37. static void sysstats P((struct parse *, FILE *));
  38. static void iostats P((struct parse *, FILE *));
  39. static void memstats P((struct parse *, FILE *));
  40. static void timerstats P((struct parse *, FILE *));
  41. static void addpeer P((struct parse *, FILE *));
  42. static void addserver P((struct parse *, FILE *));
  43. static void addrefclock P((struct parse *, FILE *));
  44. static void broadcast P((struct parse *, FILE *));
  45. static void doconfig P((struct parse *, FILE *, int, int));
  46. static void unconfig P((struct parse *, FILE *));
  47. static void set P((struct parse *, FILE *));
  48. static void sys_clear P((struct parse *, FILE *));
  49. static void doset P((struct parse *, FILE *, int));
  50. static void reslist P((struct parse *, FILE *));
  51. static void new_restrict P((struct parse *, FILE *));
  52. static void unrestrict P((struct parse *, FILE *));
  53. static void delrestrict P((struct parse *, FILE *));
  54. static void do_restrict P((struct parse *, FILE *, int));
  55. static void monlist P((struct parse *, FILE *));
  56. static void reset P((struct parse *, FILE *));
  57. static void preset P((struct parse *, FILE *));
  58. static void readkeys P((struct parse *, FILE *));
  59. static void trustkey P((struct parse *, FILE *));
  60. static void untrustkey P((struct parse *, FILE *));
  61. static void do_trustkey P((struct parse *, FILE *, int));
  62. static void authinfo P((struct parse *, FILE *));
  63. static void traps P((struct parse *, FILE *));
  64. static void addtrap P((struct parse *, FILE *));
  65. static void clrtrap P((struct parse *, FILE *));
  66. static void do_addclr_trap P((struct parse *, FILE *, int));
  67. static void requestkey P((struct parse *, FILE *));
  68. static void controlkey P((struct parse *, FILE *));
  69. static void do_changekey P((struct parse *, FILE *, int));
  70. static void ctlstats P((struct parse *, FILE *));
  71. static void clockstat P((struct parse *, FILE *));
  72. static void fudge P((struct parse *, FILE *));
  73. static void clkbug P((struct parse *, FILE *));
  74. static void kerninfo P((struct parse *, FILE *));
  75. static void get_if_stats P((struct parse *, FILE *));
  76. static void do_if_reload P((struct parse *, FILE *));
  77. /*
  78. * Commands we understand. Ntpdc imports this.
  79. */
  80. struct xcmd opcmds[] = {
  81. { "listpeers", peerlist, { OPT|IP_VERSION, NO, NO, NO },
  82. { "-4|-6", "", "", "" },
  83. "display list of peers the server knows about [IP Version]" },
  84. { "peers", peers, { OPT|IP_VERSION, NO, NO, NO },
  85. { "-4|-6", "", "", "" },
  86. "display peer summary information [IP Version]" },
  87. { "dmpeers", dmpeers, { OPT|IP_VERSION, NO, NO, NO },
  88. { "-4|-6", "", "", "" },
  89. "display peer summary info the way Dave Mills likes it (IP Version)" },
  90. { "showpeer", showpeer, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD},
  91. { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
  92. "display detailed information for one or more peers" },
  93. { "pstats", peerstats, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
  94. { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
  95. "display statistical information for one or more peers" },
  96. { "loopinfo", loopinfo, { OPT|NTP_STR, NO, NO, NO },
  97. { "oneline|multiline", "", "", "" },
  98. "display loop filter information" },
  99. { "sysinfo", sysinfo, { NO, NO, NO, NO },
  100. { "", "", "", "" },
  101. "display local server information" },
  102. { "sysstats", sysstats, { NO, NO, NO, NO },
  103. { "", "", "", "" },
  104. "display local server statistics" },
  105. { "memstats", memstats, { NO, NO, NO, NO },
  106. { "", "", "", "" },
  107. "display peer memory usage statistics" },
  108. { "iostats", iostats, { NO, NO, NO, NO },
  109. { "", "", "", "" },
  110. "display I/O subsystem statistics" },
  111. { "timerstats", timerstats, { NO, NO, NO, NO },
  112. { "", "", "", "" },
  113. "display event timer subsystem statistics" },
  114. { "addpeer", addpeer, { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
  115. { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." },
  116. "configure a new peer association" },
  117. { "addserver", addserver, { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
  118. { "addr", "keyid", "version", "minpoll#|prefer|burst|iburst|'minpoll N'|'maxpoll N'|'keyid N'|'version N' ..." },
  119. "configure a new server" },
  120. { "addrefclock",addrefclock, { NTP_ADD, OPT|NTP_UINT, OPT|NTP_STR, OPT|NTP_STR },
  121. { "addr", "mode", "minpoll|prefer", "minpoll|prefer" },
  122. "configure a new server" },
  123. { "broadcast", broadcast, { NTP_ADD, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
  124. { "addr", "keyid", "version", "minpoll" },
  125. "configure broadcasting time service" },
  126. { "unconfig", unconfig, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
  127. { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
  128. "unconfigure existing peer assocations" },
  129. { "enable", set, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
  130. { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." },
  131. "set a system flag (auth, bclient, monitor, pll, kernel, stats)" },
  132. { "disable", sys_clear, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
  133. { "auth|bclient|monitor|pll|kernel|stats", "...", "...", "..." },
  134. "clear a system flag (auth, bclient, monitor, pll, kernel, stats)" },
  135. { "reslist", reslist, {OPT|IP_VERSION, NO, NO, NO },
  136. { "-4|-6", "", "", "" },
  137. "display the server's restrict list" },
  138. { "restrict", new_restrict, { NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR },
  139. { "address", "mask",
  140. "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod",
  141. "..." },
  142. "create restrict entry/add flags to entry" },
  143. { "unrestrict", unrestrict, { NTP_ADD, NTP_ADD, NTP_STR, OPT|NTP_STR },
  144. { "address", "mask",
  145. "ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer|version|kod",
  146. "..." },
  147. "remove flags from a restrict entry" },
  148. { "delrestrict", delrestrict, { NTP_ADD, NTP_ADD, OPT|NTP_STR, NO },
  149. { "address", "mask", "ntpport", "" },
  150. "delete a restrict entry" },
  151. { "monlist", monlist, { OPT|NTP_INT, NO, NO, NO },
  152. { "version", "", "", "" },
  153. "display data the server's monitor routines have collected" },
  154. { "reset", reset, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
  155. { "io|sys|mem|timer|auth|allpeers", "...", "...", "..." },
  156. "reset various subsystem statistics counters" },
  157. { "preset", preset, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
  158. { "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
  159. "reset stat counters associated with particular peer(s)" },
  160. { "readkeys", readkeys, { NO, NO, NO, NO },
  161. { "", "", "", "" },
  162. "request a reread of the keys file and re-init of system keys" },
  163. { "trustedkey", trustkey, { NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT },
  164. { "keyid", "keyid", "keyid", "keyid" },
  165. "add one or more key ID's to the trusted list" },
  166. { "untrustedkey", untrustkey, { NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT, OPT|NTP_UINT },
  167. { "keyid", "keyid", "keyid", "keyid" },
  168. "remove one or more key ID's from the trusted list" },
  169. { "authinfo", authinfo, { NO, NO, NO, NO },
  170. { "", "", "", "" },
  171. "display the state of the authentication code" },
  172. { "traps", traps, { NO, NO, NO, NO },
  173. { "", "", "", "" },
  174. "display the traps set in the server" },
  175. { "addtrap", addtrap, { NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO },
  176. { "address", "port", "interface", "" },
  177. "configure a trap in the server" },
  178. { "clrtrap", clrtrap, { NTP_ADD, OPT|NTP_UINT, OPT|NTP_ADD, NO },
  179. { "address", "port", "interface", "" },
  180. "remove a trap (configured or otherwise) from the server" },
  181. { "requestkey", requestkey, { NTP_UINT, NO, NO, NO },
  182. { "keyid", "", "", "" },
  183. "change the keyid the server uses to authenticate requests" },
  184. { "controlkey", controlkey, { NTP_UINT, NO, NO, NO },
  185. { "keyid", "", "", "" },
  186. "change the keyid the server uses to authenticate control messages" },
  187. { "ctlstats", ctlstats, { NO, NO, NO, NO },
  188. { "", "", "", "" },
  189. "display packet count statistics from the control module" },
  190. { "clockstat", clockstat, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
  191. { "address", "address", "address", "address" },
  192. "display clock status information" },
  193. { "fudge", fudge, { NTP_ADD, NTP_STR, NTP_STR, NO },
  194. { "address", "time1|time2|val1|val2|flags", "value", "" },
  195. "set/change one of a clock's fudge factors" },
  196. { "clkbug", clkbug, { NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD, OPT|NTP_ADD },
  197. { "address", "address", "address", "address" },
  198. "display clock debugging information" },
  199. { "kerninfo", kerninfo, { NO, NO, NO, NO },
  200. { "", "", "", "" },
  201. "display the kernel pll/pps variables" },
  202. { "ifstats", get_if_stats, { NO, NO, NO, NO },
  203. { "", "", "", "" },
  204. "list interface statistics" },
  205. { "ifreload", do_if_reload, { NO, NO, NO, NO },
  206. { "", "", "", "" },
  207. "reload interface configuration" },
  208. { 0, 0, { NO, NO, NO, NO },
  209. { "", "", "", "" }, "" }
  210. };
  211. /*
  212. * For quick string comparisons
  213. */
  214. #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
  215. /*
  216. * checkitems - utility to print a message if no items were returned
  217. */
  218. static int
  219. checkitems(
  220. int items,
  221. FILE *fp
  222. )
  223. {
  224. if (items == 0) {
  225. (void) fprintf(fp, "No data returned in response to query\n");
  226. return 0;
  227. }
  228. return 1;
  229. }
  230. /*
  231. * checkitemsize - utility to print a message if the item size is wrong
  232. */
  233. static int
  234. checkitemsize(
  235. int itemsize,
  236. int expected
  237. )
  238. {
  239. if (itemsize != expected) {
  240. (void) fprintf(stderr,
  241. "***Incorrect item size returned by remote host (%d should be %d)\n",
  242. itemsize, expected);
  243. return 0;
  244. }
  245. return 1;
  246. }
  247. /*
  248. * check1item - check to make sure we have exactly one item
  249. */
  250. static int
  251. check1item(
  252. int items,
  253. FILE *fp
  254. )
  255. {
  256. if (items == 0) {
  257. (void) fprintf(fp, "No data returned in response to query\n");
  258. return 0;
  259. }
  260. if (items > 1) {
  261. (void) fprintf(fp, "Expected one item in response, got %d\n",
  262. items);
  263. return 0;
  264. }
  265. return 1;
  266. }
  267. /*
  268. * peerlist - get a short list of peers
  269. */
  270. /*ARGSUSED*/
  271. static void
  272. peerlist(
  273. struct parse *pcmd,
  274. FILE *fp
  275. )
  276. {
  277. struct info_peer_list *plist;
  278. struct sockaddr_storage paddr;
  279. int items;
  280. int itemsize;
  281. int res;
  282. again:
  283. res = doquery(impl_ver, REQ_PEER_LIST, 0, 0, 0, (char *)NULL, &items,
  284. &itemsize, (void *)&plist, 0,
  285. sizeof(struct info_peer_list));
  286. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  287. impl_ver = IMPL_XNTPD_OLD;
  288. goto again;
  289. }
  290. if (res != 0)
  291. return;
  292. if (!checkitems(items, fp))
  293. return;
  294. if (!checkitemsize(itemsize, sizeof(struct info_peer_list)) &&
  295. !checkitemsize(itemsize, v4sizeof(struct info_peer_list)))
  296. return;
  297. while (items > 0) {
  298. memset((char *)&paddr, 0, sizeof(paddr));
  299. if (plist->v6_flag != 0) {
  300. GET_INADDR6(paddr) = plist->addr6;
  301. paddr.ss_family = AF_INET6;
  302. } else {
  303. GET_INADDR(paddr) = plist->addr;
  304. paddr.ss_family = AF_INET;
  305. }
  306. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  307. paddr.ss_len = SOCKLEN(&paddr);
  308. #endif
  309. if ((pcmd->nargs == 0) ||
  310. ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) ||
  311. ((pcmd->argval->ival == 4) && (plist->v6_flag == 0)))
  312. (void) fprintf(fp, "%-9s %s\n",
  313. modetoa(plist->hmode),
  314. nntohost(&paddr));
  315. plist++;
  316. items--;
  317. }
  318. }
  319. /*
  320. * peers - show peer summary
  321. */
  322. static void
  323. peers(
  324. struct parse *pcmd,
  325. FILE *fp
  326. )
  327. {
  328. dopeers(pcmd, fp, 0);
  329. }
  330. /*
  331. * dmpeers - show peer summary, Dave Mills style
  332. */
  333. static void
  334. dmpeers(
  335. struct parse *pcmd,
  336. FILE *fp
  337. )
  338. {
  339. dopeers(pcmd, fp, 1);
  340. }
  341. /*
  342. * peers - show peer summary
  343. */
  344. /*ARGSUSED*/
  345. static void
  346. dopeers(
  347. struct parse *pcmd,
  348. FILE *fp,
  349. int dmstyle
  350. )
  351. {
  352. struct info_peer_summary *plist;
  353. struct sockaddr_storage dstadr;
  354. struct sockaddr_storage srcadr;
  355. int items;
  356. int itemsize;
  357. int ntp_poll;
  358. int res;
  359. int c;
  360. l_fp tempts;
  361. again:
  362. res = doquery(impl_ver, REQ_PEER_LIST_SUM, 0, 0, 0, (char *)NULL,
  363. &items, &itemsize, (void *)&plist, 0,
  364. sizeof(struct info_peer_summary));
  365. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  366. impl_ver = IMPL_XNTPD_OLD;
  367. goto again;
  368. }
  369. if (res != 0)
  370. return;
  371. if (!checkitems(items, fp))
  372. return;
  373. if (!checkitemsize(itemsize, sizeof(struct info_peer_summary)) &&
  374. !checkitemsize(itemsize, v4sizeof(struct info_peer_summary)))
  375. return;
  376. (void) fprintf(fp,
  377. " remote local st poll reach delay offset disp\n");
  378. (void) fprintf(fp,
  379. "=======================================================================\n");
  380. while (items > 0) {
  381. if (!dmstyle) {
  382. if (plist->flags & INFO_FLAG_SYSPEER)
  383. c = '*';
  384. else if (plist->hmode == MODE_ACTIVE)
  385. c = '+';
  386. else if (plist->hmode == MODE_PASSIVE)
  387. c = '-';
  388. else if (plist->hmode == MODE_CLIENT)
  389. c = '=';
  390. else if (plist->hmode == MODE_BROADCAST)
  391. c = '^';
  392. else if (plist->hmode == MODE_BCLIENT)
  393. c = '~';
  394. else
  395. c = ' ';
  396. } else {
  397. if (plist->flags & INFO_FLAG_SYSPEER)
  398. c = '*';
  399. else if (plist->flags & INFO_FLAG_SHORTLIST)
  400. c = '+';
  401. else if (plist->flags & INFO_FLAG_SEL_CANDIDATE)
  402. c = '.';
  403. else
  404. c = ' ';
  405. }
  406. NTOHL_FP(&(plist->offset), &tempts);
  407. ntp_poll = 1<<max(min3(plist->ppoll, plist->hpoll, NTP_MAXPOLL),
  408. NTP_MINPOLL);
  409. memset((char *)&dstadr, 0, sizeof(dstadr));
  410. memset((char *)&srcadr, 0, sizeof(srcadr));
  411. if (plist->v6_flag != 0) {
  412. GET_INADDR6(dstadr) = plist->dstadr6;
  413. GET_INADDR6(srcadr) = plist->srcadr6;
  414. srcadr.ss_family = AF_INET6;
  415. dstadr.ss_family = AF_INET6;
  416. } else {
  417. GET_INADDR(dstadr) = plist->dstadr;
  418. GET_INADDR(srcadr) = plist->srcadr;
  419. srcadr.ss_family = AF_INET;
  420. dstadr.ss_family = AF_INET;
  421. }
  422. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  423. srcadr.ss_len = SOCKLEN(&srcadr);
  424. dstadr.ss_len = SOCKLEN(&dstadr);
  425. #endif
  426. if ((pcmd->nargs == 0) ||
  427. ((pcmd->argval->ival == 6) && (plist->v6_flag != 0)) ||
  428. ((pcmd->argval->ival == 4) && (plist->v6_flag == 0)))
  429. (void) fprintf(fp,
  430. "%c%-15.15s %-15.15s %2d %4d %3o %7.7s %9.9s %7.7s\n",
  431. c, nntohost(&srcadr), stoa(&dstadr),
  432. plist->stratum, ntp_poll, plist->reach,
  433. fptoa(NTOHS_FP(plist->delay), 5),
  434. lfptoa(&tempts, 6),
  435. ufptoa(NTOHS_FP(plist->dispersion), 5));
  436. plist++;
  437. items--;
  438. }
  439. }
  440. /* Convert a refid & stratum (in host order) to a string */
  441. static char*
  442. refid_string(
  443. u_int32 refid,
  444. int stratum
  445. )
  446. {
  447. if (stratum <= 1) {
  448. static char junk[5];
  449. junk[4] = 0;
  450. memmove(junk, (char *)&refid, 4);
  451. return junk;
  452. }
  453. return numtoa(refid);
  454. }
  455. static void
  456. print_pflag(
  457. FILE *fp,
  458. u_int32 flags
  459. )
  460. {
  461. const char *str;
  462. if (flags == 0) {
  463. (void) fprintf(fp, " none\n");
  464. } else {
  465. str = "";
  466. if (flags & INFO_FLAG_SYSPEER) {
  467. (void) fprintf(fp, " system_peer");
  468. str = ",";
  469. }
  470. if (flags & INFO_FLAG_CONFIG) {
  471. (void) fprintf(fp, "%s config", str);
  472. str = ",";
  473. }
  474. if (flags & INFO_FLAG_REFCLOCK) {
  475. (void) fprintf(fp, "%s refclock", str);
  476. str = ",";
  477. }
  478. if (flags & INFO_FLAG_AUTHENABLE) {
  479. (void) fprintf(fp, "%s auth", str);
  480. str = ",";
  481. }
  482. if (flags & INFO_FLAG_BCLIENT) {
  483. (void) fprintf(fp, "%s bclient", str);
  484. str = ",";
  485. }
  486. if (flags & INFO_FLAG_PREFER) {
  487. (void) fprintf(fp, "%s prefer", str);
  488. str = ",";
  489. }
  490. if (flags & INFO_FLAG_IBURST) {
  491. (void) fprintf(fp, "%s iburst", str);
  492. str = ",";
  493. }
  494. if (flags & INFO_FLAG_BURST) {
  495. (void) fprintf(fp, "%s burst", str);
  496. }
  497. (void) fprintf(fp, "\n");
  498. }
  499. }
  500. /*
  501. * printpeer - print detail information for a peer
  502. */
  503. static void
  504. printpeer(
  505. register struct info_peer *pp,
  506. FILE *fp
  507. )
  508. {
  509. register int i;
  510. l_fp tempts;
  511. struct sockaddr_storage srcadr, dstadr;
  512. memset((char *)&srcadr, 0, sizeof(srcadr));
  513. memset((char *)&dstadr, 0, sizeof(dstadr));
  514. if (pp->v6_flag != 0) {
  515. srcadr.ss_family = AF_INET6;
  516. dstadr.ss_family = AF_INET6;
  517. GET_INADDR6(srcadr) = pp->srcadr6;
  518. GET_INADDR6(dstadr) = pp->dstadr6;
  519. } else {
  520. srcadr.ss_family = AF_INET;
  521. dstadr.ss_family = AF_INET;
  522. GET_INADDR(srcadr) = pp->srcadr;
  523. GET_INADDR(dstadr) = pp->dstadr;
  524. }
  525. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  526. srcadr.ss_len = SOCKLEN(&srcadr);
  527. dstadr.ss_len = SOCKLEN(&dstadr);
  528. #endif
  529. (void) fprintf(fp, "remote %s, local %s\n",
  530. stoa(&srcadr), stoa(&dstadr));
  531. (void) fprintf(fp, "hmode %s, pmode %s, stratum %d, precision %d\n",
  532. modetoa(pp->hmode), modetoa(pp->pmode),
  533. pp->stratum, pp->precision);
  534. (void) fprintf(fp,
  535. "leap %c%c, refid [%s], rootdistance %s, rootdispersion %s\n",
  536. pp->leap & 0x2 ? '1' : '0',
  537. pp->leap & 0x1 ? '1' : '0',
  538. refid_string(pp->refid, pp->stratum), fptoa(NTOHS_FP(pp->rootdelay), 5),
  539. ufptoa(NTOHS_FP(pp->rootdispersion), 5));
  540. (void) fprintf(fp,
  541. "ppoll %d, hpoll %d, keyid %lu, version %d, association %u\n",
  542. pp->ppoll, pp->hpoll, (u_long)pp->keyid, pp->version, ntohs(pp->associd));
  543. (void) fprintf(fp,
  544. "reach %03o, unreach %d, flash 0x%04x, ",
  545. pp->reach, pp->unreach, pp->flash2);
  546. (void) fprintf(fp, "boffset %s, ttl/mode %d\n",
  547. fptoa(NTOHS_FP(pp->estbdelay), 5), pp->ttl);
  548. (void) fprintf(fp, "timer %lds, flags", (long)ntohl(pp->timer));
  549. print_pflag(fp, pp->flags);
  550. NTOHL_FP(&pp->reftime, &tempts);
  551. (void) fprintf(fp, "reference time: %s\n",
  552. prettydate(&tempts));
  553. NTOHL_FP(&pp->org, &tempts);
  554. (void) fprintf(fp, "originate timestamp: %s\n",
  555. prettydate(&tempts));
  556. NTOHL_FP(&pp->rec, &tempts);
  557. (void) fprintf(fp, "receive timestamp: %s\n",
  558. prettydate(&tempts));
  559. NTOHL_FP(&pp->xmt, &tempts);
  560. (void) fprintf(fp, "transmit timestamp: %s\n",
  561. prettydate(&tempts));
  562. (void) fprintf(fp, "filter delay: ");
  563. for (i = 0; i < NTP_SHIFT; i++) {
  564. (void) fprintf(fp, " %-8.8s",
  565. fptoa(NTOHS_FP(pp->filtdelay[i]), 5));
  566. if (i == (NTP_SHIFT>>1)-1)
  567. (void) fprintf(fp, "\n ");
  568. }
  569. (void) fprintf(fp, "\n");
  570. (void) fprintf(fp, "filter offset:");
  571. for (i = 0; i < NTP_SHIFT; i++) {
  572. NTOHL_FP(&pp->filtoffset[i], &tempts);
  573. (void) fprintf(fp, " %-8.8s", lfptoa(&tempts, 6));
  574. if (i == (NTP_SHIFT>>1)-1)
  575. (void) fprintf(fp, "\n ");
  576. }
  577. (void) fprintf(fp, "\n");
  578. (void) fprintf(fp, "filter order: ");
  579. for (i = 0; i < NTP_SHIFT; i++) {
  580. (void) fprintf(fp, " %-8d", pp->order[i]);
  581. if (i == (NTP_SHIFT>>1)-1)
  582. (void) fprintf(fp, "\n ");
  583. }
  584. (void) fprintf(fp, "\n");
  585. NTOHL_FP(&pp->offset, &tempts);
  586. (void) fprintf(fp,
  587. "offset %s, delay %s, error bound %s, filter error %s\n",
  588. lfptoa(&tempts, 6), fptoa(NTOHS_FP(pp->delay), 5),
  589. ufptoa(NTOHS_FP(pp->dispersion), 5),
  590. ufptoa(NTOHS_FP(pp->selectdisp), 5));
  591. }
  592. /*
  593. * showpeer - show detailed information for a peer
  594. */
  595. static void
  596. showpeer(
  597. struct parse *pcmd,
  598. FILE *fp
  599. )
  600. {
  601. struct info_peer *pp;
  602. /* 4 is the maximum number of peers which will fit in a packet */
  603. struct info_peer_list *pl, plist[min(MAXARGS, 4)];
  604. int qitems;
  605. int items;
  606. int itemsize;
  607. int res;
  608. int sendsize;
  609. again:
  610. if (impl_ver == IMPL_XNTPD)
  611. sendsize = sizeof(struct info_peer_list);
  612. else
  613. sendsize = v4sizeof(struct info_peer_list);
  614. for (qitems = 0, pl = plist; qitems < min(pcmd->nargs, 4); qitems++) {
  615. if (pcmd->argval[qitems].netnum.ss_family == AF_INET) {
  616. pl->addr = GET_INADDR(pcmd->argval[qitems].netnum);
  617. if (impl_ver == IMPL_XNTPD)
  618. pl->v6_flag = 0;
  619. } else {
  620. if (impl_ver == IMPL_XNTPD_OLD) {
  621. fprintf(stderr,
  622. "***Server doesn't understand IPv6 addresses\n");
  623. return;
  624. }
  625. pl->addr6 = GET_INADDR6(pcmd->argval[qitems].netnum);
  626. pl->v6_flag = 1;
  627. }
  628. pl->port = (u_short)s_port;
  629. pl->hmode = pl->flags = 0;
  630. pl = (struct info_peer_list *)((char *)pl + sendsize);
  631. }
  632. res = doquery(impl_ver, REQ_PEER_INFO, 0, qitems,
  633. sendsize, (char *)plist, &items,
  634. &itemsize, (void *)&pp, 0, sizeof(struct info_peer));
  635. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  636. impl_ver = IMPL_XNTPD_OLD;
  637. goto again;
  638. }
  639. if (res != 0)
  640. return;
  641. if (!checkitems(items, fp))
  642. return;
  643. if (!checkitemsize(itemsize, sizeof(struct info_peer)) &&
  644. !checkitemsize(itemsize, v4sizeof(struct info_peer)))
  645. return;
  646. while (items-- > 0) {
  647. printpeer(pp, fp);
  648. if (items > 0)
  649. (void) fprintf(fp, "\n");
  650. pp++;
  651. }
  652. }
  653. /*
  654. * peerstats - return statistics for a peer
  655. */
  656. static void
  657. peerstats(
  658. struct parse *pcmd,
  659. FILE *fp
  660. )
  661. {
  662. struct info_peer_stats *pp;
  663. /* 4 is the maximum number of peers which will fit in a packet */
  664. struct info_peer_list *pl, plist[min(MAXARGS, 4)];
  665. struct sockaddr_storage src, dst;
  666. int qitems;
  667. int items;
  668. int itemsize;
  669. int res;
  670. int sendsize;
  671. again:
  672. if (impl_ver == IMPL_XNTPD)
  673. sendsize = sizeof(struct info_peer_list);
  674. else
  675. sendsize = v4sizeof(struct info_peer_list);
  676. memset((char *)plist, 0, sizeof(struct info_peer_list) * min(MAXARGS, 4));
  677. for (qitems = 0, pl = plist; qitems < min(pcmd->nargs, 4); qitems++) {
  678. if (pcmd->argval[qitems].netnum.ss_family == AF_INET) {
  679. pl->addr = GET_INADDR(pcmd->argval[qitems].netnum);
  680. if (impl_ver == IMPL_XNTPD)
  681. pl->v6_flag = 0;
  682. } else {
  683. if (impl_ver == IMPL_XNTPD_OLD) {
  684. fprintf(stderr,
  685. "***Server doesn't understand IPv6 addresses\n");
  686. return;
  687. }
  688. pl->addr6 = GET_INADDR6(pcmd->argval[qitems].netnum);
  689. pl->v6_flag = 1;
  690. }
  691. pl->port = (u_short)s_port;
  692. pl->hmode = plist[qitems].flags = 0;
  693. pl = (struct info_peer_list *)((char *)pl + sendsize);
  694. }
  695. res = doquery(impl_ver, REQ_PEER_STATS, 0, qitems,
  696. sendsize, (char *)plist, &items,
  697. &itemsize, (void *)&pp, 0,
  698. sizeof(struct info_peer_stats));
  699. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  700. impl_ver = IMPL_XNTPD_OLD;
  701. goto again;
  702. }
  703. if (res != 0)
  704. return;
  705. if (!checkitems(items, fp))
  706. return;
  707. if (!checkitemsize(itemsize, sizeof(struct info_peer_stats)) &&
  708. !checkitemsize(itemsize, v4sizeof(struct info_peer_stats)))
  709. return;
  710. while (items-- > 0) {
  711. memset((char *)&src, 0, sizeof(src));
  712. memset((char *)&dst, 0, sizeof(dst));
  713. if (pp->v6_flag != 0) {
  714. GET_INADDR6(src) = pp->srcadr6;
  715. GET_INADDR6(dst) = pp->dstadr6;
  716. src.ss_family = AF_INET6;
  717. dst.ss_family = AF_INET6;
  718. } else {
  719. GET_INADDR(src) = pp->srcadr;
  720. GET_INADDR(dst) = pp->dstadr;
  721. src.ss_family = AF_INET;
  722. dst.ss_family = AF_INET;
  723. }
  724. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  725. src.ss_len = SOCKLEN(&src);
  726. dst.ss_len = SOCKLEN(&dst);
  727. #endif
  728. (void) fprintf(fp, "remote host: %s\n",
  729. nntohost(&src));
  730. (void) fprintf(fp, "local interface: %s\n",
  731. stoa(&dst));
  732. (void) fprintf(fp, "time last received: %lds\n",
  733. (long)ntohl(pp->timereceived));
  734. (void) fprintf(fp, "time until next send: %lds\n",
  735. (long)ntohl(pp->timetosend));
  736. (void) fprintf(fp, "reachability change: %lds\n",
  737. (long)ntohl(pp->timereachable));
  738. (void) fprintf(fp, "packets sent: %ld\n",
  739. (long)ntohl(pp->sent));
  740. (void) fprintf(fp, "packets received: %ld\n",
  741. (long)ntohl(pp->processed));
  742. (void) fprintf(fp, "bad authentication: %ld\n",
  743. (long)ntohl(pp->badauth));
  744. (void) fprintf(fp, "bogus origin: %ld\n",
  745. (long)ntohl(pp->bogusorg));
  746. (void) fprintf(fp, "duplicate: %ld\n",
  747. (long)ntohl(pp->oldpkt));
  748. (void) fprintf(fp, "bad dispersion: %ld\n",
  749. (long)ntohl(pp->seldisp));
  750. (void) fprintf(fp, "bad reference time: %ld\n",
  751. (long)ntohl(pp->selbroken));
  752. (void) fprintf(fp, "candidate order: %d\n",
  753. (int)pp->candidate);
  754. if (items > 0)
  755. (void) fprintf(fp, "\n");
  756. (void) fprintf(fp, "flags: ");
  757. print_pflag(fp, ntohs(pp->flags));
  758. pp++;
  759. }
  760. }
  761. /*
  762. * loopinfo - show loop filter information
  763. */
  764. static void
  765. loopinfo(
  766. struct parse *pcmd,
  767. FILE *fp
  768. )
  769. {
  770. struct info_loop *il;
  771. int items;
  772. int itemsize;
  773. int oneline = 0;
  774. int res;
  775. l_fp tempts;
  776. if (pcmd->nargs > 0) {
  777. if (STREQ(pcmd->argval[0].string, "oneline"))
  778. oneline = 1;
  779. else if (STREQ(pcmd->argval[0].string, "multiline"))
  780. oneline = 0;
  781. else {
  782. (void) fprintf(stderr, "How many lines?\n");
  783. return;
  784. }
  785. }
  786. again:
  787. res = doquery(impl_ver, REQ_LOOP_INFO, 0, 0, 0, (char *)NULL,
  788. &items, &itemsize, (void *)&il, 0,
  789. sizeof(struct info_loop));
  790. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  791. impl_ver = IMPL_XNTPD_OLD;
  792. goto again;
  793. }
  794. if (res != 0)
  795. return;
  796. if (!check1item(items, fp))
  797. return;
  798. if (!checkitemsize(itemsize, sizeof(struct info_loop)))
  799. return;
  800. if (oneline) {
  801. l_fp temp2ts;
  802. NTOHL_FP(&il->last_offset, &tempts);
  803. NTOHL_FP(&il->drift_comp, &temp2ts);
  804. (void) fprintf(fp,
  805. "offset %s, frequency %s, time_const %ld, watchdog %ld\n",
  806. lfptoa(&tempts, 6),
  807. lfptoa(&temp2ts, 3),
  808. (long)(int32_t)ntohl((u_long)il->compliance),
  809. (u_long)ntohl((u_long)il->watchdog_timer));
  810. } else {
  811. NTOHL_FP(&il->last_offset, &tempts);
  812. (void) fprintf(fp, "offset: %s s\n",
  813. lfptoa(&tempts, 6));
  814. NTOHL_FP(&il->drift_comp, &tempts);
  815. (void) fprintf(fp, "frequency: %s ppm\n",
  816. lfptoa(&tempts, 3));
  817. (void) fprintf(fp, "poll adjust: %ld\n",
  818. (long)(int32_t)ntohl(il->compliance));
  819. (void) fprintf(fp, "watchdog timer: %ld s\n",
  820. (u_long)ntohl(il->watchdog_timer));
  821. }
  822. }
  823. /*
  824. * sysinfo - show current system state
  825. */
  826. /*ARGSUSED*/
  827. static void
  828. sysinfo(
  829. struct parse *pcmd,
  830. FILE *fp
  831. )
  832. {
  833. struct info_sys *is;
  834. struct sockaddr_storage peeraddr;
  835. int items;
  836. int itemsize;
  837. int res;
  838. l_fp tempts;
  839. again:
  840. res = doquery(impl_ver, REQ_SYS_INFO, 0, 0, 0, (char *)NULL,
  841. &items, &itemsize, (void *)&is, 0,
  842. sizeof(struct info_sys));
  843. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  844. impl_ver = IMPL_XNTPD_OLD;
  845. goto again;
  846. }
  847. if (res != 0)
  848. return;
  849. if (!check1item(items, fp))
  850. return;
  851. if (!checkitemsize(itemsize, sizeof(struct info_sys)) &&
  852. !checkitemsize(itemsize, v4sizeof(struct info_sys)))
  853. return;
  854. memset((char *)&peeraddr, 0, sizeof(peeraddr));
  855. if (is->v6_flag != 0) {
  856. GET_INADDR6(peeraddr) = is->peer6;
  857. peeraddr.ss_family = AF_INET6;
  858. } else {
  859. GET_INADDR(peeraddr) = is->peer;
  860. peeraddr.ss_family = AF_INET;
  861. }
  862. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  863. peeraddr.ss_len = SOCKLEN(&peeraddr);
  864. #endif
  865. (void) fprintf(fp, "system peer: %s\n", nntohost(&peeraddr));
  866. (void) fprintf(fp, "system peer mode: %s\n", modetoa(is->peer_mode));
  867. (void) fprintf(fp, "leap indicator: %c%c\n",
  868. is->leap & 0x2 ? '1' : '0',
  869. is->leap & 0x1 ? '1' : '0');
  870. (void) fprintf(fp, "stratum: %d\n", (int)is->stratum);
  871. (void) fprintf(fp, "precision: %d\n", (int)is->precision);
  872. (void) fprintf(fp, "root distance: %s s\n",
  873. fptoa(NTOHS_FP(is->rootdelay), 5));
  874. (void) fprintf(fp, "root dispersion: %s s\n",
  875. ufptoa(NTOHS_FP(is->rootdispersion), 5));
  876. (void) fprintf(fp, "reference ID: [%s]\n",
  877. refid_string(is->refid, is->stratum));
  878. NTOHL_FP(&is->reftime, &tempts);
  879. (void) fprintf(fp, "reference time: %s\n", prettydate(&tempts));
  880. (void) fprintf(fp, "system flags: ");
  881. if ((is->flags & (INFO_FLAG_BCLIENT | INFO_FLAG_AUTHENABLE |
  882. INFO_FLAG_NTP | INFO_FLAG_KERNEL| INFO_FLAG_CAL |
  883. INFO_FLAG_PPS_SYNC | INFO_FLAG_MONITOR | INFO_FLAG_FILEGEN)) == 0) {
  884. (void) fprintf(fp, "none\n");
  885. } else {
  886. if (is->flags & INFO_FLAG_BCLIENT)
  887. (void) fprintf(fp, "bclient ");
  888. if (is->flags & INFO_FLAG_AUTHENTICATE)
  889. (void) fprintf(fp, "auth ");
  890. if (is->flags & INFO_FLAG_MONITOR)
  891. (void) fprintf(fp, "monitor ");
  892. if (is->flags & INFO_FLAG_NTP)
  893. (void) fprintf(fp, "ntp ");
  894. if (is->flags & INFO_FLAG_KERNEL)
  895. (void) fprintf(fp, "kernel ");
  896. if (is->flags & INFO_FLAG_FILEGEN)
  897. (void) fprintf(fp, "stats ");
  898. if (is->flags & INFO_FLAG_CAL)
  899. (void) fprintf(fp, "calibrate ");
  900. if (is->flags & INFO_FLAG_PPS_SYNC)
  901. (void) fprintf(fp, "pps ");
  902. (void) fprintf(fp, "\n");
  903. }
  904. (void) fprintf(fp, "jitter: %s s\n",
  905. fptoa(ntohl(is->frequency), 6));
  906. (void) fprintf(fp, "stability: %s ppm\n",
  907. ufptoa(ntohl(is->stability), 3));
  908. (void) fprintf(fp, "broadcastdelay: %s s\n",
  909. fptoa(NTOHS_FP(is->bdelay), 6));
  910. NTOHL_FP(&is->authdelay, &tempts);
  911. (void) fprintf(fp, "authdelay: %s s\n", lfptoa(&tempts, 6));
  912. }
  913. /*
  914. * sysstats - print system statistics
  915. */
  916. /*ARGSUSED*/
  917. static void
  918. sysstats(
  919. struct parse *pcmd,
  920. FILE *fp
  921. )
  922. {
  923. struct info_sys_stats *ss;
  924. int items;
  925. int itemsize;
  926. int res;
  927. again:
  928. res = doquery(impl_ver, REQ_SYS_STATS, 0, 0, 0, (char *)NULL,
  929. &items, &itemsize, (void *)&ss, 0,
  930. sizeof(struct info_sys_stats));
  931. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  932. impl_ver = IMPL_XNTPD_OLD;
  933. goto again;
  934. }
  935. if (res != 0)
  936. return;
  937. if (!check1item(items, fp))
  938. return;
  939. if (itemsize != sizeof(struct info_sys_stats) &&
  940. itemsize != sizeof(struct old_info_sys_stats)) {
  941. /* issue warning according to new structure size */
  942. checkitemsize(itemsize, sizeof(struct info_sys_stats));
  943. return;
  944. }
  945. fprintf(fp, "time since restart: %ld\n",
  946. (u_long)ntohl(ss->timeup));
  947. fprintf(fp, "time since reset: %ld\n",
  948. (u_long)ntohl(ss->timereset));
  949. fprintf(fp, "packets received: %ld\n",
  950. (u_long)ntohl(ss->received));
  951. fprintf(fp, "packets processed: %ld\n",
  952. (u_long)ntohl(ss->processed));
  953. fprintf(fp, "current version: %ld\n",
  954. (u_long)ntohl(ss->newversionpkt));
  955. fprintf(fp, "previous version: %ld\n",
  956. (u_long)ntohl(ss->oldversionpkt));
  957. fprintf(fp, "bad version: %ld\n",
  958. (u_long)ntohl(ss->unknownversion));
  959. fprintf(fp, "access denied: %ld\n",
  960. (u_long)ntohl(ss->denied));
  961. fprintf(fp, "bad length or format: %ld\n",
  962. (u_long)ntohl(ss->badlength));
  963. fprintf(fp, "bad authentication: %ld\n",
  964. (u_long)ntohl(ss->badauth));
  965. if (itemsize != sizeof(struct info_sys_stats))
  966. return;
  967. fprintf(fp, "rate exceeded: %ld\n",
  968. (u_long)ntohl(ss->limitrejected));
  969. }
  970. /*
  971. * iostats - print I/O statistics
  972. */
  973. /*ARGSUSED*/
  974. static void
  975. iostats(
  976. struct parse *pcmd,
  977. FILE *fp
  978. )
  979. {
  980. struct info_io_stats *io;
  981. int items;
  982. int itemsize;
  983. int res;
  984. again:
  985. res = doquery(impl_ver, REQ_IO_STATS, 0, 0, 0, (char *)NULL,
  986. &items, &itemsize, (void *)&io, 0,
  987. sizeof(struct info_io_stats));
  988. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  989. impl_ver = IMPL_XNTPD_OLD;
  990. goto again;
  991. }
  992. if (res != 0)
  993. return;
  994. if (!check1item(items, fp))
  995. return;
  996. if (!checkitemsize(itemsize, sizeof(struct info_io_stats)))
  997. return;
  998. (void) fprintf(fp, "time since reset: %ld\n",
  999. (u_long)ntohl(io->timereset));
  1000. (void) fprintf(fp, "receive buffers: %d\n",
  1001. ntohs(io->totalrecvbufs));
  1002. (void) fprintf(fp, "free receive buffers: %d\n",
  1003. ntohs(io->freerecvbufs));
  1004. (void) fprintf(fp, "used receive buffers: %d\n",
  1005. ntohs(io->fullrecvbufs));
  1006. (void) fprintf(fp, "low water refills: %d\n",
  1007. ntohs(io->lowwater));
  1008. (void) fprintf(fp, "dropped packets: %ld\n",
  1009. (u_long)ntohl(io->dropped));
  1010. (void) fprintf(fp, "ignored packets: %ld\n",
  1011. (u_long)ntohl(io->ignored));
  1012. (void) fprintf(fp, "received packets: %ld\n",
  1013. (u_long)ntohl(io->received));
  1014. (void) fprintf(fp, "packets sent: %ld\n",
  1015. (u_long)ntohl(io->sent));
  1016. (void) fprintf(fp, "packets not sent: %ld\n",
  1017. (u_long)ntohl(io->notsent));
  1018. (void) fprintf(fp, "interrupts handled: %ld\n",
  1019. (u_long)ntohl(io->interrupts));
  1020. (void) fprintf(fp, "received by int: %ld\n",
  1021. (u_long)ntohl(io->int_received));
  1022. }
  1023. /*
  1024. * memstats - print peer memory statistics
  1025. */
  1026. /*ARGSUSED*/
  1027. static void
  1028. memstats(
  1029. struct parse *pcmd,
  1030. FILE *fp
  1031. )
  1032. {
  1033. struct info_mem_stats *mem;
  1034. int i;
  1035. int items;
  1036. int itemsize;
  1037. int res;
  1038. again:
  1039. res = doquery(impl_ver, REQ_MEM_STATS, 0, 0, 0, (char *)NULL,
  1040. &items, &itemsize, (void *)&mem, 0,
  1041. sizeof(struct info_mem_stats));
  1042. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  1043. impl_ver = IMPL_XNTPD_OLD;
  1044. goto again;
  1045. }
  1046. if (res != 0)
  1047. return;
  1048. if (!check1item(items, fp))
  1049. return;
  1050. if (!checkitemsize(itemsize, sizeof(struct info_mem_stats)))
  1051. return;
  1052. (void) fprintf(fp, "time since reset: %ld\n",
  1053. (u_long)ntohl(mem->timereset));
  1054. (void) fprintf(fp, "total peer memory: %d\n",
  1055. ntohs(mem->totalpeermem));
  1056. (void) fprintf(fp, "free peer memory: %d\n",
  1057. ntohs(mem->freepeermem));
  1058. (void) fprintf(fp, "calls to findpeer: %ld\n",
  1059. (u_long)ntohl(mem->findpeer_calls));
  1060. (void) fprintf(fp, "new peer allocations: %ld\n",
  1061. (u_long)ntohl(mem->allocations));
  1062. (void) fprintf(fp, "peer demobilizations: %ld\n",
  1063. (u_long)ntohl(mem->demobilizations));
  1064. (void) fprintf(fp, "hash table counts: ");
  1065. for (i = 0; i < NTP_HASH_SIZE; i++) {
  1066. (void) fprintf(fp, "%4d", (int)mem->hashcount[i]);
  1067. if ((i % 8) == 7 && i != (NTP_HASH_SIZE-1)) {
  1068. (void) fprintf(fp, "\n ");
  1069. }
  1070. }
  1071. (void) fprintf(fp, "\n");
  1072. }
  1073. /*
  1074. * timerstats - print timer statistics
  1075. */
  1076. /*ARGSUSED*/
  1077. static void
  1078. timerstats(
  1079. struct parse *pcmd,
  1080. FILE *fp
  1081. )
  1082. {
  1083. struct info_timer_stats *tim;
  1084. int items;
  1085. int itemsize;
  1086. int res;
  1087. again:
  1088. res = doquery(impl_ver, REQ_TIMER_STATS, 0, 0, 0, (char *)NULL,
  1089. &items, &itemsize, (void *)&tim, 0,
  1090. sizeof(struct info_timer_stats));
  1091. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  1092. impl_ver = IMPL_XNTPD_OLD;
  1093. goto again;
  1094. }
  1095. if (res != 0)
  1096. return;
  1097. if (!check1item(items, fp))
  1098. return;
  1099. if (!checkitemsize(itemsize, sizeof(struct info_timer_stats)))
  1100. return;
  1101. (void) fprintf(fp, "time since reset: %ld\n",
  1102. (u_long)ntohl(tim->timereset));
  1103. (void) fprintf(fp, "alarms handled: %ld\n",
  1104. (u_long)ntohl(tim->alarms));
  1105. (void) fprintf(fp, "alarm overruns: %ld\n",
  1106. (u_long)ntohl(tim->overflows));
  1107. (void) fprintf(fp, "calls to transmit: %ld\n",
  1108. (u_long)ntohl(tim->xmtcalls));
  1109. }
  1110. /*
  1111. * addpeer - configure an active mode association
  1112. */
  1113. static void
  1114. addpeer(
  1115. struct parse *pcmd,
  1116. FILE *fp
  1117. )
  1118. {
  1119. doconfig(pcmd, fp, MODE_ACTIVE, 0);
  1120. }
  1121. /*
  1122. * addserver - configure a client mode association
  1123. */
  1124. static void
  1125. addserver(
  1126. struct parse *pcmd,
  1127. FILE *fp
  1128. )
  1129. {
  1130. doconfig(pcmd, fp, MODE_CLIENT, 0);
  1131. }
  1132. /*
  1133. * addrefclock - configure a reference clock association
  1134. */
  1135. static void
  1136. addrefclock(
  1137. struct parse *pcmd,
  1138. FILE *fp
  1139. )
  1140. {
  1141. doconfig(pcmd, fp, MODE_CLIENT, 1);
  1142. }
  1143. /*
  1144. * broadcast - configure a broadcast mode association
  1145. */
  1146. static void
  1147. broadcast(
  1148. struct parse *pcmd,
  1149. FILE *fp
  1150. )
  1151. {
  1152. doconfig(pcmd, fp, MODE_BROADCAST, 0);
  1153. }
  1154. /*
  1155. * config - configure a new peer association
  1156. */
  1157. static void
  1158. doconfig(
  1159. struct parse *pcmd,
  1160. FILE *fp,
  1161. int mode,
  1162. int refc
  1163. )
  1164. {
  1165. struct conf_peer cpeer;
  1166. int items;
  1167. int itemsize;
  1168. char *dummy;
  1169. u_long keyid;
  1170. u_int version;
  1171. u_char minpoll;
  1172. u_char maxpoll;
  1173. u_int flags;
  1174. u_char cmode;
  1175. int res;
  1176. int sendsize;
  1177. int numtyp;
  1178. again:
  1179. keyid = 0;
  1180. version = 3;
  1181. flags = 0;
  1182. res = 0;
  1183. cmode = 0;
  1184. minpoll = NTP_MINDPOLL;
  1185. maxpoll = NTP_MAXDPOLL;
  1186. numtyp = 1;
  1187. if (refc)
  1188. numtyp = 5;
  1189. if (impl_ver == IMPL_XNTPD)
  1190. sendsize = sizeof(struct conf_peer);
  1191. else
  1192. sendsize = v4sizeof(struct conf_peer);
  1193. items = 1;
  1194. while (pcmd->nargs > items) {
  1195. if (STREQ(pcmd->argval[items].string, "prefer"))
  1196. flags |= CONF_FLAG_PREFER;
  1197. else if (STREQ(pcmd->argval[items].string, "burst"))
  1198. flags |= CONF_FLAG_BURST;
  1199. else if (STREQ(pcmd->argval[items].string, "dynamic"))
  1200. (void) fprintf(fp, "Warning: the \"dynamic\" keyword has been obsoleted and will be removed in the next release\n");
  1201. else if (STREQ(pcmd->argval[items].string, "iburst"))
  1202. flags |= CONF_FLAG_IBURST;
  1203. else if (!refc && STREQ(pcmd->argval[items].string, "keyid"))
  1204. numtyp = 1;
  1205. else if (!refc && STREQ(pcmd->argval[items].string, "version"))
  1206. numtyp = 2;
  1207. else if (STREQ(pcmd->argval[items].string, "minpoll"))
  1208. numtyp = 3;
  1209. else if (STREQ(pcmd->argval[items].string, "maxpoll"))
  1210. numtyp = 4;
  1211. else {
  1212. long val;
  1213. if (!atoint(pcmd->argval[items].string, &val))
  1214. numtyp = 0;
  1215. switch (numtyp) {
  1216. case 1:
  1217. keyid = val;
  1218. numtyp = 2;
  1219. break;
  1220. case 2:
  1221. version = (u_int) val;
  1222. numtyp = 0;
  1223. break;
  1224. case 3:
  1225. minpoll = (u_char)val;
  1226. numtyp = 0;
  1227. break;
  1228. case 4:
  1229. maxpoll = (u_char)val;
  1230. numtyp = 0;
  1231. break;
  1232. case 5:
  1233. cmode = (u_char)val;
  1234. numtyp = 0;
  1235. break;
  1236. default:
  1237. (void) fprintf(fp, "*** '%s' not understood\n",
  1238. pcmd->argval[items].string);
  1239. res++;
  1240. numtyp = 0;
  1241. }
  1242. if (val < 0) {
  1243. (void) fprintf(stderr,
  1244. "***Value '%s' should be unsigned\n",
  1245. pcmd->argval[items].string);
  1246. res++;
  1247. }
  1248. }
  1249. items++;
  1250. }
  1251. if (keyid > 0)
  1252. flags |= CONF_FLAG_AUTHENABLE;
  1253. if (version > NTP_VERSION ||
  1254. version < NTP_OLDVERSION) {
  1255. (void)fprintf(fp, "***invalid version number: %u\n",
  1256. version);
  1257. res++;
  1258. }
  1259. if (minpoll < NTP_MINPOLL || minpoll > NTP_MAXPOLL ||
  1260. maxpoll < NTP_MINPOLL || maxpoll > NTP_MAXPOLL ||
  1261. minpoll > maxpoll) {
  1262. (void) fprintf(fp, "***min/max-poll must be within %d..%d\n",
  1263. NTP_MINPOLL, NTP_MAXPOLL);
  1264. res++;
  1265. }
  1266. if (res)
  1267. return;
  1268. memset((void *)&cpeer, 0, sizeof(cpeer));
  1269. if (pcmd->argval[0].netnum.ss_family == AF_INET) {
  1270. cpeer.peeraddr = GET_INADDR(pcmd->argval[0].netnum);
  1271. if (impl_ver == IMPL_XNTPD)
  1272. cpeer.v6_flag = 0;
  1273. } else {
  1274. if (impl_ver == IMPL_XNTPD_OLD) {
  1275. fprintf(stderr,
  1276. "***Server doesn't understand IPv6 addresses\n");
  1277. return;
  1278. }
  1279. cpeer.peeraddr6 = GET_INADDR6(pcmd->argval[0].netnum);
  1280. cpeer.v6_flag = 1;
  1281. }
  1282. cpeer.hmode = (u_char) mode;
  1283. cpeer.keyid = keyid;
  1284. cpeer.version = (u_char) version;
  1285. cpeer.minpoll = minpoll;
  1286. cpeer.maxpoll = maxpoll;
  1287. cpeer.flags = (u_char)flags;
  1288. cpeer.ttl = cmode;
  1289. res = doquery(impl_ver, REQ_CONFIG, 1, 1,
  1290. sendsize, (char *)&cpeer, &items,
  1291. &itemsize, &dummy, 0, sizeof(struct conf_peer));
  1292. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  1293. impl_ver = IMPL_XNTPD_OLD;
  1294. goto again;
  1295. }
  1296. if (res == INFO_ERR_FMT) {
  1297. (void) fprintf(fp,
  1298. "***Retrying command with old conf_peer size\n");
  1299. res = doquery(impl_ver, REQ_CONFIG, 1, 1,
  1300. sizeof(struct old_conf_peer), (char *)&cpeer,
  1301. &items, &itemsize, &dummy, 0,
  1302. sizeof(struct conf_peer));
  1303. }
  1304. if (res == 0)
  1305. (void) fprintf(fp, "done!\n");
  1306. return;
  1307. }
  1308. /*
  1309. * unconfig - unconfigure some associations
  1310. */
  1311. static void
  1312. unconfig(
  1313. struct parse *pcmd,
  1314. FILE *fp
  1315. )
  1316. {
  1317. /* 8 is the maximum number of peers which will fit in a packet */
  1318. struct conf_unpeer *pl, plist[min(MAXARGS, 8)];
  1319. int qitems;
  1320. int items;
  1321. int itemsize;
  1322. char *dummy;
  1323. int res;
  1324. int sendsize;
  1325. again:
  1326. if (impl_ver == IMPL_XNTPD)
  1327. sendsize = sizeof(struct conf_unpeer);
  1328. else
  1329. sendsize = v4sizeof(struct conf_unpeer);
  1330. for (qitems = 0, pl = plist; qitems < min(pcmd->nargs, 8); qitems++) {
  1331. if (pcmd->argval[0].netnum.ss_family == AF_INET) {
  1332. pl->peeraddr = GET_INADDR(pcmd->argval[qitems].netnum);
  1333. if (impl_ver == IMPL_XNTPD)
  1334. pl->v6_flag = 0;
  1335. } else {
  1336. if (impl_ver == IMPL_XNTPD_OLD) {
  1337. fprintf(stderr,
  1338. "***Server doesn't understand IPv6 addresses\n");
  1339. return;
  1340. }
  1341. pl->peeraddr6 =
  1342. GET_INADDR6(pcmd->argval[qitems].netnum);
  1343. pl->v6_flag = 1;
  1344. }
  1345. pl = (struct conf_unpeer *)((char *)pl + sendsize);
  1346. }
  1347. res = doquery(impl_ver, REQ_UNCONFIG, 1, qitems,
  1348. sendsize, (char *)plist, &items,
  1349. &itemsize, &dummy, 0, sizeof(struct conf_unpeer));
  1350. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  1351. impl_ver = IMPL_XNTPD_OLD;
  1352. goto again;
  1353. }
  1354. if (res == 0)
  1355. (void) fprintf(fp, "done!\n");
  1356. }
  1357. /*
  1358. * set - set some system flags
  1359. */
  1360. static void
  1361. set(
  1362. struct parse *pcmd,
  1363. FILE *fp
  1364. )
  1365. {
  1366. doset(pcmd, fp, REQ_SET_SYS_FLAG);
  1367. }
  1368. /*
  1369. * clear - clear some system flags
  1370. */
  1371. static void
  1372. sys_clear(
  1373. struct parse *pcmd,
  1374. FILE *fp
  1375. )
  1376. {
  1377. doset(pcmd, fp, REQ_CLR_SYS_FLAG);
  1378. }
  1379. /*
  1380. * doset - set/clear system flags
  1381. */
  1382. static void
  1383. doset(
  1384. struct parse *pcmd,
  1385. FILE *fp,
  1386. int req
  1387. )
  1388. {
  1389. /* 8 is the maximum number of peers which will fit in a packet */
  1390. struct conf_sys_flags sys;
  1391. int items;
  1392. int itemsize;
  1393. char *dummy;
  1394. int res;
  1395. sys.flags = 0;
  1396. res = 0;
  1397. for (items = 0; items < pcmd->nargs; items++) {
  1398. if (STREQ(pcmd->argval[items].string, "auth"))
  1399. sys.flags |= SYS_FLAG_AUTH;
  1400. else if (STREQ(pcmd->argval[items].string, "bclient"))
  1401. sys.flags |= SYS_FLAG_BCLIENT;
  1402. else if (STREQ(pcmd->argval[items].string, "calibrate"))
  1403. sys.flags |= SYS_FLAG_CAL;
  1404. else if (STREQ(pcmd->argval[items].string, "kernel"))
  1405. sys.flags |= SYS_FLAG_KERNEL;
  1406. else if (STREQ(pcmd->argval[items].string, "monitor"))
  1407. sys.flags |= SYS_FLAG_MONITOR;
  1408. else if (STREQ(pcmd->argval[items].string, "ntp"))
  1409. sys.flags |= SYS_FLAG_NTP;
  1410. else if (STREQ(pcmd->argval[items].string, "pps"))
  1411. sys.flags |= SYS_FLAG_PPS;
  1412. else if (STREQ(pcmd->argval[items].string, "stats"))
  1413. sys.flags |= SYS_FLAG_FILEGEN;
  1414. else {
  1415. (void) fprintf(fp, "Unknown flag %s\n",
  1416. pcmd->argval[items].string);
  1417. res = 1;
  1418. }
  1419. }
  1420. sys.flags = htonl(sys.flags);
  1421. if (res || sys.flags == 0)
  1422. return;
  1423. again:
  1424. res = doquery(impl_ver, req, 1, 1,
  1425. sizeof(struct conf_sys_flags), (char *)&sys, &items,
  1426. &itemsize, &dummy, 0, sizeof(struct conf_sys_flags));
  1427. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  1428. impl_ver = IMPL_XNTPD_OLD;
  1429. goto again;
  1430. }
  1431. if (res == 0)
  1432. (void) fprintf(fp, "done!\n");
  1433. }
  1434. /*
  1435. * data for printing/interrpreting the restrict flags
  1436. */
  1437. struct resflags {
  1438. const char *str;
  1439. int bit;
  1440. };
  1441. /* XXX: HMS: we apparently don't report set bits we do not recognize. */
  1442. static struct resflags resflagsV2[] = {
  1443. { "ignore", 0x001 },
  1444. { "noserve", 0x002 },
  1445. { "notrust", 0x004 },
  1446. { "noquery", 0x008 },
  1447. { "nomodify", 0x010 },
  1448. { "nopeer", 0x020 },
  1449. { "notrap", 0x040 },
  1450. { "lptrap", 0x080 },
  1451. { "limited", 0x100 },
  1452. { "", 0 }
  1453. };
  1454. static struct resflags resflagsV3[] = {
  1455. { "ignore", RES_IGNORE },
  1456. { "noserve", RES_DONTSERVE },
  1457. { "notrust", RES_DONTTRUST },
  1458. { "noquery", RES_NOQUERY },
  1459. { "nomodify", RES_NOMODIFY },
  1460. { "nopeer", RES_NOPEER },
  1461. { "notrap", RES_NOTRAP },
  1462. { "lptrap", RES_LPTRAP },
  1463. { "limited", RES_LIMITED },
  1464. { "version", RES_VERSION },
  1465. { "kod", RES_DEMOBILIZE },
  1466. { "timeout", RES_TIMEOUT },
  1467. { "", 0 }
  1468. };
  1469. static struct resflags resmflags[] = {
  1470. { "ntpport", RESM_NTPONLY },
  1471. { "interface", RESM_INTERFACE },
  1472. { "", 0 }
  1473. };
  1474. /*
  1475. * reslist - obtain and print the server's restrict list
  1476. */
  1477. /*ARGSUSED*/
  1478. static void
  1479. reslist(
  1480. struct parse *pcmd,
  1481. FILE *fp
  1482. )
  1483. {
  1484. struct info_restrict *rl;
  1485. struct sockaddr_storage resaddr;
  1486. struct sockaddr_storage maskaddr;
  1487. int items;
  1488. int itemsize;
  1489. int res;
  1490. int skip;
  1491. char *addr;
  1492. char *mask;
  1493. struct resflags *rf;
  1494. u_int32 count;
  1495. u_short flags;
  1496. u_short mflags;
  1497. char flagstr[300];
  1498. static const char *comma = ", ";
  1499. again:
  1500. res = doquery(impl_ver, REQ_GET_RESTRICT, 0, 0, 0, (char *)NULL,
  1501. &items, &itemsize, (void *)&rl, 0,
  1502. sizeof(struct info_restrict));
  1503. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  1504. impl_ver = IMPL_XNTPD_OLD;
  1505. goto again;
  1506. }
  1507. if (res != 0)
  1508. return;
  1509. if (!checkitems(items, fp))
  1510. return;
  1511. if (!checkitemsize(itemsize, sizeof(struct info_restrict)) &&
  1512. !checkitemsize(itemsize, v4sizeof(struct info_restrict)))
  1513. return;
  1514. (void) fprintf(fp,
  1515. " address mask count flags\n");
  1516. (void) fprintf(fp,
  1517. "=====================================================================\n");
  1518. while (items > 0) {
  1519. memset((char *)&resaddr, 0, sizeof(resaddr));
  1520. memset((char *)&maskaddr, 0, sizeof(maskaddr));
  1521. if (rl->v6_flag != 0) {
  1522. GET_INADDR6(resaddr) = rl->addr6;
  1523. GET_INADDR6(maskaddr) = rl->mask6;
  1524. resaddr.ss_family = AF_INET6;
  1525. maskaddr.ss_family = AF_INET6;
  1526. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  1527. resaddr.ss_len = SOCKLEN(&resaddr);
  1528. #endif
  1529. addr = nntohost(&resaddr);
  1530. } else {
  1531. GET_INADDR(resaddr) = rl->addr;
  1532. GET_INADDR(maskaddr) = rl->mask;
  1533. resaddr.ss_family = AF_INET;
  1534. maskaddr.ss_family = AF_INET;
  1535. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  1536. resaddr.ss_len = SOCKLEN(&resaddr);
  1537. #endif
  1538. if ((rl->mask == (u_int32)0xffffffff))
  1539. addr = nntohost(&resaddr);
  1540. else
  1541. addr = stoa(&resaddr);
  1542. }
  1543. mask = stoa(&maskaddr);
  1544. skip = 1;
  1545. if ((pcmd->nargs == 0) ||
  1546. ((pcmd->argval->ival == 6) && (rl->v6_flag != 0)) ||
  1547. ((pcmd->argval->ival == 4) && (rl->v6_flag == 0)))
  1548. skip = 0;
  1549. count = ntohl(rl->count);
  1550. flags = ntohs(rl->flags);
  1551. mflags = ntohs(rl->mflags);
  1552. flagstr[0] = '\0';
  1553. res = 1;
  1554. rf = &resmflags[0];
  1555. while (rf->bit != 0) {
  1556. if (mflags & rf->bit) {
  1557. if (!res)
  1558. (void) strcat(flagstr, comma);
  1559. res = 0;
  1560. (void) strcat(flagstr, rf->str);
  1561. }
  1562. rf++;
  1563. }
  1564. rf = (impl_ver == IMPL_XNTPD_OLD)
  1565. ? &resflagsV2[0]
  1566. : &resflagsV3[0]
  1567. ;
  1568. while (rf->bit != 0) {
  1569. if (flags & rf->bit) {
  1570. if (!res)
  1571. (void) strcat(flagstr, comma);
  1572. res = 0;
  1573. (void) strcat(flagstr, rf->str);
  1574. }
  1575. rf++;
  1576. }
  1577. if (flagstr[0] == '\0')
  1578. (void) strcpy(flagstr, "none");
  1579. if (!skip)
  1580. (void) fprintf(fp, "%-15.15s %-15.15s %9ld %s\n",
  1581. addr, mask, (u_long)count, flagstr);
  1582. rl++;
  1583. items--;
  1584. }
  1585. }
  1586. /*
  1587. * new_restrict - create/add a set of restrictions
  1588. */
  1589. static void
  1590. new_restrict(
  1591. struct parse *pcmd,
  1592. FILE *fp
  1593. )
  1594. {
  1595. do_restrict(pcmd, fp, REQ_RESADDFLAGS);
  1596. }
  1597. /*
  1598. * unrestrict - remove restriction flags from existing entry
  1599. */
  1600. static void
  1601. unrestrict(
  1602. struct parse *pcmd,
  1603. FILE *fp
  1604. )
  1605. {
  1606. do_restrict(pcmd, fp, REQ_RESSUBFLAGS);
  1607. }
  1608. /*
  1609. * delrestrict - delete an existing restriction
  1610. */
  1611. static void
  1612. delrestrict(
  1613. struct parse *pcmd,
  1614. FILE *fp
  1615. )
  1616. {
  1617. do_restrict(pcmd, fp, REQ_UNRESTRICT);
  1618. }
  1619. /*
  1620. * do_restrict - decode commandline restrictions and make the request
  1621. */
  1622. static void
  1623. do_restrict(
  1624. struct parse *pcmd,
  1625. FILE *fp,
  1626. int req_code
  1627. )
  1628. {
  1629. struct conf_restrict cres;
  1630. int items;
  1631. int itemsize;
  1632. char *dummy;
  1633. u_int32 num;
  1634. u_long bit;
  1635. int i;
  1636. int res;
  1637. int err;
  1638. int sendsize;
  1639. /* Initialize cres */
  1640. cres.addr = 0;
  1641. cres.mask = 0;
  1642. cres.flags = 0;
  1643. cres.mflags = 0;
  1644. cres.v6_flag = 0;
  1645. again:
  1646. if (impl_ver == IMPL_XNTPD)
  1647. sendsize = sizeof(struct conf_restrict);
  1648. else
  1649. sendsize = v4sizeof(struct conf_restrict);
  1650. if (pcmd->argval[0].netnum.ss_family == AF_INET) {
  1651. cres.addr = GET_INADDR(pcmd->argval[0].netnum);
  1652. cres.mask = GET_INADDR(pcmd->argval[1].netnum);
  1653. if (impl_ver == IMPL_XNTPD)
  1654. cres.v6_flag = 0;
  1655. } else {
  1656. if (impl_ver == IMPL_XNTPD_OLD) {
  1657. fprintf(stderr,
  1658. "***Server doesn't understand IPv6 addresses\n");
  1659. return;
  1660. }
  1661. cres.addr6 = GET_INADDR6(pcmd->argval[0].netnum);
  1662. cres.v6_flag = 1;
  1663. }
  1664. cres.flags = 0;
  1665. cres.mflags = 0;
  1666. err = 0;
  1667. for (res = 2; res < pcmd->nargs; res++) {
  1668. if (STREQ(pcmd->argval[res].string, "ntpport")) {
  1669. cres.mflags |= RESM_NTPONLY;
  1670. } else {
  1671. for (i = 0; resflagsV3[i].bit != 0; i++) {
  1672. if (STREQ(pcmd->argval[res].string,
  1673. resflagsV3[i].str))
  1674. break;
  1675. }
  1676. if (resflagsV3[i].bit != 0) {
  1677. cres.flags |= resflagsV3[i].bit;
  1678. if (req_code == REQ_UNRESTRICT) {
  1679. (void) fprintf(fp,
  1680. "Flag %s inappropriate\n",
  1681. resflagsV3[i].str);
  1682. err++;
  1683. }
  1684. } else {
  1685. (void) fprintf(fp, "Unknown flag %s\n",
  1686. pcmd->argval[res].string);
  1687. err++;
  1688. }
  1689. }
  1690. }
  1691. cres.flags = htons(cres.flags);
  1692. cres.mflags = htons(cres.mflags);
  1693. /*
  1694. * Make sure mask for default address is zero. Otherwise,
  1695. * make sure mask bits are contiguous.
  1696. */
  1697. if (pcmd->argval[0].netnum.ss_family == AF_INET) {
  1698. if (cres.addr == 0) {
  1699. cres.mask = 0;
  1700. } else {
  1701. num = ntohl(cres.mask);
  1702. for (bit = 0x80000000; bit != 0; bit >>= 1)
  1703. if ((num & bit) == 0)
  1704. break;
  1705. for ( ; bit != 0; bit >>= 1)
  1706. if ((num & bit) != 0)
  1707. break;
  1708. if (bit != 0) {
  1709. (void) fprintf(fp, "Invalid mask %s\n",
  1710. numtoa(cres.mask));
  1711. err++;
  1712. }
  1713. }
  1714. } else {
  1715. /* XXX IPv6 sanity checking stuff */
  1716. }
  1717. if (err)
  1718. return;
  1719. res = doquery(impl_ver, req_code, 1, 1,
  1720. sendsize, (char *)&cres, &items,
  1721. &itemsize, &dummy, 0, sizeof(struct conf_restrict));
  1722. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  1723. impl_ver = IMPL_XNTPD_OLD;
  1724. goto again;
  1725. }
  1726. if (res == 0)
  1727. (void) fprintf(fp, "done!\n");
  1728. return;
  1729. }
  1730. /*
  1731. * monlist - obtain and print the server's monitor data
  1732. */
  1733. /*ARGSUSED*/
  1734. static void
  1735. monlist(
  1736. struct parse *pcmd,
  1737. FILE *fp
  1738. )
  1739. {
  1740. char *struct_star;