PageRenderTime 316ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 1ms

/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
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.0, LGPL-2.1, BSD-2-Clause, 0BSD, JSON, AGPL-1.0, GPL-2.0
  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;
  1741. struct sockaddr_storage addr;
  1742. struct sockaddr_storage dstadr;
  1743. int items;
  1744. int itemsize;
  1745. int res;
  1746. int version = -1;
  1747. if (pcmd->nargs > 0) {
  1748. version = pcmd->argval[0].ival;
  1749. }
  1750. again:
  1751. res = doquery(impl_ver,
  1752. (version == 1 || version == -1) ? REQ_MON_GETLIST_1 :
  1753. REQ_MON_GETLIST, 0, 0, 0, (char *)NULL,
  1754. &items, &itemsize, &struct_star,
  1755. (version < 0) ? (1 << INFO_ERR_REQ) : 0,
  1756. sizeof(struct info_monitor_1));
  1757. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  1758. impl_ver = IMPL_XNTPD_OLD;
  1759. goto again;
  1760. }
  1761. if (res == INFO_ERR_REQ && version < 0)
  1762. res = doquery(impl_ver, REQ_MON_GETLIST, 0, 0, 0, (char *)NULL,
  1763. &items, &itemsize, &struct_star, 0,
  1764. sizeof(struct info_monitor));
  1765. if (res != 0)
  1766. return;
  1767. if (!checkitems(items, fp))
  1768. return;
  1769. if (itemsize == sizeof(struct info_monitor_1) ||
  1770. itemsize == v4sizeof(struct info_monitor_1)) {
  1771. struct info_monitor_1 *ml = (struct info_monitor_1 *) struct_star;
  1772. (void) fprintf(fp,
  1773. "remote address port local address count m ver code avgint lstint\n");
  1774. (void) fprintf(fp,
  1775. "===============================================================================\n");
  1776. while (items > 0) {
  1777. memset((char *)&addr, 0, sizeof(addr));
  1778. memset((char *)&dstadr, 0, sizeof(dstadr));
  1779. if (ml->v6_flag != 0) {
  1780. GET_INADDR6(addr) = ml->addr6;
  1781. addr.ss_family = AF_INET6;
  1782. GET_INADDR6(dstadr) = ml->daddr6;
  1783. dstadr.ss_family = AF_INET6;
  1784. } else {
  1785. GET_INADDR(addr) = ml->addr;
  1786. addr.ss_family = AF_INET;
  1787. GET_INADDR(dstadr) = ml->daddr;
  1788. dstadr.ss_family = AF_INET;
  1789. }
  1790. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  1791. addr.ss_len = SOCKLEN(&addr);
  1792. dstadr.ss_len = SOCKLEN(&dstadr);
  1793. #endif
  1794. if ((pcmd->nargs == 0) ||
  1795. ((pcmd->argval->ival == 6) && (ml->v6_flag != 0)) ||
  1796. ((pcmd->argval->ival == 4) && (ml->v6_flag == 0)))
  1797. (void) fprintf(fp,
  1798. "%-22.22s %5d %-15s %8ld %1d %1d %6lx %6lu %7lu\n",
  1799. nntohost(&addr),
  1800. ntohs(ml->port),
  1801. stoa(&dstadr),
  1802. (u_long)ntohl(ml->count),
  1803. ml->mode,
  1804. ml->version,
  1805. (u_long)ntohl(ml->lastdrop),
  1806. (u_long)ntohl(ml->lasttime),
  1807. (u_long)ntohl(ml->firsttime));
  1808. ml++;
  1809. items--;
  1810. }
  1811. } else if (itemsize == sizeof(struct info_monitor) ||
  1812. itemsize == v4sizeof(struct info_monitor)) {
  1813. struct info_monitor *ml = (struct info_monitor *) struct_star;
  1814. (void) fprintf(fp,
  1815. " address port count mode ver code avgint lstint\n");
  1816. (void) fprintf(fp,
  1817. "===============================================================================\n");
  1818. while (items > 0) {
  1819. memset((char *)&dstadr, 0, sizeof(dstadr));
  1820. if (ml->v6_flag != 0) {
  1821. GET_INADDR6(dstadr) = ml->addr6;
  1822. dstadr.ss_family = AF_INET6;
  1823. } else {
  1824. GET_INADDR(dstadr) = ml->addr;
  1825. dstadr.ss_family = AF_INET;
  1826. }
  1827. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  1828. dstadr.ss_len = SOCKLEN(&dstadr);
  1829. #endif
  1830. if ((pcmd->nargs == 0) ||
  1831. ((pcmd->argval->ival == 6) && (ml->v6_flag != 0)) ||
  1832. ((pcmd->argval->ival == 4) && (ml->v6_flag == 0)))
  1833. (void) fprintf(fp,
  1834. "%-25.25s %5d %9ld %4d %2d %9lx %9lu %9lu\n",
  1835. nntohost(&dstadr),
  1836. ntohs(ml->port),
  1837. (u_long)ntohl(ml->count),
  1838. ml->mode,
  1839. ml->version,
  1840. (u_long)ntohl(ml->lastdrop),
  1841. (u_long)ntohl(ml->lasttime),
  1842. (u_long)ntohl(ml->firsttime));
  1843. ml++;
  1844. items--;
  1845. }
  1846. } else if (itemsize == sizeof(struct old_info_monitor)) {
  1847. struct old_info_monitor *oml = (struct old_info_monitor *)struct_star;
  1848. (void) fprintf(fp,
  1849. " address port count mode version lasttime firsttime\n");
  1850. (void) fprintf(fp,
  1851. "======================================================================\n");
  1852. while (items > 0) {
  1853. memset((char *)&dstadr, 0, sizeof(dstadr));
  1854. if (oml->v6_flag != 0) {
  1855. GET_INADDR6(dstadr) = oml->addr6;
  1856. dstadr.ss_family = AF_INET6;
  1857. } else {
  1858. GET_INADDR(dstadr) = oml->addr;
  1859. dstadr.ss_family = AF_INET;
  1860. }
  1861. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  1862. dstadr.ss_len = SOCKLEN(&dstadr);
  1863. #endif
  1864. (void) fprintf(fp, "%-20.20s %5d %9ld %4d %3d %9lu %9lu\n",
  1865. nntohost(&dstadr),
  1866. ntohs(oml->port),
  1867. (u_long)ntohl(oml->count),
  1868. oml->mode,
  1869. oml->version,
  1870. (u_long)ntohl(oml->lasttime),
  1871. (u_long)ntohl(oml->firsttime));
  1872. oml++;
  1873. items--;
  1874. }
  1875. } else {
  1876. /* issue warning according to new info_monitor size */
  1877. checkitemsize(itemsize, sizeof(struct info_monitor));
  1878. }
  1879. }
  1880. /*
  1881. * Mapping between command line strings and stat reset flags
  1882. */
  1883. struct statreset {
  1884. const char *str;
  1885. int flag;
  1886. } sreset[] = {
  1887. { "io", RESET_FLAG_IO },
  1888. { "sys", RESET_FLAG_SYS },
  1889. { "mem", RESET_FLAG_MEM },
  1890. { "timer", RESET_FLAG_TIMER },
  1891. { "auth", RESET_FLAG_AUTH },
  1892. { "allpeers", RESET_FLAG_ALLPEERS },
  1893. { "", 0 }
  1894. };
  1895. /*
  1896. * reset - reset statistic counters
  1897. */
  1898. static void
  1899. reset(
  1900. struct parse *pcmd,
  1901. FILE *fp
  1902. )
  1903. {
  1904. struct reset_flags rflags;
  1905. int items;
  1906. int itemsize;
  1907. char *dummy;
  1908. int i;
  1909. int res;
  1910. int err;
  1911. err = 0;
  1912. rflags.flags = 0;
  1913. for (res = 0; res < pcmd->nargs; res++) {
  1914. for (i = 0; sreset[i].flag != 0; i++) {
  1915. if (STREQ(pcmd->argval[res].string, sreset[i].str))
  1916. break;
  1917. }
  1918. if (sreset[i].flag == 0) {
  1919. (void) fprintf(fp, "Flag %s unknown\n",
  1920. pcmd->argval[res].string);
  1921. err++;
  1922. } else {
  1923. rflags.flags |= sreset[i].flag;
  1924. }
  1925. }
  1926. rflags.flags = htonl(rflags.flags);
  1927. if (err) {
  1928. (void) fprintf(fp, "Not done due to errors\n");
  1929. return;
  1930. }
  1931. again:
  1932. res = doquery(impl_ver, REQ_RESET_STATS, 1, 1,
  1933. sizeof(struct reset_flags), (char *)&rflags, &items,
  1934. &itemsize, &dummy, 0, sizeof(struct reset_flags));
  1935. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  1936. impl_ver = IMPL_XNTPD_OLD;
  1937. goto again;
  1938. }
  1939. if (res == 0)
  1940. (void) fprintf(fp, "done!\n");
  1941. return;
  1942. }
  1943. /*
  1944. * preset - reset stat counters for particular peers
  1945. */
  1946. static void
  1947. preset(
  1948. struct parse *pcmd,
  1949. FILE *fp
  1950. )
  1951. {
  1952. /* 8 is the maximum number of peers which will fit in a packet */
  1953. struct conf_unpeer *pl, plist[min(MAXARGS, 8)];
  1954. int qitems;
  1955. int items;
  1956. int itemsize;
  1957. char *dummy;
  1958. int res;
  1959. int sendsize;
  1960. again:
  1961. if (impl_ver == IMPL_XNTPD)
  1962. sendsize = sizeof(struct conf_unpeer);
  1963. else
  1964. sendsize = v4sizeof(struct conf_unpeer);
  1965. for (qitems = 0, pl = plist; qitems < min(pcmd->nargs, 8); qitems++) {
  1966. if (pcmd->argval[qitems].netnum.ss_family == AF_INET) {
  1967. pl->peeraddr = GET_INADDR(pcmd->argval[qitems].netnum);
  1968. if (impl_ver == IMPL_XNTPD)
  1969. pl->v6_flag = 0;
  1970. } else {
  1971. if (impl_ver == IMPL_XNTPD_OLD) {
  1972. fprintf(stderr,
  1973. "***Server doesn't understand IPv6 addresses\n");
  1974. return;
  1975. }
  1976. pl->peeraddr6 =
  1977. GET_INADDR6(pcmd->argval[qitems].netnum);
  1978. pl->v6_flag = 1;
  1979. }
  1980. pl = (struct conf_unpeer *)((char *)pl + sendsize);
  1981. }
  1982. res = doquery(impl_ver, REQ_RESET_PEER, 1, qitems,
  1983. sendsize, (char *)plist, &items,
  1984. &itemsize, &dummy, 0, sizeof(struct conf_unpeer));
  1985. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  1986. impl_ver = IMPL_XNTPD_OLD;
  1987. goto again;
  1988. }
  1989. if (res == 0)
  1990. (void) fprintf(fp, "done!\n");
  1991. }
  1992. /*
  1993. * readkeys - request the server to reread the keys file
  1994. */
  1995. /*ARGSUSED*/
  1996. static void
  1997. readkeys(
  1998. struct parse *pcmd,
  1999. FILE *fp
  2000. )
  2001. {
  2002. int items;
  2003. int itemsize;
  2004. char *dummy;
  2005. int res;
  2006. again:
  2007. res = doquery(impl_ver, REQ_REREAD_KEYS, 1, 0, 0, (char *)0,
  2008. &items, &itemsize, &dummy, 0, sizeof(dummy));
  2009. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  2010. impl_ver = IMPL_XNTPD_OLD;
  2011. goto again;
  2012. }
  2013. if (res == 0)
  2014. (void) fprintf(fp, "done!\n");
  2015. return;
  2016. }
  2017. /*
  2018. * trustkey - add some keys to the trusted key list
  2019. */
  2020. static void
  2021. trustkey(
  2022. struct parse *pcmd,
  2023. FILE *fp
  2024. )
  2025. {
  2026. do_trustkey(pcmd, fp, REQ_TRUSTKEY);
  2027. }
  2028. /*
  2029. * untrustkey - remove some keys from the trusted key list
  2030. */
  2031. static void
  2032. untrustkey(
  2033. struct parse *pcmd,
  2034. FILE *fp
  2035. )
  2036. {
  2037. do_trustkey(pcmd, fp, REQ_UNTRUSTKEY);
  2038. }
  2039. /*
  2040. * do_trustkey - do grunge work of adding/deleting keys
  2041. */
  2042. static void
  2043. do_trustkey(
  2044. struct parse *pcmd,
  2045. FILE *fp,
  2046. int req
  2047. )
  2048. {
  2049. u_long keyids[MAXARGS];
  2050. int i;
  2051. int items;
  2052. int itemsize;
  2053. char *dummy;
  2054. int ritems;
  2055. int res;
  2056. ritems = 0;
  2057. for (i = 0; i < pcmd->nargs; i++) {
  2058. keyids[ritems++] = pcmd->argval[i].uval;
  2059. }
  2060. again:
  2061. res = doquery(impl_ver, req, 1, ritems, sizeof(u_long),
  2062. (char *)keyids, &items, &itemsize, &dummy, 0,
  2063. sizeof(dummy));
  2064. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  2065. impl_ver = IMPL_XNTPD_OLD;
  2066. goto again;
  2067. }
  2068. if (res == 0)
  2069. (void) fprintf(fp, "done!\n");
  2070. return;
  2071. }
  2072. /*
  2073. * authinfo - obtain and print info about authentication
  2074. */
  2075. /*ARGSUSED*/
  2076. static void
  2077. authinfo(
  2078. struct parse *pcmd,
  2079. FILE *fp
  2080. )
  2081. {
  2082. struct info_auth *ia;
  2083. int items;
  2084. int itemsize;
  2085. int res;
  2086. again:
  2087. res = doquery(impl_ver, REQ_AUTHINFO, 0, 0, 0, (char *)NULL,
  2088. &items, &itemsize, (void *)&ia, 0,
  2089. sizeof(struct info_auth));
  2090. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  2091. impl_ver = IMPL_XNTPD_OLD;
  2092. goto again;
  2093. }
  2094. if (res != 0)
  2095. return;
  2096. if (!check1item(items, fp))
  2097. return;
  2098. if (!checkitemsize(itemsize, sizeof(struct info_auth)))
  2099. return;
  2100. (void) fprintf(fp, "time since reset: %ld\n",
  2101. (u_long)ntohl(ia->timereset));
  2102. (void) fprintf(fp, "stored keys: %ld\n",
  2103. (u_long)ntohl(ia->numkeys));
  2104. (void) fprintf(fp, "free keys: %ld\n",
  2105. (u_long)ntohl(ia->numfreekeys));
  2106. (void) fprintf(fp, "key lookups: %ld\n",
  2107. (u_long)ntohl(ia->keylookups));
  2108. (void) fprintf(fp, "keys not found: %ld\n",
  2109. (u_long)ntohl(ia->keynotfound));
  2110. (void) fprintf(fp, "uncached keys: %ld\n",
  2111. (u_long)ntohl(ia->keyuncached));
  2112. (void) fprintf(fp, "encryptions: %ld\n",
  2113. (u_long)ntohl(ia->encryptions));
  2114. (void) fprintf(fp, "decryptions: %ld\n",
  2115. (u_long)ntohl(ia->decryptions));
  2116. (void) fprintf(fp, "expired keys: %ld\n",
  2117. (u_long)ntohl(ia->expired));
  2118. }
  2119. /*
  2120. * traps - obtain and print a list of traps
  2121. */
  2122. /*ARGSUSED*/
  2123. static void
  2124. traps(
  2125. struct parse *pcmd,
  2126. FILE *fp
  2127. )
  2128. {
  2129. int i;
  2130. struct info_trap *it;
  2131. struct sockaddr_storage trap_addr, local_addr;
  2132. int items;
  2133. int itemsize;
  2134. int res;
  2135. again:
  2136. res = doquery(impl_ver, REQ_TRAPS, 0, 0, 0, (char *)NULL,
  2137. &items, &itemsize, (void *)&it, 0,
  2138. sizeof(struct info_trap));
  2139. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  2140. impl_ver = IMPL_XNTPD_OLD;
  2141. goto again;
  2142. }
  2143. if (res != 0)
  2144. return;
  2145. if (!checkitems(items, fp))
  2146. return;
  2147. if (!checkitemsize(itemsize, sizeof(struct info_trap)) &&
  2148. !checkitemsize(itemsize, v4sizeof(struct info_trap)))
  2149. return;
  2150. for (i = 0; i < items; i++ ) {
  2151. if (i != 0)
  2152. (void) fprintf(fp, "\n");
  2153. memset((char *)&trap_addr, 0, sizeof(trap_addr));
  2154. memset((char *)&local_addr, 0, sizeof(local_addr));
  2155. if (it->v6_flag != 0) {
  2156. GET_INADDR6(trap_addr) = it->trap_address6;
  2157. GET_INADDR6(local_addr) = it->local_address6;
  2158. trap_addr.ss_family = AF_INET6;
  2159. local_addr.ss_family = AF_INET6;
  2160. } else {
  2161. GET_INADDR(trap_addr) = it->trap_address;
  2162. GET_INADDR(local_addr) = it->local_address;
  2163. trap_addr.ss_family = AF_INET;
  2164. local_addr.ss_family = AF_INET;
  2165. }
  2166. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  2167. trap_addr.ss_len = SOCKLEN(&trap_addr);
  2168. local_addr.ss_len = SOCKLEN(&local_addr);
  2169. #endif
  2170. (void) fprintf(fp, "address %s, port %d\n",
  2171. stoa(&trap_addr),
  2172. ntohs(it->trap_port));
  2173. (void) fprintf(fp, "interface: %s, ",
  2174. (it->local_address == 0)
  2175. ? "wildcard"
  2176. : stoa(&local_addr));
  2177. if (ntohl(it->flags) & TRAP_CONFIGURED)
  2178. (void) fprintf(fp, "configured\n");
  2179. else if (ntohl(it->flags) & TRAP_NONPRIO)
  2180. (void) fprintf(fp, "low priority\n");
  2181. else
  2182. (void) fprintf(fp, "normal priority\n");
  2183. (void) fprintf(fp, "set for %ld secs, last set %ld secs ago\n",
  2184. (long)ntohl(it->origtime),
  2185. (long)ntohl(it->settime));
  2186. (void) fprintf(fp, "sequence %d, number of resets %ld\n",
  2187. ntohs(it->sequence),
  2188. (long)ntohl(it->resets));
  2189. }
  2190. }
  2191. /*
  2192. * addtrap - configure a trap
  2193. */
  2194. static void
  2195. addtrap(
  2196. struct parse *pcmd,
  2197. FILE *fp
  2198. )
  2199. {
  2200. do_addclr_trap(pcmd, fp, REQ_ADD_TRAP);
  2201. }
  2202. /*
  2203. * clrtrap - clear a trap from the server
  2204. */
  2205. static void
  2206. clrtrap(
  2207. struct parse *pcmd,
  2208. FILE *fp
  2209. )
  2210. {
  2211. do_addclr_trap(pcmd, fp, REQ_CLR_TRAP);
  2212. }
  2213. /*
  2214. * do_addclr_trap - do grunge work of adding/deleting traps
  2215. */
  2216. static void
  2217. do_addclr_trap(
  2218. struct parse *pcmd,
  2219. FILE *fp,
  2220. int req
  2221. )
  2222. {
  2223. struct conf_trap ctrap;
  2224. int items;
  2225. int itemsize;
  2226. char *dummy;
  2227. int res;
  2228. int sendsize;
  2229. again:
  2230. if (impl_ver == IMPL_XNTPD)
  2231. sendsize = sizeof(struct conf_trap);
  2232. else
  2233. sendsize = v4sizeof(struct conf_trap);
  2234. if (pcmd->argval[0].netnum.ss_family == AF_INET) {
  2235. ctrap.trap_address = GET_INADDR(pcmd->argval[0].netnum);
  2236. if (impl_ver == IMPL_XNTPD)
  2237. ctrap.v6_flag = 0;
  2238. } else {
  2239. if (impl_ver == IMPL_XNTPD_OLD) {
  2240. fprintf(stderr,
  2241. "***Server doesn't understand IPv6 addresses\n");
  2242. return;
  2243. }
  2244. ctrap.trap_address6 = GET_INADDR6(pcmd->argval[0].netnum);
  2245. ctrap.v6_flag = 1;
  2246. }
  2247. ctrap.local_address = 0;
  2248. ctrap.trap_port = htons(TRAPPORT);
  2249. ctrap.unused = 0;
  2250. if (pcmd->nargs > 1) {
  2251. ctrap.trap_port
  2252. = htons((u_short)(pcmd->argval[1].uval & 0xffff));
  2253. if (pcmd->nargs > 2) {
  2254. if (pcmd->argval[2].netnum.ss_family !=
  2255. pcmd->argval[0].netnum.ss_family) {
  2256. fprintf(stderr,
  2257. "***Cannot mix IPv4 and IPv6 addresses\n");
  2258. return;
  2259. }
  2260. if (pcmd->argval[2].netnum.ss_family == AF_INET)
  2261. ctrap.local_address = GET_INADDR(pcmd->argval[2].netnum);
  2262. else
  2263. ctrap.local_address6 = GET_INADDR6(pcmd->argval[2].netnum);
  2264. }
  2265. }
  2266. res = doquery(impl_ver, req, 1, 1, sendsize,
  2267. (char *)&ctrap, &items, &itemsize, &dummy, 0,
  2268. sizeof(struct conf_trap));
  2269. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  2270. impl_ver = IMPL_XNTPD_OLD;
  2271. goto again;
  2272. }
  2273. if (res == 0)
  2274. (void) fprintf(fp, "done!\n");
  2275. return;
  2276. }
  2277. /*
  2278. * requestkey - change the server's request key (a dangerous request)
  2279. */
  2280. static void
  2281. requestkey(
  2282. struct parse *pcmd,
  2283. FILE *fp
  2284. )
  2285. {
  2286. do_changekey(pcmd, fp, REQ_REQUEST_KEY);
  2287. }
  2288. /*
  2289. * controlkey - change the server's control key
  2290. */
  2291. static void
  2292. controlkey(
  2293. struct parse *pcmd,
  2294. FILE *fp
  2295. )
  2296. {
  2297. do_changekey(pcmd, fp, REQ_CONTROL_KEY);
  2298. }
  2299. /*
  2300. * do_changekey - do grunge work of changing keys
  2301. */
  2302. static void
  2303. do_changekey(
  2304. struct parse *pcmd,
  2305. FILE *fp,
  2306. int req
  2307. )
  2308. {
  2309. u_long key;
  2310. int items;
  2311. int itemsize;
  2312. char *dummy;
  2313. int res;
  2314. key = htonl((u_int32)pcmd->argval[0].uval);
  2315. again:
  2316. res = doquery(impl_ver, req, 1, 1, sizeof(u_int32),
  2317. (char *)&key, &items, &itemsize, &dummy, 0,
  2318. sizeof(dummy));
  2319. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  2320. impl_ver = IMPL_XNTPD_OLD;
  2321. goto again;
  2322. }
  2323. if (res == 0)
  2324. (void) fprintf(fp, "done!\n");
  2325. return;
  2326. }
  2327. /*
  2328. * ctlstats - obtain and print info about authentication
  2329. */
  2330. /*ARGSUSED*/
  2331. static void
  2332. ctlstats(
  2333. struct parse *pcmd,
  2334. FILE *fp
  2335. )
  2336. {
  2337. struct info_control *ic;
  2338. int items;
  2339. int itemsize;
  2340. int res;
  2341. again:
  2342. res = doquery(impl_ver, REQ_GET_CTLSTATS, 0, 0, 0, (char *)NULL,
  2343. &items, &itemsize, (void *)&ic, 0,
  2344. sizeof(struct info_control));
  2345. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  2346. impl_ver = IMPL_XNTPD_OLD;
  2347. goto again;
  2348. }
  2349. if (res != 0)
  2350. return;
  2351. if (!check1item(items, fp))
  2352. return;
  2353. if (!checkitemsize(itemsize, sizeof(struct info_control)))
  2354. return;
  2355. (void) fprintf(fp, "time since reset: %ld\n",
  2356. (u_long)ntohl(ic->ctltimereset));
  2357. (void) fprintf(fp, "requests received: %ld\n",
  2358. (u_long)ntohl(ic->numctlreq));
  2359. (void) fprintf(fp, "responses sent: %ld\n",
  2360. (u_long)ntohl(ic->numctlresponses));
  2361. (void) fprintf(fp, "fragments sent: %ld\n",
  2362. (u_long)ntohl(ic->numctlfrags));
  2363. (void) fprintf(fp, "async messages sent: %ld\n",
  2364. (u_long)ntohl(ic->numasyncmsgs));
  2365. (void) fprintf(fp, "error msgs sent: %ld\n",
  2366. (u_long)ntohl(ic->numctlerrors));
  2367. (void) fprintf(fp, "total bad pkts: %ld\n",
  2368. (u_long)ntohl(ic->numctlbadpkts));
  2369. (void) fprintf(fp, "packet too short: %ld\n",
  2370. (u_long)ntohl(ic->numctltooshort));
  2371. (void) fprintf(fp, "response on input: %ld\n",
  2372. (u_long)ntohl(ic->numctlinputresp));
  2373. (void) fprintf(fp, "fragment on input: %ld\n",
  2374. (u_long)ntohl(ic->numctlinputfrag));
  2375. (void) fprintf(fp, "error set on input: %ld\n",
  2376. (u_long)ntohl(ic->numctlinputerr));
  2377. (void) fprintf(fp, "bad offset on input: %ld\n",
  2378. (u_long)ntohl(ic->numctlbadoffset));
  2379. (void) fprintf(fp, "bad version packets: %ld\n",
  2380. (u_long)ntohl(ic->numctlbadversion));
  2381. (void) fprintf(fp, "data in pkt too short: %ld\n",
  2382. (u_long)ntohl(ic->numctldatatooshort));
  2383. (void) fprintf(fp, "unknown op codes: %ld\n",
  2384. (u_long)ntohl(ic->numctlbadop));
  2385. }
  2386. /*
  2387. * clockstat - get and print clock status information
  2388. */
  2389. static void
  2390. clockstat(
  2391. struct parse *pcmd,
  2392. FILE *fp
  2393. )
  2394. {
  2395. struct info_clock *cl;
  2396. /* 8 is the maximum number of clocks which will fit in a packet */
  2397. u_long clist[min(MAXARGS, 8)];
  2398. int qitems;
  2399. int items;
  2400. int itemsize;
  2401. int res;
  2402. l_fp ts;
  2403. struct clktype *clk;
  2404. for (qitems = 0; qitems < min(pcmd->nargs, 8); qitems++)
  2405. clist[qitems] = GET_INADDR(pcmd->argval[qitems].netnum);
  2406. again:
  2407. res = doquery(impl_ver, REQ_GET_CLOCKINFO, 0, qitems,
  2408. sizeof(u_int32), (char *)clist, &items,
  2409. &itemsize, (void *)&cl, 0, sizeof(struct info_clock));
  2410. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  2411. impl_ver = IMPL_XNTPD_OLD;
  2412. goto again;
  2413. }
  2414. if (res != 0)
  2415. return;
  2416. if (!checkitems(items, fp))
  2417. return;
  2418. if (!checkitemsize(itemsize, sizeof(struct info_clock)))
  2419. return;
  2420. while (items-- > 0) {
  2421. (void) fprintf(fp, "clock address: %s\n",
  2422. numtoa(cl->clockadr));
  2423. for (clk = clktypes; clk->code >= 0; clk++)
  2424. if (clk->code == cl->type)
  2425. break;
  2426. if (clk->code >= 0)
  2427. (void) fprintf(fp, "clock type: %s\n",
  2428. clk->clocktype);
  2429. else
  2430. (void) fprintf(fp, "clock type: unknown type (%d)\n",
  2431. cl->type);
  2432. (void) fprintf(fp, "last event: %d\n",
  2433. cl->lastevent);
  2434. (void) fprintf(fp, "current status: %d\n",
  2435. cl->currentstatus);
  2436. (void) fprintf(fp, "number of polls: %lu\n",
  2437. (u_long)ntohl(cl->polls));
  2438. (void) fprintf(fp, "no response to poll: %lu\n",
  2439. (u_long)ntohl(cl->noresponse));
  2440. (void) fprintf(fp, "bad format responses: %lu\n",
  2441. (u_long)ntohl(cl->badformat));
  2442. (void) fprintf(fp, "bad data responses: %lu\n",
  2443. (u_long)ntohl(cl->baddata));
  2444. (void) fprintf(fp, "running time: %lu\n",
  2445. (u_long)ntohl(cl->timestarted));
  2446. NTOHL_FP(&cl->fudgetime1, &ts);
  2447. (void) fprintf(fp, "fudge time 1: %s\n",
  2448. lfptoa(&ts, 6));
  2449. NTOHL_FP(&cl->fudgetime2, &ts);
  2450. (void) fprintf(fp, "fudge time 2: %s\n",
  2451. lfptoa(&ts, 6));
  2452. (void) fprintf(fp, "stratum: %ld\n",
  2453. (u_long)ntohl(cl->fudgeval1));
  2454. (void) fprintf(fp, "reference ID: %s\n",
  2455. refid_string(ntohl(cl->fudgeval2), 0));
  2456. (void) fprintf(fp, "fudge flags: 0x%x\n",
  2457. cl->flags);
  2458. if (items > 0)
  2459. (void) fprintf(fp, "\n");
  2460. cl++;
  2461. }
  2462. }
  2463. /*
  2464. * fudge - set clock fudge factors
  2465. */
  2466. static void
  2467. fudge(
  2468. struct parse *pcmd,
  2469. FILE *fp
  2470. )
  2471. {
  2472. struct conf_fudge fudgedata;
  2473. int items;
  2474. int itemsize;
  2475. char *dummy;
  2476. l_fp ts;
  2477. int res;
  2478. long val;
  2479. u_long u_val;
  2480. int err;
  2481. err = 0;
  2482. memset((char *)&fudgedata, 0, sizeof fudgedata);
  2483. fudgedata.clockadr = GET_INADDR(pcmd->argval[0].netnum);
  2484. if (STREQ(pcmd->argval[1].string, "time1")) {
  2485. fudgedata.which = htonl(FUDGE_TIME1);
  2486. if (!atolfp(pcmd->argval[2].string, &ts))
  2487. err = 1;
  2488. else
  2489. NTOHL_FP(&ts, &fudgedata.fudgetime);
  2490. } else if (STREQ(pcmd->argval[1].string, "time2")) {
  2491. fudgedata.which = htonl(FUDGE_TIME2);
  2492. if (!atolfp(pcmd->argval[2].string, &ts))
  2493. err = 1;
  2494. else
  2495. NTOHL_FP(&ts, &fudgedata.fudgetime);
  2496. } else if (STREQ(pcmd->argval[1].string, "val1")) {
  2497. fudgedata.which = htonl(FUDGE_VAL1);
  2498. if (!atoint(pcmd->argval[2].string, &val))
  2499. err = 1;
  2500. else
  2501. fudgedata.fudgeval_flags = htonl(val);
  2502. } else if (STREQ(pcmd->argval[1].string, "val2")) {
  2503. fudgedata.which = htonl(FUDGE_VAL2);
  2504. if (!atoint(pcmd->argval[2].string, &val))
  2505. err = 1;
  2506. else
  2507. fudgedata.fudgeval_flags = htonl((u_int32)val);
  2508. } else if (STREQ(pcmd->argval[1].string, "flags")) {
  2509. fudgedata.which = htonl(FUDGE_FLAGS);
  2510. if (!hextoint(pcmd->argval[2].string, &u_val))
  2511. err = 1;
  2512. else
  2513. fudgedata.fudgeval_flags = htonl((u_int32)(u_val & 0xf));
  2514. } else {
  2515. (void) fprintf(stderr, "What fudge is %s?\n",
  2516. pcmd->argval[1].string);
  2517. return;
  2518. }
  2519. if (err) {
  2520. (void) fprintf(stderr, "Unknown fudge parameter %s\n",
  2521. pcmd->argval[2].string);
  2522. return;
  2523. }
  2524. again:
  2525. res = doquery(impl_ver, REQ_SET_CLKFUDGE, 1, 1,
  2526. sizeof(struct conf_fudge), (char *)&fudgedata, &items,
  2527. &itemsize, &dummy, 0, sizeof(dummy));
  2528. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  2529. impl_ver = IMPL_XNTPD_OLD;
  2530. goto again;
  2531. }
  2532. if (res == 0)
  2533. (void) fprintf(fp, "done!\n");
  2534. return;
  2535. }
  2536. /*
  2537. * clkbug - get and print clock debugging information
  2538. */
  2539. static void
  2540. clkbug(
  2541. struct parse *pcmd,
  2542. FILE *fp
  2543. )
  2544. {
  2545. register int i;
  2546. register int n;
  2547. register u_int32 s;
  2548. struct info_clkbug *cl;
  2549. /* 8 is the maximum number of clocks which will fit in a packet */
  2550. u_long clist[min(MAXARGS, 8)];
  2551. u_int32 ltemp;
  2552. int qitems;
  2553. int items;
  2554. int itemsize;
  2555. int res;
  2556. int needsp;
  2557. l_fp ts;
  2558. for (qitems = 0; qitems < min(pcmd->nargs, 8); qitems++)
  2559. clist[qitems] = GET_INADDR(pcmd->argval[qitems].netnum);
  2560. again:
  2561. res = doquery(impl_ver, REQ_GET_CLKBUGINFO, 0, qitems,
  2562. sizeof(u_int32), (char *)clist, &items,
  2563. &itemsize, (void *)&cl, 0, sizeof(struct info_clkbug));
  2564. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  2565. impl_ver = IMPL_XNTPD_OLD;
  2566. goto again;
  2567. }
  2568. if (res != 0)
  2569. return;
  2570. if (!checkitems(items, fp))
  2571. return;
  2572. if (!checkitemsize(itemsize, sizeof(struct info_clkbug)))
  2573. return;
  2574. while (items-- > 0) {
  2575. (void) fprintf(fp, "clock address: %s\n",
  2576. numtoa(cl->clockadr));
  2577. n = (int)cl->nvalues;
  2578. (void) fprintf(fp, "values: %d", n);
  2579. s = ntohs(cl->svalues);
  2580. if (n > NUMCBUGVALUES)
  2581. n = NUMCBUGVALUES;
  2582. for (i = 0; i < n; i++) {
  2583. ltemp = ntohl(cl->values[i]);
  2584. ltemp &= 0xffffffff; /* HMS: This does nothing now */
  2585. if ((i & 0x3) == 0)
  2586. (void) fprintf(fp, "\n");
  2587. if (s & (1 << i))
  2588. (void) fprintf(fp, "%12ld", (u_long)ltemp);
  2589. else
  2590. (void) fprintf(fp, "%12lu", (u_long)ltemp);
  2591. }
  2592. (void) fprintf(fp, "\n");
  2593. n = (int)cl->ntimes;
  2594. (void) fprintf(fp, "times: %d", n);
  2595. s = ntohl(cl->stimes);
  2596. if (n > NUMCBUGTIMES)
  2597. n = NUMCBUGTIMES;
  2598. needsp = 0;
  2599. for (i = 0; i < n; i++) {
  2600. if ((i & 0x1) == 0) {
  2601. (void) fprintf(fp, "\n");
  2602. } else {
  2603. for (;needsp > 0; needsp--)
  2604. putc(' ', fp);
  2605. }
  2606. NTOHL_FP(&cl->times[i], &ts);
  2607. if (s & (1 << i)) {
  2608. (void) fprintf(fp, "%17s",
  2609. lfptoa(&ts, 6));
  2610. needsp = 22;
  2611. } else {
  2612. (void) fprintf(fp, "%37s",
  2613. uglydate(&ts));
  2614. needsp = 2;
  2615. }
  2616. }
  2617. (void) fprintf(fp, "\n");
  2618. if (items > 0) {
  2619. cl++;
  2620. (void) fprintf(fp, "\n");
  2621. }
  2622. }
  2623. }
  2624. /*
  2625. * kerninfo - display the kernel pll/pps variables
  2626. */
  2627. static void
  2628. kerninfo(
  2629. struct parse *pcmd,
  2630. FILE *fp
  2631. )
  2632. {
  2633. struct info_kernel *ik;
  2634. int items;
  2635. int itemsize;
  2636. int res;
  2637. unsigned status;
  2638. double tscale = 1e-6;
  2639. again:
  2640. res = doquery(impl_ver, REQ_GET_KERNEL, 0, 0, 0, (char *)NULL,
  2641. &items, &itemsize, (void *)&ik, 0,
  2642. sizeof(struct info_kernel));
  2643. if (res == INFO_ERR_IMPL && impl_ver == IMPL_XNTPD) {
  2644. impl_ver = IMPL_XNTPD_OLD;
  2645. goto again;
  2646. }
  2647. if (res != 0)
  2648. return;
  2649. if (!check1item(items, fp))
  2650. return;
  2651. if (!checkitemsize(itemsize, sizeof(struct info_kernel)))
  2652. return;
  2653. status = ntohs(ik->status) & 0xffff;
  2654. /*
  2655. * pll variables. We know more than we should about the NANO bit.
  2656. */
  2657. #ifdef STA_NANO
  2658. if (status & STA_NANO)
  2659. tscale = 1e-9;
  2660. #endif
  2661. (void)fprintf(fp, "pll offset: %g s\n",
  2662. (int32_t)ntohl(ik->offset) * tscale);
  2663. (void)fprintf(fp, "pll frequency: %s ppm\n",
  2664. fptoa((s_fp)ntohl(ik->freq), 3));
  2665. (void)fprintf(fp, "maximum error: %g s\n",
  2666. (u_long)ntohl(ik->maxerror) * 1e-6);
  2667. (void)fprintf(fp, "estimated error: %g s\n",
  2668. (u_long)ntohl(ik->esterror) * 1e-6);
  2669. (void)fprintf(fp, "status: %04x ", status);
  2670. #ifdef STA_PLL
  2671. if (status & STA_PLL) (void)fprintf(fp, " pll");
  2672. #endif
  2673. #ifdef STA_PPSFREQ
  2674. if (status & STA_PPSFREQ) (void)fprintf(fp, " ppsfreq");
  2675. #endif
  2676. #ifdef STA_PPSTIME
  2677. if (status & STA_PPSTIME) (void)fprintf(fp, " ppstime");
  2678. #endif
  2679. #ifdef STA_FLL
  2680. if (status & STA_FLL) (void)fprintf(fp, " fll");
  2681. #endif
  2682. #ifdef STA_INS
  2683. if (status & STA_INS) (void)fprintf(fp, " ins");
  2684. #endif
  2685. #ifdef STA_DEL
  2686. if (status & STA_DEL) (void)fprintf(fp, " del");
  2687. #endif
  2688. #ifdef STA_UNSYNC
  2689. if (status & STA_UNSYNC) (void)fprintf(fp, " unsync");
  2690. #endif
  2691. #ifdef STA_FREQHOLD
  2692. if (status & STA_FREQHOLD) (void)fprintf(fp, " freqhold");
  2693. #endif
  2694. #ifdef STA_PPSSIGNAL
  2695. if (status & STA_PPSSIGNAL) (void)fprintf(fp, " ppssignal");
  2696. #endif
  2697. #ifdef STA_PPSJITTER
  2698. if (status & STA_PPSJITTER) (void)fprintf(fp, " ppsjitter");
  2699. #endif
  2700. #ifdef STA_PPSWANDER
  2701. if (status & STA_PPSWANDER) (void)fprintf(fp, " ppswander");
  2702. #endif
  2703. #ifdef STA_PPSERROR
  2704. if (status & STA_PPSERROR) (void)fprintf(fp, " ppserror");
  2705. #endif
  2706. #ifdef STA_CLOCKERR
  2707. if (status & STA_CLOCKERR) (void)fprintf(fp, " clockerr");
  2708. #endif
  2709. #ifdef STA_NANO
  2710. if (status & STA_NANO) (void)fprintf(fp, " nano");
  2711. #endif
  2712. #ifdef STA_MODE
  2713. if (status & STA_MODE) (void)fprintf(fp, " mode=fll");
  2714. #endif
  2715. #ifdef STA_CLK
  2716. if (status & STA_CLK) (void)fprintf(fp, " src=B");
  2717. #endif
  2718. (void)fprintf(fp, "\n");
  2719. (void)fprintf(fp, "pll time constant: %ld\n",
  2720. (u_long)ntohl(ik->constant));
  2721. (void)fprintf(fp, "precision: %g s\n",
  2722. (u_long)ntohl(ik->precision) * tscale);
  2723. (void)fprintf(fp, "frequency tolerance: %s ppm\n",
  2724. fptoa((s_fp)ntohl(ik->tolerance), 0));
  2725. /*
  2726. * For backwards compatibility (ugh), we find the pps variables
  2727. * only if the shift member is nonzero.
  2728. */
  2729. if (!ik->shift)
  2730. return;
  2731. /*
  2732. * pps variables
  2733. */
  2734. (void)fprintf(fp, "pps frequency: %s ppm\n",
  2735. fptoa((s_fp)ntohl(ik->ppsfreq), 3));
  2736. (void)fprintf(fp, "pps stability: %s ppm\n",
  2737. fptoa((s_fp)ntohl(ik->stabil), 3));
  2738. (void)fprintf(fp, "pps jitter: %g s\n",
  2739. (u_long)ntohl(ik->jitter) * tscale);
  2740. (void)fprintf(fp, "calibration interval: %d s\n",
  2741. 1 << ntohs(ik->shift));
  2742. (void)fprintf(fp, "calibration cycles: %ld\n",
  2743. (u_long)ntohl(ik->calcnt));
  2744. (void)fprintf(fp, "jitter exceeded: %ld\n",
  2745. (u_long)ntohl(ik->jitcnt));
  2746. (void)fprintf(fp, "stability exceeded: %ld\n",
  2747. (u_long)ntohl(ik->stbcnt));
  2748. (void)fprintf(fp, "calibration errors: %ld\n",
  2749. (u_long)ntohl(ik->errcnt));
  2750. }
  2751. #define IF_LIST_FMT "%2d %c %48s %c %c %12.12s %03x %3d %2d %5d %5d %5d %2d %2d %3d %7d\n"
  2752. #define IF_LIST_FMT_STR "%2s %c %48s %c %c %12.12s %3s %3s %2s %5s %5s %5s %2s %2s %3s %7s\n"
  2753. #define IF_LIST_AFMT_STR " %48s %c\n"
  2754. #define IF_LIST_LABELS "#", 'A', "Address/Mask/Broadcast", 'T', 'E', "IF name", "Flg", "TL", "#M", "recv", "sent", "drop", "S", "IX", "PC", "uptime"
  2755. #define IF_LIST_LINE "=====================================================================================================================\n"
  2756. static void
  2757. iflist(
  2758. FILE *fp,
  2759. struct info_if_stats *ifs,
  2760. int items,
  2761. int itemsize,
  2762. int res
  2763. )
  2764. {
  2765. static char *actions = "?.+-";
  2766. struct sockaddr_storage saddr;
  2767. if (res != 0)
  2768. return;
  2769. if (!checkitems(items, fp))
  2770. return;
  2771. if (!checkitemsize(itemsize, sizeof(struct info_if_stats)))
  2772. return;
  2773. fprintf(fp, IF_LIST_FMT_STR, IF_LIST_LABELS);
  2774. fprintf(fp, IF_LIST_LINE);
  2775. while (items > 0) {
  2776. if (ntohl(ifs->v6_flag)) {
  2777. memcpy((char *)&GET_INADDR6(saddr), (char *)&ifs->unaddr.addr6, sizeof(ifs->unaddr.addr6));
  2778. saddr.ss_family = AF_INET6;
  2779. } else {
  2780. memcpy((char *)&GET_INADDR(saddr), (char *)&ifs->unaddr.addr, sizeof(ifs->unaddr.addr));
  2781. saddr.ss_family = AF_INET;
  2782. }
  2783. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  2784. saddr.ss_len = SOCKLEN(&saddr);
  2785. #endif
  2786. fprintf(fp, IF_LIST_FMT,
  2787. ntohl(ifs->ifnum),
  2788. actions[(ifs->action >= 1 && ifs->action < 4) ? ifs->action : 0],
  2789. stoa((&saddr)), 'A',
  2790. ifs->ignore_packets ? 'D' : 'E',
  2791. ifs->name,
  2792. ntohl(ifs->flags),
  2793. ntohl(ifs->last_ttl),
  2794. ntohl(ifs->num_mcast),
  2795. ntohl(ifs->received),
  2796. ntohl(ifs->sent),
  2797. ntohl(ifs->notsent),
  2798. ntohl(ifs->scopeid),
  2799. ntohl(ifs->ifindex),
  2800. ntohl(ifs->peercnt),
  2801. ntohl(ifs->uptime));
  2802. if (ntohl(ifs->v6_flag)) {
  2803. memcpy((char *)&GET_INADDR6(saddr), (char *)&ifs->unmask.addr6, sizeof(ifs->unmask.addr6));
  2804. saddr.ss_family = AF_INET6;
  2805. } else {
  2806. memcpy((char *)&GET_INADDR(saddr), (char *)&ifs->unmask.addr, sizeof(ifs->unmask.addr));
  2807. saddr.ss_family = AF_INET;
  2808. }
  2809. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  2810. saddr.ss_len = SOCKLEN(&saddr);
  2811. #endif
  2812. fprintf(fp, IF_LIST_AFMT_STR, stoa(&saddr), 'M');
  2813. if (!ntohl(ifs->v6_flag) && ntohl(ifs->flags) & (INT_BCASTOPEN)) {
  2814. memcpy((char *)&GET_INADDR(saddr), (char *)&ifs->unbcast.addr, sizeof(ifs->unbcast.addr));
  2815. saddr.ss_family = AF_INET;
  2816. #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
  2817. saddr.ss_len = SOCKLEN(&saddr);
  2818. #endif
  2819. fprintf(fp, IF_LIST_AFMT_STR, stoa(&saddr), 'B');
  2820. }
  2821. ifs++;
  2822. items--;
  2823. }
  2824. }
  2825. /*ARGSUSED*/
  2826. static void
  2827. get_if_stats(
  2828. struct parse *pcmd,
  2829. FILE *fp
  2830. )
  2831. {
  2832. struct info_if_stats *ifs;
  2833. int items;
  2834. int itemsize;
  2835. int res;
  2836. res = doquery(impl_ver, REQ_IF_STATS, 1, 0, 0, (char *)NULL, &items,
  2837. &itemsize, (void *)&ifs, 0,
  2838. sizeof(struct info_if_stats));
  2839. iflist(fp, ifs, items, itemsize, res);
  2840. }
  2841. /*ARGSUSED*/
  2842. static void
  2843. do_if_reload(
  2844. struct parse *pcmd,
  2845. FILE *fp
  2846. )
  2847. {
  2848. struct info_if_stats *ifs;
  2849. int items;
  2850. int itemsize;
  2851. int res;
  2852. res = doquery(impl_ver, REQ_IF_RELOAD, 1, 0, 0, (char *)NULL, &items,
  2853. &itemsize, (void *)&ifs, 0,
  2854. sizeof(struct info_if_stats));
  2855. iflist(fp, ifs, items, itemsize, res);
  2856. }