/contrib/ntp/ntpq/ntpq-subs.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1768 lines · 1381 code · 202 blank · 185 comment · 308 complexity · 7c8e2ff6e32af5485776a9dff2cc41b2 MD5 · raw file

  1. /*
  2. * ntpq_ops.c - subroutines which are called to perform operations by ntpq
  3. */
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include <sys/types.h>
  7. #include <sys/time.h>
  8. #include "ntpq.h"
  9. #include "ntp_stdlib.h"
  10. extern char * chosts[];
  11. extern char currenthost[];
  12. extern int numhosts;
  13. int maxhostlen;
  14. /*
  15. * Declarations for command handlers in here
  16. */
  17. static int checkassocid P((u_int32));
  18. static char * strsave P((char *));
  19. static struct varlist *findlistvar P((struct varlist *, char *));
  20. static void doaddvlist P((struct varlist *, char *));
  21. static void dormvlist P((struct varlist *, char *));
  22. static void doclearvlist P((struct varlist *));
  23. static void makequerydata P((struct varlist *, int *, char *));
  24. static int doquerylist P((struct varlist *, int, int, int, u_short *, int *, char **));
  25. static void doprintvlist P((struct varlist *, FILE *));
  26. static void addvars P((struct parse *, FILE *));
  27. static void rmvars P((struct parse *, FILE *));
  28. static void clearvars P((struct parse *, FILE *));
  29. static void showvars P((struct parse *, FILE *));
  30. static int dolist P((struct varlist *, int, int, int, FILE *));
  31. static void readlist P((struct parse *, FILE *));
  32. static void writelist P((struct parse *, FILE *));
  33. static void readvar P((struct parse *, FILE *));
  34. static void writevar P((struct parse *, FILE *));
  35. static void clocklist P((struct parse *, FILE *));
  36. static void clockvar P((struct parse *, FILE *));
  37. static int findassidrange P((u_int32, u_int32, int *, int *));
  38. static void mreadlist P((struct parse *, FILE *));
  39. static void mreadvar P((struct parse *, FILE *));
  40. static int dogetassoc P((FILE *));
  41. static void printassoc P((int, FILE *));
  42. static void associations P((struct parse *, FILE *));
  43. static void lassociations P((struct parse *, FILE *));
  44. static void passociations P((struct parse *, FILE *));
  45. static void lpassociations P((struct parse *, FILE *));
  46. #ifdef UNUSED
  47. static void radiostatus P((struct parse *, FILE *));
  48. #endif /* UNUSED */
  49. static void pstatus P((struct parse *, FILE *));
  50. static long when P((l_fp *, l_fp *, l_fp *));
  51. static char * prettyinterval P((char *, long));
  52. static int doprintpeers P((struct varlist *, int, int, int, char *, FILE *, int));
  53. static int dogetpeers P((struct varlist *, int, FILE *, int));
  54. static void dopeers P((int, FILE *, int));
  55. static void peers P((struct parse *, FILE *));
  56. static void lpeers P((struct parse *, FILE *));
  57. static void doopeers P((int, FILE *, int));
  58. static void opeers P((struct parse *, FILE *));
  59. static void lopeers P((struct parse *, FILE *));
  60. /*
  61. * Commands we understand. Ntpdc imports this.
  62. */
  63. struct xcmd opcmds[] = {
  64. { "associations", associations, { NO, NO, NO, NO },
  65. { "", "", "", "" },
  66. "print list of association ID's and statuses for the server's peers" },
  67. { "passociations", passociations, { NO, NO, NO, NO },
  68. { "", "", "", "" },
  69. "print list of associations returned by last associations command" },
  70. { "lassociations", lassociations, { NO, NO, NO, NO },
  71. { "", "", "", "" },
  72. "print list of associations including all client information" },
  73. { "lpassociations", lpassociations, { NO, NO, NO, NO },
  74. { "", "", "", "" },
  75. "print last obtained list of associations, including client information" },
  76. { "addvars", addvars, { NTP_STR, NO, NO, NO },
  77. { "name[=value][,...]", "", "", "" },
  78. "add variables to the variable list or change their values" },
  79. { "rmvars", rmvars, { NTP_STR, NO, NO, NO },
  80. { "name[,...]", "", "", "" },
  81. "remove variables from the variable list" },
  82. { "clearvars", clearvars, { NO, NO, NO, NO },
  83. { "", "", "", "" },
  84. "remove all variables from the variable list" },
  85. { "showvars", showvars, { NO, NO, NO, NO },
  86. { "", "", "", "" },
  87. "print variables on the variable list" },
  88. { "readlist", readlist, { OPT|NTP_UINT, NO, NO, NO },
  89. { "assocID", "", "", "" },
  90. "read the system or peer variables included in the variable list" },
  91. { "rl", readlist, { OPT|NTP_UINT, NO, NO, NO },
  92. { "assocID", "", "", "" },
  93. "read the system or peer variables included in the variable list" },
  94. { "writelist", writelist, { OPT|NTP_UINT, NO, NO, NO },
  95. { "assocID", "", "", "" },
  96. "write the system or peer variables included in the variable list" },
  97. { "readvar", readvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
  98. { "assocID", "name=value[,...]", "", "" },
  99. "read system or peer variables" },
  100. { "rv", readvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
  101. { "assocID", "name=value[,...]", "", "" },
  102. "read system or peer variables" },
  103. { "writevar", writevar, { NTP_UINT, NTP_STR, NO, NO },
  104. { "assocID", "name=value,[...]", "", "" },
  105. "write system or peer variables" },
  106. { "mreadlist", mreadlist, { NTP_UINT, NTP_UINT, NO, NO },
  107. { "assocID", "assocID", "", "" },
  108. "read the peer variables in the variable list for multiple peers" },
  109. { "mrl", mreadlist, { NTP_UINT, NTP_UINT, NO, NO },
  110. { "assocID", "assocID", "", "" },
  111. "read the peer variables in the variable list for multiple peers" },
  112. { "mreadvar", mreadvar, { NTP_UINT, NTP_UINT, OPT|NTP_STR, NO },
  113. { "assocID", "assocID", "name=value[,...]", "" },
  114. "read peer variables from multiple peers" },
  115. { "mrv", mreadvar, { NTP_UINT, NTP_UINT, OPT|NTP_STR, NO },
  116. { "assocID", "assocID", "name=value[,...]", "" },
  117. "read peer variables from multiple peers" },
  118. { "clocklist", clocklist, { OPT|NTP_UINT, NO, NO, NO },
  119. { "assocID", "", "", "" },
  120. "read the clock variables included in the variable list" },
  121. { "cl", clocklist, { OPT|NTP_UINT, NO, NO, NO },
  122. { "assocID", "", "", "" },
  123. "read the clock variables included in the variable list" },
  124. { "clockvar", clockvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
  125. { "assocID", "name=value[,...]", "", "" },
  126. "read clock variables" },
  127. { "cv", clockvar, { OPT|NTP_UINT, OPT|NTP_STR, NO, NO },
  128. { "assocID", "name=value[,...]", "", "" },
  129. "read clock variables" },
  130. { "pstatus", pstatus, { NTP_UINT, NO, NO, NO },
  131. { "assocID", "", "", "" },
  132. "print status information returned for a peer" },
  133. { "peers", peers, { OPT|IP_VERSION, NO, NO, NO },
  134. { "-4|-6", "", "", "" },
  135. "obtain and print a list of the server's peers [IP version]" },
  136. { "lpeers", lpeers, { OPT|IP_VERSION, NO, NO, NO },
  137. { "-4|-6", "", "", "" },
  138. "obtain and print a list of all peers and clients [IP version]" },
  139. { "opeers", opeers, { OPT|IP_VERSION, NO, NO, NO },
  140. { "-4|-6", "", "", "" },
  141. "print peer list the old way, with dstadr shown rather than refid [IP version]" },
  142. { "lopeers", lopeers, { OPT|IP_VERSION, NO, NO, NO },
  143. { "-4|-6", "", "", "" },
  144. "obtain and print a list of all peers and clients showing dstadr [IP version]" },
  145. { 0, 0, { NO, NO, NO, NO },
  146. { "-4|-6", "", "", "" }, "" }
  147. };
  148. /*
  149. * Variable list data space
  150. */
  151. #define MAXLIST 64 /* maximum number of variables in list */
  152. #define LENHOSTNAME 256 /* host name is 256 characters long */
  153. /*
  154. * Old CTL_PST defines for version 2.
  155. */
  156. #define OLD_CTL_PST_CONFIG 0x80
  157. #define OLD_CTL_PST_AUTHENABLE 0x40
  158. #define OLD_CTL_PST_AUTHENTIC 0x20
  159. #define OLD_CTL_PST_REACH 0x10
  160. #define OLD_CTL_PST_SANE 0x08
  161. #define OLD_CTL_PST_DISP 0x04
  162. #define OLD_CTL_PST_SEL_REJECT 0
  163. #define OLD_CTL_PST_SEL_SELCAND 1
  164. #define OLD_CTL_PST_SEL_SYNCCAND 2
  165. #define OLD_CTL_PST_SEL_SYSPEER 3
  166. char flash2[] = " .+* "; /* flash decode for version 2 */
  167. char flash3[] = " x.-+#*o"; /* flash decode for peer status version 3 */
  168. struct varlist {
  169. char *name;
  170. char *value;
  171. } varlist[MAXLIST] = { { 0, 0 } };
  172. /*
  173. * Imported from ntpq.c
  174. */
  175. extern int showhostnames;
  176. extern int rawmode;
  177. extern struct servent *server_entry;
  178. extern struct association assoc_cache[];
  179. extern int numassoc;
  180. extern u_char pktversion;
  181. extern struct ctl_var peer_var[];
  182. /*
  183. * For quick string comparisons
  184. */
  185. #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
  186. /*
  187. * checkassocid - return the association ID, checking to see if it is valid
  188. */
  189. static int
  190. checkassocid(
  191. u_int32 value
  192. )
  193. {
  194. if (value == 0 || value >= 65536) {
  195. (void) fprintf(stderr, "***Invalid association ID specified\n");
  196. return 0;
  197. }
  198. return (int)value;
  199. }
  200. /*
  201. * strsave - save a string
  202. * XXX - should be in libntp.a
  203. */
  204. static char *
  205. strsave(
  206. char *str
  207. )
  208. {
  209. char *cp;
  210. u_int len;
  211. len = strlen(str) + 1;
  212. if ((cp = (char *)malloc(len)) == NULL) {
  213. (void) fprintf(stderr, "Malloc failed!!\n");
  214. exit(1);
  215. }
  216. memmove(cp, str, len);
  217. return (cp);
  218. }
  219. /*
  220. * findlistvar - look for the named variable in a list and return if found
  221. */
  222. static struct varlist *
  223. findlistvar(
  224. struct varlist *list,
  225. char *name
  226. )
  227. {
  228. register struct varlist *vl;
  229. for (vl = list; vl < list + MAXLIST && vl->name != 0; vl++)
  230. if (STREQ(name, vl->name))
  231. return vl;
  232. if (vl < list + MAXLIST)
  233. return vl;
  234. return (struct varlist *)0;
  235. }
  236. /*
  237. * doaddvlist - add variable(s) to the variable list
  238. */
  239. static void
  240. doaddvlist(
  241. struct varlist *vlist,
  242. char *vars
  243. )
  244. {
  245. register struct varlist *vl;
  246. int len;
  247. char *name;
  248. char *value;
  249. len = strlen(vars);
  250. while (nextvar(&len, &vars, &name, &value)) {
  251. vl = findlistvar(vlist, name);
  252. if (vl == 0) {
  253. (void) fprintf(stderr, "Variable list full\n");
  254. return;
  255. }
  256. if (vl->name == 0) {
  257. vl->name = strsave(name);
  258. } else if (vl->value != 0) {
  259. free(vl->value);
  260. vl->value = 0;
  261. }
  262. if (value != 0)
  263. vl->value = strsave(value);
  264. }
  265. }
  266. /*
  267. * dormvlist - remove variable(s) from the variable list
  268. */
  269. static void
  270. dormvlist(
  271. struct varlist *vlist,
  272. char *vars
  273. )
  274. {
  275. register struct varlist *vl;
  276. int len;
  277. char *name;
  278. char *value;
  279. len = strlen(vars);
  280. while (nextvar(&len, &vars, &name, &value)) {
  281. vl = findlistvar(vlist, name);
  282. if (vl == 0 || vl->name == 0) {
  283. (void) fprintf(stderr, "Variable `%s' not found\n",
  284. name);
  285. } else {
  286. free((void *)vl->name);
  287. if (vl->value != 0)
  288. free(vl->value);
  289. for ( ; (vl+1) < (varlist+MAXLIST)
  290. && (vl+1)->name != 0; vl++) {
  291. vl->name = (vl+1)->name;
  292. vl->value = (vl+1)->value;
  293. }
  294. vl->name = vl->value = 0;
  295. }
  296. }
  297. }
  298. /*
  299. * doclearvlist - clear a variable list
  300. */
  301. static void
  302. doclearvlist(
  303. struct varlist *vlist
  304. )
  305. {
  306. register struct varlist *vl;
  307. for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
  308. free((void *)vl->name);
  309. vl->name = 0;
  310. if (vl->value != 0) {
  311. free(vl->value);
  312. vl->value = 0;
  313. }
  314. }
  315. }
  316. /*
  317. * makequerydata - form a data buffer to be included with a query
  318. */
  319. static void
  320. makequerydata(
  321. struct varlist *vlist,
  322. int *datalen,
  323. char *data
  324. )
  325. {
  326. register struct varlist *vl;
  327. register char *cp, *cpend;
  328. register int namelen, valuelen;
  329. register int totallen;
  330. cp = data;
  331. cpend = data + *datalen;
  332. for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
  333. namelen = strlen(vl->name);
  334. if (vl->value == 0)
  335. valuelen = 0;
  336. else
  337. valuelen = strlen(vl->value);
  338. totallen = namelen + valuelen + (valuelen != 0) + (cp != data);
  339. if (cp + totallen > cpend)
  340. break;
  341. if (cp != data)
  342. *cp++ = ',';
  343. memmove(cp, vl->name, (unsigned)namelen);
  344. cp += namelen;
  345. if (valuelen != 0) {
  346. *cp++ = '=';
  347. memmove(cp, vl->value, (unsigned)valuelen);
  348. cp += valuelen;
  349. }
  350. }
  351. *datalen = cp - data;
  352. }
  353. /*
  354. * doquerylist - send a message including variables in a list
  355. */
  356. static int
  357. doquerylist(
  358. struct varlist *vlist,
  359. int op,
  360. int associd,
  361. int auth,
  362. u_short *rstatus,
  363. int *dsize,
  364. char **datap
  365. )
  366. {
  367. char data[CTL_MAX_DATA_LEN];
  368. int datalen;
  369. datalen = sizeof(data);
  370. makequerydata(vlist, &datalen, data);
  371. return doquery(op, associd, auth, datalen, data, rstatus,
  372. dsize, datap);
  373. }
  374. /*
  375. * doprintvlist - print the variables on a list
  376. */
  377. static void
  378. doprintvlist(
  379. struct varlist *vlist,
  380. FILE *fp
  381. )
  382. {
  383. register struct varlist *vl;
  384. if (vlist->name == 0) {
  385. (void) fprintf(fp, "No variables on list\n");
  386. } else {
  387. for (vl = vlist; vl < vlist + MAXLIST && vl->name != 0; vl++) {
  388. if (vl->value == 0) {
  389. (void) fprintf(fp, "%s\n", vl->name);
  390. } else {
  391. (void) fprintf(fp, "%s=%s\n",
  392. vl->name, vl->value);
  393. }
  394. }
  395. }
  396. }
  397. /*
  398. * addvars - add variables to the variable list
  399. */
  400. /*ARGSUSED*/
  401. static void
  402. addvars(
  403. struct parse *pcmd,
  404. FILE *fp
  405. )
  406. {
  407. doaddvlist(varlist, pcmd->argval[0].string);
  408. }
  409. /*
  410. * rmvars - remove variables from the variable list
  411. */
  412. /*ARGSUSED*/
  413. static void
  414. rmvars(
  415. struct parse *pcmd,
  416. FILE *fp
  417. )
  418. {
  419. dormvlist(varlist, pcmd->argval[0].string);
  420. }
  421. /*
  422. * clearvars - clear the variable list
  423. */
  424. /*ARGSUSED*/
  425. static void
  426. clearvars(
  427. struct parse *pcmd,
  428. FILE *fp
  429. )
  430. {
  431. doclearvlist(varlist);
  432. }
  433. /*
  434. * showvars - show variables on the variable list
  435. */
  436. /*ARGSUSED*/
  437. static void
  438. showvars(
  439. struct parse *pcmd,
  440. FILE *fp
  441. )
  442. {
  443. doprintvlist(varlist, fp);
  444. }
  445. /*
  446. * dolist - send a request with the given list of variables
  447. */
  448. static int
  449. dolist(
  450. struct varlist *vlist,
  451. int associd,
  452. int op,
  453. int type,
  454. FILE *fp
  455. )
  456. {
  457. char *datap;
  458. int res;
  459. int dsize;
  460. u_short rstatus;
  461. res = doquerylist(vlist, op, associd, 0, &rstatus, &dsize, &datap);
  462. if (res != 0)
  463. return 0;
  464. if (numhosts > 1)
  465. (void) fprintf(fp, "server=%s ", currenthost);
  466. if (dsize == 0) {
  467. if (associd == 0)
  468. (void) fprintf(fp, "No system%s variables returned\n",
  469. (type == TYPE_CLOCK) ? " clock" : "");
  470. else
  471. (void) fprintf(fp,
  472. "No information returned for%s association %u\n",
  473. (type == TYPE_CLOCK) ? " clock" : "", associd);
  474. return 1;
  475. }
  476. (void) fprintf(fp,"assID=%d ",associd);
  477. printvars(dsize, datap, (int)rstatus, type, fp);
  478. return 1;
  479. }
  480. /*
  481. * readlist - send a read variables request with the variables on the list
  482. */
  483. static void
  484. readlist(
  485. struct parse *pcmd,
  486. FILE *fp
  487. )
  488. {
  489. int associd;
  490. if (pcmd->nargs == 0) {
  491. associd = 0;
  492. } else {
  493. /* HMS: I think we want the u_int32 target here, not the u_long */
  494. if (pcmd->argval[0].uval == 0)
  495. associd = 0;
  496. else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  497. return;
  498. }
  499. (void) dolist(varlist, associd, CTL_OP_READVAR,
  500. (associd == 0) ? TYPE_SYS : TYPE_PEER, fp);
  501. }
  502. /*
  503. * writelist - send a write variables request with the variables on the list
  504. */
  505. static void
  506. writelist(
  507. struct parse *pcmd,
  508. FILE *fp
  509. )
  510. {
  511. char *datap;
  512. int res;
  513. int associd;
  514. int dsize;
  515. u_short rstatus;
  516. if (pcmd->nargs == 0) {
  517. associd = 0;
  518. } else {
  519. /* HMS: Do we really want uval here? */
  520. if (pcmd->argval[0].uval == 0)
  521. associd = 0;
  522. else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  523. return;
  524. }
  525. res = doquerylist(varlist, CTL_OP_WRITEVAR, associd, 1, &rstatus,
  526. &dsize, &datap);
  527. if (res != 0)
  528. return;
  529. if (numhosts > 1)
  530. (void) fprintf(fp, "server=%s ", currenthost);
  531. if (dsize == 0)
  532. (void) fprintf(fp, "done! (no data returned)\n");
  533. else {
  534. (void) fprintf(fp,"assID=%d ",associd);
  535. printvars(dsize, datap, (int)rstatus,
  536. (associd != 0) ? TYPE_PEER : TYPE_SYS, fp);
  537. }
  538. return;
  539. }
  540. /*
  541. * readvar - send a read variables request with the specified variables
  542. */
  543. static void
  544. readvar(
  545. struct parse *pcmd,
  546. FILE *fp
  547. )
  548. {
  549. int associd;
  550. struct varlist tmplist[MAXLIST];
  551. /* HMS: uval? */
  552. if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
  553. associd = 0;
  554. else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  555. return;
  556. memset((char *)tmplist, 0, sizeof(tmplist));
  557. if (pcmd->nargs >= 2)
  558. doaddvlist(tmplist, pcmd->argval[1].string);
  559. (void) dolist(tmplist, associd, CTL_OP_READVAR,
  560. (associd == 0) ? TYPE_SYS : TYPE_PEER, fp);
  561. doclearvlist(tmplist);
  562. }
  563. /*
  564. * writevar - send a write variables request with the specified variables
  565. */
  566. static void
  567. writevar(
  568. struct parse *pcmd,
  569. FILE *fp
  570. )
  571. {
  572. char *datap;
  573. int res;
  574. int associd;
  575. int dsize;
  576. u_short rstatus;
  577. struct varlist tmplist[MAXLIST];
  578. /* HMS: uval? */
  579. if (pcmd->argval[0].uval == 0)
  580. associd = 0;
  581. else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  582. return;
  583. memset((char *)tmplist, 0, sizeof(tmplist));
  584. doaddvlist(tmplist, pcmd->argval[1].string);
  585. res = doquerylist(tmplist, CTL_OP_WRITEVAR, associd, 1, &rstatus,
  586. &dsize, &datap);
  587. doclearvlist(tmplist);
  588. if (res != 0)
  589. return;
  590. if (numhosts > 1)
  591. (void) fprintf(fp, "server=%s ", currenthost);
  592. if (dsize == 0)
  593. (void) fprintf(fp, "done! (no data returned)\n");
  594. else {
  595. (void) fprintf(fp,"assID=%d ",associd);
  596. printvars(dsize, datap, (int)rstatus,
  597. (associd != 0) ? TYPE_PEER : TYPE_SYS, fp);
  598. }
  599. return;
  600. }
  601. /*
  602. * clocklist - send a clock variables request with the variables on the list
  603. */
  604. static void
  605. clocklist(
  606. struct parse *pcmd,
  607. FILE *fp
  608. )
  609. {
  610. int associd;
  611. /* HMS: uval? */
  612. if (pcmd->nargs == 0) {
  613. associd = 0;
  614. } else {
  615. if (pcmd->argval[0].uval == 0)
  616. associd = 0;
  617. else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  618. return;
  619. }
  620. (void) dolist(varlist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
  621. }
  622. /*
  623. * clockvar - send a clock variables request with the specified variables
  624. */
  625. static void
  626. clockvar(
  627. struct parse *pcmd,
  628. FILE *fp
  629. )
  630. {
  631. int associd;
  632. struct varlist tmplist[MAXLIST];
  633. /* HMS: uval? */
  634. if (pcmd->nargs == 0 || pcmd->argval[0].uval == 0)
  635. associd = 0;
  636. else if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  637. return;
  638. memset((char *)tmplist, 0, sizeof(tmplist));
  639. if (pcmd->nargs >= 2)
  640. doaddvlist(tmplist, pcmd->argval[1].string);
  641. (void) dolist(tmplist, associd, CTL_OP_READCLOCK, TYPE_CLOCK, fp);
  642. doclearvlist(tmplist);
  643. }
  644. /*
  645. * findassidrange - verify a range of association ID's
  646. */
  647. static int
  648. findassidrange(
  649. u_int32 assid1,
  650. u_int32 assid2,
  651. int *from,
  652. int *to
  653. )
  654. {
  655. register int i;
  656. int f, t;
  657. if (assid1 == 0 || assid1 > 65535) {
  658. (void) fprintf(stderr,
  659. "***Invalid association ID %lu specified\n", (u_long)assid1);
  660. return 0;
  661. }
  662. if (assid2 == 0 || assid2 > 65535) {
  663. (void) fprintf(stderr,
  664. "***Invalid association ID %lu specified\n", (u_long)assid2);
  665. return 0;
  666. }
  667. f = t = -1;
  668. for (i = 0; i < numassoc; i++) {
  669. if (assoc_cache[i].assid == assid1) {
  670. f = i;
  671. if (t != -1)
  672. break;
  673. }
  674. if (assoc_cache[i].assid == assid2) {
  675. t = i;
  676. if (f != -1)
  677. break;
  678. }
  679. }
  680. if (f == -1 || t == -1) {
  681. (void) fprintf(stderr,
  682. "***Association ID %lu not found in list\n",
  683. (f == -1) ? (u_long)assid1 : (u_long)assid2);
  684. return 0;
  685. }
  686. if (f < t) {
  687. *from = f;
  688. *to = t;
  689. } else {
  690. *from = t;
  691. *to = f;
  692. }
  693. return 1;
  694. }
  695. /*
  696. * mreadlist - send a read variables request for multiple associations
  697. */
  698. static void
  699. mreadlist(
  700. struct parse *pcmd,
  701. FILE *fp
  702. )
  703. {
  704. int i;
  705. int from;
  706. int to;
  707. /* HMS: uval? */
  708. if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
  709. &from, &to))
  710. return;
  711. for (i = from; i <= to; i++) {
  712. if (i != from)
  713. (void) fprintf(fp, "\n");
  714. if (!dolist(varlist, (int)assoc_cache[i].assid,
  715. CTL_OP_READVAR, TYPE_PEER, fp))
  716. return;
  717. }
  718. return;
  719. }
  720. /*
  721. * mreadvar - send a read variables request for multiple associations
  722. */
  723. static void
  724. mreadvar(
  725. struct parse *pcmd,
  726. FILE *fp
  727. )
  728. {
  729. int i;
  730. int from;
  731. int to;
  732. struct varlist tmplist[MAXLIST];
  733. /* HMS: uval? */
  734. if (!findassidrange(pcmd->argval[0].uval, pcmd->argval[1].uval,
  735. &from, &to))
  736. return;
  737. memset((char *)tmplist, 0, sizeof(tmplist));
  738. if (pcmd->nargs >= 3)
  739. doaddvlist(tmplist, pcmd->argval[2].string);
  740. for (i = from; i <= to; i++) {
  741. if (i != from)
  742. (void) fprintf(fp, "\n");
  743. if (!dolist(varlist, (int)assoc_cache[i].assid,
  744. CTL_OP_READVAR, TYPE_PEER, fp))
  745. break;
  746. }
  747. doclearvlist(tmplist);
  748. return;
  749. }
  750. /*
  751. * dogetassoc - query the host for its list of associations
  752. */
  753. static int
  754. dogetassoc(
  755. FILE *fp
  756. )
  757. {
  758. char *datap;
  759. int res;
  760. int dsize;
  761. u_short rstatus;
  762. res = doquery(CTL_OP_READSTAT, 0, 0, 0, (char *)0, &rstatus,
  763. &dsize, &datap);
  764. if (res != 0)
  765. return 0;
  766. if (dsize == 0) {
  767. if (numhosts > 1)
  768. (void) fprintf(fp, "server=%s ", currenthost);
  769. (void) fprintf(fp, "No association ID's returned\n");
  770. return 0;
  771. }
  772. if (dsize & 0x3) {
  773. if (numhosts > 1)
  774. (void) fprintf(stderr, "server=%s ", currenthost);
  775. (void) fprintf(stderr,
  776. "***Server returned %d octets, should be multiple of 4\n",
  777. dsize);
  778. return 0;
  779. }
  780. numassoc = 0;
  781. while (dsize > 0) {
  782. assoc_cache[numassoc].assid = ntohs(*((u_short *)datap));
  783. datap += sizeof(u_short);
  784. assoc_cache[numassoc].status = ntohs(*((u_short *)datap));
  785. datap += sizeof(u_short);
  786. if (++numassoc >= MAXASSOC)
  787. break;
  788. dsize -= sizeof(u_short) + sizeof(u_short);
  789. }
  790. sortassoc();
  791. return 1;
  792. }
  793. /*
  794. * printassoc - print the current list of associations
  795. */
  796. static void
  797. printassoc(
  798. int showall,
  799. FILE *fp
  800. )
  801. {
  802. register char *bp;
  803. int i;
  804. u_char statval;
  805. int event;
  806. u_long event_count;
  807. const char *conf;
  808. const char *reach;
  809. const char *auth;
  810. const char *condition = "";
  811. const char *last_event;
  812. const char *cnt;
  813. char buf[128];
  814. if (numassoc == 0) {
  815. (void) fprintf(fp, "No association ID's in list\n");
  816. return;
  817. }
  818. /*
  819. * Output a header
  820. */
  821. (void) fprintf(fp,
  822. "\nind assID status conf reach auth condition last_event cnt\n");
  823. (void) fprintf(fp,
  824. "===========================================================\n");
  825. for (i = 0; i < numassoc; i++) {
  826. statval = (u_char) CTL_PEER_STATVAL(assoc_cache[i].status);
  827. if (!showall && !(statval & (CTL_PST_CONFIG|CTL_PST_REACH)))
  828. continue;
  829. event = CTL_PEER_EVENT(assoc_cache[i].status);
  830. event_count = CTL_PEER_NEVNT(assoc_cache[i].status);
  831. if (statval & CTL_PST_CONFIG)
  832. conf = "yes";
  833. else
  834. conf = "no";
  835. if (statval & CTL_PST_REACH || 1) {
  836. reach = "yes";
  837. if (statval & CTL_PST_AUTHENABLE) {
  838. if (statval & CTL_PST_AUTHENTIC)
  839. auth = "ok ";
  840. else
  841. auth = "bad";
  842. } else
  843. auth = "none";
  844. if (pktversion > NTP_OLDVERSION)
  845. switch (statval & 0x7) {
  846. case CTL_PST_SEL_REJECT:
  847. condition = "reject";
  848. break;
  849. case CTL_PST_SEL_SANE:
  850. condition = "falsetick";
  851. break;
  852. case CTL_PST_SEL_CORRECT:
  853. condition = "excess";
  854. break;
  855. case CTL_PST_SEL_SELCAND:
  856. condition = "outlyer";
  857. break;
  858. case CTL_PST_SEL_SYNCCAND:
  859. condition = "candidat";
  860. break;
  861. case CTL_PST_SEL_DISTSYSPEER:
  862. condition = "selected";
  863. break;
  864. case CTL_PST_SEL_SYSPEER:
  865. condition = "sys.peer";
  866. break;
  867. case CTL_PST_SEL_PPS:
  868. condition = "pps.peer";
  869. break;
  870. }
  871. else
  872. switch (statval & 0x3) {
  873. case OLD_CTL_PST_SEL_REJECT:
  874. if (!(statval & OLD_CTL_PST_SANE))
  875. condition = "insane";
  876. else if (!(statval & OLD_CTL_PST_DISP))
  877. condition = "hi_disp";
  878. else
  879. condition = "";
  880. break;
  881. case OLD_CTL_PST_SEL_SELCAND:
  882. condition = "sel_cand";
  883. break;
  884. case OLD_CTL_PST_SEL_SYNCCAND:
  885. condition = "sync_cand";
  886. break;
  887. case OLD_CTL_PST_SEL_SYSPEER:
  888. condition = "sys_peer";
  889. break;
  890. }
  891. } else {
  892. reach = "no";
  893. auth = condition = "";
  894. }
  895. switch (PEER_EVENT|event) {
  896. case EVNT_PEERIPERR:
  897. last_event = "IP error";
  898. break;
  899. case EVNT_PEERAUTH:
  900. last_event = "auth fail";
  901. break;
  902. case EVNT_UNREACH:
  903. last_event = "lost reach";
  904. break;
  905. case EVNT_REACH:
  906. last_event = "reachable";
  907. break;
  908. case EVNT_PEERCLOCK:
  909. last_event = "clock expt";
  910. break;
  911. #if 0
  912. case EVNT_PEERSTRAT:
  913. last_event = "stratum chg";
  914. break;
  915. #endif
  916. default:
  917. last_event = "";
  918. break;
  919. }
  920. if (event_count != 0)
  921. cnt = uinttoa(event_count);
  922. else
  923. cnt = "";
  924. (void) sprintf(buf,
  925. "%3d %5u %04x %3.3s %4s %4.4s %9.9s %11s %2s",
  926. i+1, assoc_cache[i].assid, assoc_cache[i].status,
  927. conf, reach, auth, condition, last_event, cnt);
  928. bp = &buf[strlen(buf)];
  929. while (bp > buf && *(bp-1) == ' ')
  930. *(--bp) = '\0';
  931. (void) fprintf(fp, "%s\n", buf);
  932. }
  933. }
  934. /*
  935. * associations - get, record and print a list of associations
  936. */
  937. /*ARGSUSED*/
  938. static void
  939. associations(
  940. struct parse *pcmd,
  941. FILE *fp
  942. )
  943. {
  944. if (dogetassoc(fp))
  945. printassoc(0, fp);
  946. }
  947. /*
  948. * lassociations - get, record and print a long list of associations
  949. */
  950. /*ARGSUSED*/
  951. static void
  952. lassociations(
  953. struct parse *pcmd,
  954. FILE *fp
  955. )
  956. {
  957. if (dogetassoc(fp))
  958. printassoc(1, fp);
  959. }
  960. /*
  961. * passociations - print the association list
  962. */
  963. /*ARGSUSED*/
  964. static void
  965. passociations(
  966. struct parse *pcmd,
  967. FILE *fp
  968. )
  969. {
  970. printassoc(0, fp);
  971. }
  972. /*
  973. * lpassociations - print the long association list
  974. */
  975. /*ARGSUSED*/
  976. static void
  977. lpassociations(
  978. struct parse *pcmd,
  979. FILE *fp
  980. )
  981. {
  982. printassoc(1, fp);
  983. }
  984. #ifdef UNUSED
  985. /*
  986. * radiostatus - print the radio status returned by the server
  987. */
  988. /*ARGSUSED*/
  989. static void
  990. radiostatus(
  991. struct parse *pcmd,
  992. FILE *fp
  993. )
  994. {
  995. char *datap;
  996. int res;
  997. int dsize;
  998. u_short rstatus;
  999. res = doquery(CTL_OP_READCLOCK, 0, 0, 0, (char *)0, &rstatus,
  1000. &dsize, &datap);
  1001. if (res != 0)
  1002. return;
  1003. if (numhosts > 1)
  1004. (void) fprintf(fp, "server=%s ", currenthost);
  1005. if (dsize == 0) {
  1006. (void) fprintf(fp, "No radio status string returned\n");
  1007. return;
  1008. }
  1009. asciize(dsize, datap, fp);
  1010. }
  1011. #endif /* UNUSED */
  1012. /*
  1013. * pstatus - print peer status returned by the server
  1014. */
  1015. static void
  1016. pstatus(
  1017. struct parse *pcmd,
  1018. FILE *fp
  1019. )
  1020. {
  1021. char *datap;
  1022. int res;
  1023. int associd;
  1024. int dsize;
  1025. u_short rstatus;
  1026. /* HMS: uval? */
  1027. if ((associd = checkassocid(pcmd->argval[0].uval)) == 0)
  1028. return;
  1029. res = doquery(CTL_OP_READSTAT, associd, 0, 0, (char *)0, &rstatus,
  1030. &dsize, &datap);
  1031. if (res != 0)
  1032. return;
  1033. if (numhosts > 1)
  1034. (void) fprintf(fp, "server=%s ", currenthost);
  1035. if (dsize == 0) {
  1036. (void) fprintf(fp,
  1037. "No information returned for association %u\n",
  1038. associd);
  1039. return;
  1040. }
  1041. (void) fprintf(fp,"assID=%d ",associd);
  1042. printvars(dsize, datap, (int)rstatus, TYPE_PEER, fp);
  1043. }
  1044. /*
  1045. * when - print how long its been since his last packet arrived
  1046. */
  1047. static long
  1048. when(
  1049. l_fp *ts,
  1050. l_fp *rec,
  1051. l_fp *reftime
  1052. )
  1053. {
  1054. l_fp *lasttime;
  1055. if (rec->l_ui != 0)
  1056. lasttime = rec;
  1057. else if (reftime->l_ui != 0)
  1058. lasttime = reftime;
  1059. else
  1060. return 0;
  1061. return (ts->l_ui - lasttime->l_ui);
  1062. }
  1063. /*
  1064. * Pretty-print an interval into the given buffer, in a human-friendly format.
  1065. */
  1066. static char *
  1067. prettyinterval(
  1068. char *buf,
  1069. long diff
  1070. )
  1071. {
  1072. if (diff <= 0) {
  1073. buf[0] = '-';
  1074. buf[1] = 0;
  1075. return buf;
  1076. }
  1077. if (diff <= 2048) {
  1078. (void) sprintf(buf, "%ld", (long int)diff);
  1079. return buf;
  1080. }
  1081. diff = (diff + 29) / 60;
  1082. if (diff <= 300) {
  1083. (void) sprintf(buf, "%ldm", (long int)diff);
  1084. return buf;
  1085. }
  1086. diff = (diff + 29) / 60;
  1087. if (diff <= 96) {
  1088. (void) sprintf(buf, "%ldh", (long int)diff);
  1089. return buf;
  1090. }
  1091. diff = (diff + 11) / 24;
  1092. (void) sprintf(buf, "%ldd", (long int)diff);
  1093. return buf;
  1094. }
  1095. static char
  1096. decodeaddrtype(
  1097. struct sockaddr_storage *sock
  1098. )
  1099. {
  1100. char ch = '-';
  1101. u_int32 dummy;
  1102. struct sockaddr_in6 *sin6;
  1103. switch(sock->ss_family) {
  1104. case AF_INET:
  1105. dummy = ((struct sockaddr_in *)sock)->sin_addr.s_addr;
  1106. dummy = ntohl(dummy);
  1107. ch = (char)(((dummy&0xf0000000)==0xe0000000) ? 'm' :
  1108. ((dummy&0x000000ff)==0x000000ff) ? 'b' :
  1109. ((dummy&0xffffffff)==0x7f000001) ? 'l' :
  1110. ((dummy&0xffffffe0)==0x00000000) ? '-' :
  1111. 'u');
  1112. break;
  1113. case AF_INET6:
  1114. sin6 = (struct sockaddr_in6 *)sock;
  1115. if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
  1116. ch = 'm';
  1117. else
  1118. ch = 'u';
  1119. break;
  1120. default:
  1121. ch = '-';
  1122. break;
  1123. }
  1124. return ch;
  1125. }
  1126. /*
  1127. * A list of variables required by the peers command
  1128. */
  1129. struct varlist opeervarlist[] = {
  1130. { "srcadr", 0 }, /* 0 */
  1131. { "dstadr", 0 }, /* 1 */
  1132. { "stratum", 0 }, /* 2 */
  1133. { "hpoll", 0 }, /* 3 */
  1134. { "ppoll", 0 }, /* 4 */
  1135. { "reach", 0 }, /* 5 */
  1136. { "delay", 0 }, /* 6 */
  1137. { "offset", 0 }, /* 7 */
  1138. { "jitter", 0 }, /* 8 */
  1139. { "dispersion", 0 }, /* 9 */
  1140. { "rec", 0 }, /* 10 */
  1141. { "reftime", 0 }, /* 11 */
  1142. { "srcport", 0 }, /* 12 */
  1143. { 0, 0 }
  1144. };
  1145. struct varlist peervarlist[] = {
  1146. { "srcadr", 0 }, /* 0 */
  1147. { "refid", 0 }, /* 1 */
  1148. { "stratum", 0 }, /* 2 */
  1149. { "hpoll", 0 }, /* 3 */
  1150. { "ppoll", 0 }, /* 4 */
  1151. { "reach", 0 }, /* 5 */
  1152. { "delay", 0 }, /* 6 */
  1153. { "offset", 0 }, /* 7 */
  1154. { "jitter", 0 }, /* 8 */
  1155. { "dispersion", 0 }, /* 9 */
  1156. { "rec", 0 }, /* 10 */
  1157. { "reftime", 0 }, /* 11 */
  1158. { "srcport", 0 }, /* 12 */
  1159. { 0, 0 }
  1160. };
  1161. #define HAVE_SRCADR 0
  1162. #define HAVE_DSTADR 1
  1163. #define HAVE_REFID 1
  1164. #define HAVE_STRATUM 2
  1165. #define HAVE_HPOLL 3
  1166. #define HAVE_PPOLL 4
  1167. #define HAVE_REACH 5
  1168. #define HAVE_DELAY 6
  1169. #define HAVE_OFFSET 7
  1170. #define HAVE_JITTER 8
  1171. #define HAVE_DISPERSION 9
  1172. #define HAVE_REC 10
  1173. #define HAVE_REFTIME 11
  1174. #define HAVE_SRCPORT 12
  1175. #define MAXHAVE 13
  1176. /*
  1177. * Decode an incoming data buffer and print a line in the peer list
  1178. */
  1179. static int
  1180. doprintpeers(
  1181. struct varlist *pvl,
  1182. int associd,
  1183. int rstatus,
  1184. int datalen,
  1185. char *data,
  1186. FILE *fp,
  1187. int af
  1188. )
  1189. {
  1190. char *name;
  1191. char *value = NULL;
  1192. int i;
  1193. int c;
  1194. struct sockaddr_storage srcadr;
  1195. struct sockaddr_storage dstadr;
  1196. u_long srcport = 0;
  1197. char *dstadr_refid = "0.0.0.0";
  1198. u_long stratum = 0;
  1199. long ppoll = 0;
  1200. long hpoll = 0;
  1201. u_long reach = 0;
  1202. l_fp estoffset;
  1203. l_fp estdelay;
  1204. l_fp estjitter;
  1205. l_fp estdisp;
  1206. l_fp reftime;
  1207. l_fp rec;
  1208. l_fp ts;
  1209. u_char havevar[MAXHAVE];
  1210. u_long poll_sec;
  1211. char type = '?';
  1212. char refid_string[10];
  1213. char whenbuf[8], pollbuf[8];
  1214. char clock_name[LENHOSTNAME];
  1215. memset((char *)havevar, 0, sizeof(havevar));
  1216. get_systime(&ts);
  1217. memset((char *)&srcadr, 0, sizeof(struct sockaddr_storage));
  1218. memset((char *)&dstadr, 0, sizeof(struct sockaddr_storage));
  1219. /* Initialize by zeroing out estimate variables */
  1220. memset((char *)&estoffset, 0, sizeof(l_fp));
  1221. memset((char *)&estdelay, 0, sizeof(l_fp));
  1222. memset((char *)&estjitter, 0, sizeof(l_fp));
  1223. memset((char *)&estdisp, 0, sizeof(l_fp));
  1224. while (nextvar(&datalen, &data, &name, &value)) {
  1225. struct sockaddr_storage dum_store;
  1226. i = findvar(name, peer_var, 1);
  1227. if (i == 0)
  1228. continue; /* don't know this one */
  1229. switch (i) {
  1230. case CP_SRCADR:
  1231. if (decodenetnum(value, &srcadr))
  1232. havevar[HAVE_SRCADR] = 1;
  1233. break;
  1234. case CP_DSTADR:
  1235. if (decodenetnum(value, &dum_store))
  1236. type = decodeaddrtype(&dum_store);
  1237. if (pvl == opeervarlist) {
  1238. if (decodenetnum(value, &dstadr)) {
  1239. havevar[HAVE_DSTADR] = 1;
  1240. dstadr_refid = stoa(&dstadr);
  1241. }
  1242. }
  1243. break;
  1244. case CP_REFID:
  1245. if (pvl == peervarlist) {
  1246. havevar[HAVE_REFID] = 1;
  1247. if (*value == '\0') {
  1248. dstadr_refid = "0.0.0.0";
  1249. } else if ((int)strlen(value) <= 4) {
  1250. refid_string[0] = '.';
  1251. (void) strcpy(&refid_string[1], value);
  1252. i = strlen(refid_string);
  1253. refid_string[i] = '.';
  1254. refid_string[i+1] = '\0';
  1255. dstadr_refid = refid_string;
  1256. } else if (decodenetnum(value, &dstadr)) {
  1257. if (SOCKNUL(&dstadr))
  1258. dstadr_refid = "0.0.0.0";
  1259. else if ((dstadr.ss_family == AF_INET)
  1260. && ISREFCLOCKADR(&dstadr))
  1261. dstadr_refid =
  1262. refnumtoa(&dstadr);
  1263. else
  1264. dstadr_refid =
  1265. stoa(&dstadr);
  1266. } else {
  1267. havevar[HAVE_REFID] = 0;
  1268. }
  1269. }
  1270. break;
  1271. case CP_STRATUM:
  1272. if (decodeuint(value, &stratum))
  1273. havevar[HAVE_STRATUM] = 1;
  1274. break;
  1275. case CP_HPOLL:
  1276. if (decodeint(value, &hpoll)) {
  1277. havevar[HAVE_HPOLL] = 1;
  1278. if (hpoll < 0)
  1279. hpoll = NTP_MINPOLL;
  1280. }
  1281. break;
  1282. case CP_PPOLL:
  1283. if (decodeint(value, &ppoll)) {
  1284. havevar[HAVE_PPOLL] = 1;
  1285. if (ppoll < 0)
  1286. ppoll = NTP_MINPOLL;
  1287. }
  1288. break;
  1289. case CP_REACH:
  1290. if (decodeuint(value, &reach))
  1291. havevar[HAVE_REACH] = 1;
  1292. break;
  1293. case CP_DELAY:
  1294. if (decodetime(value, &estdelay))
  1295. havevar[HAVE_DELAY] = 1;
  1296. break;
  1297. case CP_OFFSET:
  1298. if (decodetime(value, &estoffset))
  1299. havevar[HAVE_OFFSET] = 1;
  1300. break;
  1301. case CP_JITTER:
  1302. if (pvl == peervarlist)
  1303. if (decodetime(value, &estjitter))
  1304. havevar[HAVE_JITTER] = 1;
  1305. break;
  1306. case CP_DISPERSION:
  1307. if (decodetime(value, &estdisp))
  1308. havevar[HAVE_DISPERSION] = 1;
  1309. break;
  1310. case CP_REC:
  1311. if (decodets(value, &rec))
  1312. havevar[HAVE_REC] = 1;
  1313. break;
  1314. case CP_SRCPORT:
  1315. if (decodeuint(value, &srcport))
  1316. havevar[HAVE_SRCPORT] = 1;
  1317. break;
  1318. case CP_REFTIME:
  1319. havevar[HAVE_REFTIME] = 1;
  1320. if (!decodets(value, &reftime))
  1321. L_CLR(&reftime);
  1322. break;
  1323. default:
  1324. break;
  1325. }
  1326. }
  1327. /*
  1328. * Check to see if the srcport is NTP's port. If not this probably
  1329. * isn't a valid peer association.
  1330. */
  1331. if (havevar[HAVE_SRCPORT] && srcport != NTP_PORT)
  1332. return (1);
  1333. /*
  1334. * Got everything, format the line
  1335. */
  1336. poll_sec = 1<<max(min3(ppoll, hpoll, NTP_MAXPOLL), NTP_MINPOLL);
  1337. if (pktversion > NTP_OLDVERSION)
  1338. c = flash3[CTL_PEER_STATVAL(rstatus) & 0x7];
  1339. else
  1340. c = flash2[CTL_PEER_STATVAL(rstatus) & 0x3];
  1341. if (numhosts > 1)
  1342. (void) fprintf(fp, "%-*s ", maxhostlen, currenthost);
  1343. if (af == 0 || srcadr.ss_family == af){
  1344. strcpy(clock_name, nntohost(&srcadr));
  1345. (void) fprintf(fp,
  1346. "%c%-15.15s %-15.15s %2ld %c %4.4s %4.4s %3lo %7.7s %8.7s %7.7s\n",
  1347. c, clock_name, dstadr_refid, stratum, type,
  1348. prettyinterval(whenbuf, when(&ts, &rec, &reftime)),
  1349. prettyinterval(pollbuf, (int)poll_sec), reach,
  1350. lfptoms(&estdelay, 3), lfptoms(&estoffset, 3),
  1351. havevar[HAVE_JITTER] ? lfptoms(&estjitter, 3) :
  1352. lfptoms(&estdisp, 3));
  1353. return (1);
  1354. }
  1355. else
  1356. return(1);
  1357. }
  1358. #undef HAVE_SRCADR
  1359. #undef HAVE_DSTADR
  1360. #undef HAVE_STRATUM
  1361. #undef HAVE_PPOLL
  1362. #undef HAVE_HPOLL
  1363. #undef HAVE_REACH
  1364. #undef HAVE_ESTDELAY
  1365. #undef HAVE_ESTOFFSET
  1366. #undef HAVE_JITTER
  1367. #undef HAVE_ESTDISP
  1368. #undef HAVE_REFID
  1369. #undef HAVE_REC
  1370. #undef HAVE_SRCPORT
  1371. #undef HAVE_REFTIME
  1372. #undef MAXHAVE
  1373. /*
  1374. * dogetpeers - given an association ID, read and print the spreadsheet
  1375. * peer variables.
  1376. */
  1377. static int
  1378. dogetpeers(
  1379. struct varlist *pvl,
  1380. int associd,
  1381. FILE *fp,
  1382. int af
  1383. )
  1384. {
  1385. char *datap;
  1386. int res;
  1387. int dsize;
  1388. u_short rstatus;
  1389. #ifdef notdef
  1390. res = doquerylist(pvl, CTL_OP_READVAR, associd, 0, &rstatus,
  1391. &dsize, &datap);
  1392. #else
  1393. /*
  1394. * Damn fuzzballs
  1395. */
  1396. res = doquery(CTL_OP_READVAR, associd, 0, 0, (char *)0, &rstatus,
  1397. &dsize, &datap);
  1398. #endif
  1399. if (res != 0)
  1400. return 0;
  1401. if (dsize == 0) {
  1402. if (numhosts > 1)
  1403. (void) fprintf(stderr, "server=%s ", currenthost);
  1404. (void) fprintf(stderr,
  1405. "***No information returned for association %d\n",
  1406. associd);
  1407. return 0;
  1408. }
  1409. return doprintpeers(pvl, associd, (int)rstatus, dsize, datap, fp, af);
  1410. }
  1411. /*
  1412. * peers - print a peer spreadsheet
  1413. */
  1414. static void
  1415. dopeers(
  1416. int showall,
  1417. FILE *fp,
  1418. int af
  1419. )
  1420. {
  1421. register int i;
  1422. char fullname[LENHOSTNAME];
  1423. struct sockaddr_storage netnum;
  1424. if (!dogetassoc(fp))
  1425. return;
  1426. for (i = 0; i < numhosts; ++i) {
  1427. if (getnetnum(chosts[i], &netnum, fullname, af))
  1428. if ((int)strlen(fullname) > maxhostlen)
  1429. maxhostlen = strlen(fullname);
  1430. }
  1431. if (numhosts > 1)
  1432. (void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "server");
  1433. (void) fprintf(fp,
  1434. " remote refid st t when poll reach delay offset jitter\n");
  1435. if (numhosts > 1)
  1436. for (i = 0; i <= maxhostlen; ++i)
  1437. (void) fprintf(fp, "=");
  1438. (void) fprintf(fp,
  1439. "==============================================================================\n");
  1440. for (i = 0; i < numassoc; i++) {
  1441. if (!showall &&
  1442. !(CTL_PEER_STATVAL(assoc_cache[i].status)
  1443. & (CTL_PST_CONFIG|CTL_PST_REACH)))
  1444. continue;
  1445. if (!dogetpeers(peervarlist, (int)assoc_cache[i].assid, fp, af)) {
  1446. return;
  1447. }
  1448. }
  1449. return;
  1450. }
  1451. /*
  1452. * peers - print a peer spreadsheet
  1453. */
  1454. /*ARGSUSED*/
  1455. static void
  1456. peers(
  1457. struct parse *pcmd,
  1458. FILE *fp
  1459. )
  1460. {
  1461. int af = 0;
  1462. if (pcmd->nargs == 1) {
  1463. if (pcmd->argval->ival == 6)
  1464. af = AF_INET6;
  1465. else
  1466. af = AF_INET;
  1467. }
  1468. dopeers(0, fp, af);
  1469. }
  1470. /*
  1471. * lpeers - print a peer spreadsheet including all fuzzball peers
  1472. */
  1473. /*ARGSUSED*/
  1474. static void
  1475. lpeers(
  1476. struct parse *pcmd,
  1477. FILE *fp
  1478. )
  1479. {
  1480. int af = 0;
  1481. if (pcmd->nargs == 1) {
  1482. if (pcmd->argval->ival == 6)
  1483. af = AF_INET6;
  1484. else
  1485. af = AF_INET;
  1486. }
  1487. dopeers(1, fp, af);
  1488. }
  1489. /*
  1490. * opeers - print a peer spreadsheet
  1491. */
  1492. static void
  1493. doopeers(
  1494. int showall,
  1495. FILE *fp,
  1496. int af
  1497. )
  1498. {
  1499. register int i;
  1500. char fullname[LENHOSTNAME];
  1501. struct sockaddr_storage netnum;
  1502. if (!dogetassoc(fp))
  1503. return;
  1504. for (i = 0; i < numhosts; ++i) {
  1505. if (getnetnum(chosts[i], &netnum, fullname, af))
  1506. if ((int)strlen(fullname) > maxhostlen)
  1507. maxhostlen = strlen(fullname);
  1508. }
  1509. if (numhosts > 1)
  1510. (void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "server");
  1511. (void) fprintf(fp,
  1512. " remote local st t when poll reach delay offset disp\n");
  1513. if (numhosts > 1)
  1514. for (i = 0; i <= maxhostlen; ++i)
  1515. (void) fprintf(fp, "=");
  1516. (void) fprintf(fp,
  1517. "==============================================================================\n");
  1518. for (i = 0; i < numassoc; i++) {
  1519. if (!showall &&
  1520. !(CTL_PEER_STATVAL(assoc_cache[i].status)
  1521. & (CTL_PST_CONFIG|CTL_PST_REACH)))
  1522. continue;
  1523. if (!dogetpeers(opeervarlist, (int)assoc_cache[i].assid, fp, af)) {
  1524. return;
  1525. }
  1526. }
  1527. return;
  1528. }
  1529. /*
  1530. * opeers - print a peer spreadsheet the old way
  1531. */
  1532. /*ARGSUSED*/
  1533. static void
  1534. opeers(
  1535. struct parse *pcmd,
  1536. FILE *fp
  1537. )
  1538. {
  1539. int af = 0;
  1540. if (pcmd->nargs == 1) {
  1541. if (pcmd->argval->ival == 6)
  1542. af = AF_INET6;
  1543. else
  1544. af = AF_INET;
  1545. }
  1546. doopeers(0, fp, af);
  1547. }
  1548. /*
  1549. * lopeers - print a peer spreadsheet including all fuzzball peers
  1550. */
  1551. /*ARGSUSED*/
  1552. static void
  1553. lopeers(
  1554. struct parse *pcmd,
  1555. FILE *fp
  1556. )
  1557. {
  1558. int af = 0;
  1559. if (pcmd->nargs == 1) {
  1560. if (pcmd->argval->ival == 6)
  1561. af = AF_INET6;
  1562. else
  1563. af = AF_INET;
  1564. }
  1565. doopeers(1, fp, af);
  1566. }