/contrib/ntp/ntpdc/ntpdc.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1999 lines · 1502 code · 221 blank · 276 comment · 402 complexity · 794df605728909a9e9a16fe741cee32a MD5 · raw file

  1. /*
  2. * ntpdc - control and monitor your ntpd daemon
  3. */
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include <signal.h>
  7. #include <setjmp.h>
  8. #include "ntpdc.h"
  9. #include "ntp_select.h"
  10. #include "ntp_io.h"
  11. #include "ntp_stdlib.h"
  12. /* Don't include ISC's version of IPv6 variables and structures */
  13. #define ISC_IPV6_H 1
  14. #include "isc/net.h"
  15. #include "isc/result.h"
  16. #include "ntpdc-opts.h"
  17. #ifdef SYS_WINNT
  18. # include <Mswsock.h>
  19. # include <io.h>
  20. #else
  21. # define closesocket close
  22. #endif /* SYS_WINNT */
  23. #if defined(HAVE_LIBREADLINE) || defined (HAVE_LIBEDIT)
  24. # include <readline/readline.h>
  25. # include <readline/history.h>
  26. #endif /* HAVE_LIBREADLINE || HAVE_LIBEDIT */
  27. #ifdef SYS_VXWORKS
  28. /* vxWorks needs mode flag -casey*/
  29. # define open(name, flags) open(name, flags, 0777)
  30. # define SERVER_PORT_NUM 123
  31. #endif
  32. /* We use COMMAND as an autogen keyword */
  33. #ifdef COMMAND
  34. # undef COMMAND
  35. #endif
  36. /*
  37. * Because we now potentially understand a lot of commands (and
  38. * it requires a lot of commands to talk to ntpd) we will run
  39. * interactive if connected to a terminal.
  40. */
  41. static int interactive = 0; /* set to 1 when we should prompt */
  42. static const char * prompt = "ntpdc> "; /* prompt to ask him about */
  43. /*
  44. * Keyid used for authenticated requests. Obtained on the fly.
  45. */
  46. static u_long info_auth_keyid;
  47. static int keyid_entered = 0;
  48. /*
  49. * Type of key md5
  50. */
  51. #define KEY_TYPE_MD5 4
  52. static int info_auth_keytype = KEY_TYPE_MD5; /* MD5 */
  53. u_long current_time; /* needed by authkeys; not used */
  54. /*
  55. * for get_systime()
  56. */
  57. s_char sys_precision; /* local clock precision (log2 s) */
  58. int ntpdcmain P((int, char **));
  59. /*
  60. * Built in command handler declarations
  61. */
  62. static int openhost P((const char *));
  63. static int sendpkt P((char *, int));
  64. static void growpktdata P((void));
  65. static int getresponse P((int, int, int *, int *, char **, int));
  66. static int sendrequest P((int, int, int, int, int, char *));
  67. static void getcmds P((void));
  68. static RETSIGTYPE abortcmd P((int));
  69. static void docmd P((const char *));
  70. static void tokenize P((const char *, char **, int *));
  71. static int findcmd P((char *, struct xcmd *, struct xcmd *, struct xcmd **));
  72. static int getarg P((char *, int, arg_v *));
  73. static int getnetnum P((const char *, struct sockaddr_storage *, char *, int));
  74. static void help P((struct parse *, FILE *));
  75. #ifdef QSORT_USES_VOID_P
  76. static int helpsort P((const void *, const void *));
  77. #else
  78. static int helpsort P((char **, char **));
  79. #endif
  80. static void printusage P((struct xcmd *, FILE *));
  81. static void timeout P((struct parse *, FILE *));
  82. static void my_delay P((struct parse *, FILE *));
  83. static void host P((struct parse *, FILE *));
  84. static void keyid P((struct parse *, FILE *));
  85. static void keytype P((struct parse *, FILE *));
  86. static void passwd P((struct parse *, FILE *));
  87. static void hostnames P((struct parse *, FILE *));
  88. static void setdebug P((struct parse *, FILE *));
  89. static void quit P((struct parse *, FILE *));
  90. static void version P((struct parse *, FILE *));
  91. static void warning P((const char *, const char *, const char *));
  92. static void error P((const char *, const char *, const char *));
  93. static u_long getkeyid P((const char *));
  94. /*
  95. * Built-in commands we understand
  96. */
  97. static struct xcmd builtins[] = {
  98. { "?", help, { OPT|NTP_STR, NO, NO, NO },
  99. { "command", "", "", "" },
  100. "tell the use and syntax of commands" },
  101. { "help", help, { OPT|NTP_STR, NO, NO, NO },
  102. { "command", "", "", "" },
  103. "tell the use and syntax of commands" },
  104. { "timeout", timeout, { OPT|NTP_UINT, NO, NO, NO },
  105. { "msec", "", "", "" },
  106. "set the primary receive time out" },
  107. { "delay", my_delay, { OPT|NTP_INT, NO, NO, NO },
  108. { "msec", "", "", "" },
  109. "set the delay added to encryption time stamps" },
  110. { "host", host, { OPT|NTP_STR, OPT|NTP_STR, NO, NO },
  111. { "-4|-6", "hostname", "", "" },
  112. "specify the host whose NTP server we talk to" },
  113. { "passwd", passwd, { OPT|NTP_STR, NO, NO, NO },
  114. { "", "", "", "" },
  115. "specify a password to use for authenticated requests"},
  116. { "hostnames", hostnames, { OPT|NTP_STR, NO, NO, NO },
  117. { "yes|no", "", "", "" },
  118. "specify whether hostnames or net numbers are printed"},
  119. { "debug", setdebug, { OPT|NTP_STR, NO, NO, NO },
  120. { "no|more|less", "", "", "" },
  121. "set/change debugging level" },
  122. { "quit", quit, { NO, NO, NO, NO },
  123. { "", "", "", "" },
  124. "exit ntpdc" },
  125. { "exit", quit, { NO, NO, NO, NO },
  126. { "", "", "", "" },
  127. "exit ntpdc" },
  128. { "keyid", keyid, { OPT|NTP_UINT, NO, NO, NO },
  129. { "key#", "", "", "" },
  130. "set/show keyid to use for authenticated requests" },
  131. { "keytype", keytype, { OPT|NTP_STR, NO, NO, NO },
  132. { "(md5|des)", "", "", "" },
  133. "set/show key authentication type for authenticated requests (des|md5)" },
  134. { "version", version, { NO, NO, NO, NO },
  135. { "", "", "", "" },
  136. "print version number" },
  137. { 0, 0, { NO, NO, NO, NO },
  138. { "", "", "", "" }, "" }
  139. };
  140. /*
  141. * Default values we use.
  142. */
  143. #define DEFTIMEOUT (5) /* 5 second time out */
  144. #define DEFSTIMEOUT (2) /* 2 second time out after first */
  145. #define DEFDELAY 0x51EB852 /* 20 milliseconds, l_fp fraction */
  146. #define DEFHOST "localhost" /* default host name */
  147. #define LENHOSTNAME 256 /* host name is 256 characters long */
  148. #define MAXCMDS 100 /* maximum commands on cmd line */
  149. #define MAXHOSTS 200 /* maximum hosts on cmd line */
  150. #define MAXLINE 512 /* maximum line length */
  151. #define MAXTOKENS (1+1+MAXARGS+MOREARGS+2) /* maximum number of usable tokens */
  152. #define SCREENWIDTH 78 /* nominal screen width in columns */
  153. /*
  154. * Some variables used and manipulated locally
  155. */
  156. static struct timeval tvout = { DEFTIMEOUT, 0 }; /* time out for reads */
  157. static struct timeval tvsout = { DEFSTIMEOUT, 0 }; /* secondary time out */
  158. static l_fp delay_time; /* delay time */
  159. static char currenthost[LENHOSTNAME]; /* current host name */
  160. int showhostnames = 1; /* show host names by default */
  161. static int ai_fam_templ; /* address family */
  162. static int ai_fam_default; /* default address family */
  163. static SOCKET sockfd; /* fd socket is opened on */
  164. static int havehost = 0; /* set to 1 when host open */
  165. int s_port = 0;
  166. #if defined (SYS_WINNT) || defined (SYS_VXWORKS)
  167. char password[9];
  168. #endif /* SYS_WINNT || SYS_VXWORKS */
  169. #ifdef SYS_WINNT
  170. DWORD NumberOfBytesWritten;
  171. HANDLE TimerThreadHandle = NULL; /* 1998/06/03 - Used in ntplib/machines.c */
  172. void timer(void) { ; }; /* 1998/06/03 - Used in ntplib/machines.c */
  173. #endif /* SYS_WINNT */
  174. /*
  175. * Holds data returned from queries. We allocate INITDATASIZE
  176. * octets to begin with, increasing this as we need to.
  177. */
  178. #define INITDATASIZE (sizeof(struct resp_pkt) * 16)
  179. #define INCDATASIZE (sizeof(struct resp_pkt) * 8)
  180. static char *pktdata;
  181. static int pktdatasize;
  182. /*
  183. * These are used to help the magic with old and new versions of ntpd.
  184. */
  185. int impl_ver = IMPL_XNTPD;
  186. static int req_pkt_size = REQ_LEN_NOMAC;
  187. /*
  188. * For commands typed on the command line (with the -c option)
  189. */
  190. static int numcmds = 0;
  191. static const char *ccmds[MAXCMDS];
  192. #define ADDCMD(cp) if (numcmds < MAXCMDS) ccmds[numcmds++] = (cp)
  193. /*
  194. * When multiple hosts are specified.
  195. */
  196. static int numhosts = 0;
  197. static const char *chosts[MAXHOSTS];
  198. #define ADDHOST(cp) if (numhosts < MAXHOSTS) chosts[numhosts++] = (cp)
  199. /*
  200. * Error codes for internal use
  201. */
  202. #define ERR_INCOMPLETE 16
  203. #define ERR_TIMEOUT 17
  204. /*
  205. * Macro definitions we use
  206. */
  207. #define ISSPACE(c) ((c) == ' ' || (c) == '\t')
  208. #define ISEOL(c) ((c) == '\n' || (c) == '\r' || (c) == '\0')
  209. #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
  210. /*
  211. * For converting time stamps to dates
  212. */
  213. #define JAN_1970 2208988800 /* 1970 - 1900 in seconds */
  214. /*
  215. * Jump buffer for longjumping back to the command level
  216. */
  217. static jmp_buf interrupt_buf;
  218. static volatile int jump = 0;
  219. /*
  220. * Pointer to current output unit
  221. */
  222. static FILE *current_output;
  223. /*
  224. * Command table imported from ntpdc_ops.c
  225. */
  226. extern struct xcmd opcmds[];
  227. char *progname;
  228. volatile int debug;
  229. #ifdef NO_MAIN_ALLOWED
  230. CALL(ntpdc,"ntpdc",ntpdcmain);
  231. #else
  232. int
  233. main(
  234. int argc,
  235. char *argv[]
  236. )
  237. {
  238. return ntpdcmain(argc, argv);
  239. }
  240. #endif
  241. #ifdef SYS_VXWORKS
  242. void clear_globals(void)
  243. {
  244. showhostnames = 0; /* show host names by default */
  245. havehost = 0; /* set to 1 when host open */
  246. numcmds = 0;
  247. numhosts = 0;
  248. }
  249. #endif
  250. /*
  251. * main - parse arguments and handle options
  252. */
  253. int
  254. ntpdcmain(
  255. int argc,
  256. char *argv[]
  257. )
  258. {
  259. extern int ntp_optind;
  260. delay_time.l_ui = 0;
  261. delay_time.l_uf = DEFDELAY;
  262. #ifdef SYS_VXWORKS
  263. clear_globals();
  264. taskPrioritySet(taskIdSelf(), 100 );
  265. #endif
  266. #ifdef SYS_WINNT
  267. if (!Win32InitSockets())
  268. {
  269. fprintf(stderr, "No useable winsock.dll:");
  270. exit(1);
  271. }
  272. #endif /* SYS_WINNT */
  273. /* Check to see if we have IPv6. Otherwise force the -4 flag */
  274. if (isc_net_probeipv6() != ISC_R_SUCCESS) {
  275. ai_fam_default = AF_INET;
  276. }
  277. progname = argv[0];
  278. {
  279. int optct = optionProcess(&ntpdcOptions, argc, argv);
  280. argc -= optct;
  281. argv += optct;
  282. }
  283. switch (WHICH_IDX_IPV4) {
  284. case INDEX_OPT_IPV4:
  285. ai_fam_templ = AF_INET;
  286. break;
  287. case INDEX_OPT_IPV6:
  288. ai_fam_templ = AF_INET6;
  289. break;
  290. default:
  291. ai_fam_templ = ai_fam_default;
  292. break;
  293. }
  294. if (HAVE_OPT(COMMAND)) {
  295. int cmdct = STACKCT_OPT( COMMAND );
  296. const char** cmds = STACKLST_OPT( COMMAND );
  297. while (cmdct-- > 0) {
  298. ADDCMD(*cmds++);
  299. }
  300. }
  301. debug = DESC(DEBUG_LEVEL).optOccCt;
  302. if (HAVE_OPT(INTERACTIVE)) {
  303. interactive = 1;
  304. }
  305. if (HAVE_OPT(NUMERIC)) {
  306. showhostnames = 0;
  307. }
  308. if (HAVE_OPT(LISTPEERS)) {
  309. ADDCMD("listpeers");
  310. }
  311. if (HAVE_OPT(PEERS)) {
  312. ADDCMD("peers");
  313. }
  314. if (HAVE_OPT(SHOWPEERS)) {
  315. ADDCMD("dmpeers");
  316. }
  317. if (ntp_optind == argc) {
  318. ADDHOST(DEFHOST);
  319. } else {
  320. for (; ntp_optind < argc; ntp_optind++)
  321. ADDHOST(argv[ntp_optind]);
  322. }
  323. if (numcmds == 0 && interactive == 0
  324. && isatty(fileno(stdin)) && isatty(fileno(stderr))) {
  325. interactive = 1;
  326. }
  327. #if 0
  328. ai_fam_templ = ai_fam_default;
  329. while ((c = ntp_getopt(argc, argv, "46c:dilnps")) != EOF)
  330. switch (c) {
  331. case '4':
  332. ai_fam_templ = AF_INET;
  333. break;
  334. case '6':
  335. ai_fam_templ = AF_INET6;
  336. break;
  337. case 'c':
  338. ADDCMD(ntp_optarg);
  339. break;
  340. case 'd':
  341. ++debug;
  342. break;
  343. case 'i':
  344. interactive = 1;
  345. break;
  346. case 'l':
  347. ADDCMD("listpeers");
  348. break;
  349. case 'n':
  350. showhostnames = 0;
  351. break;
  352. case 'p':
  353. ADDCMD("peers");
  354. break;
  355. case 's':
  356. ADDCMD("dmpeers");
  357. break;
  358. default:
  359. errflg++;
  360. break;
  361. }
  362. if (errflg) {
  363. (void) fprintf(stderr,
  364. "usage: %s [-46dilnps] [-c cmd] host ...\n",
  365. progname);
  366. exit(2);
  367. }
  368. if (ntp_optind == argc) {
  369. ADDHOST(DEFHOST);
  370. } else {
  371. for (; ntp_optind < argc; ntp_optind++)
  372. ADDHOST(argv[ntp_optind]);
  373. }
  374. if (numcmds == 0 && interactive == 0
  375. && isatty(fileno(stdin)) && isatty(fileno(stderr))) {
  376. interactive = 1;
  377. }
  378. #endif
  379. #ifndef SYS_WINNT /* Under NT cannot handle SIGINT, WIN32 spawns a handler */
  380. if (interactive)
  381. (void) signal_no_reset(SIGINT, abortcmd);
  382. #endif /* SYS_WINNT */
  383. /*
  384. * Initialize the packet data buffer
  385. */
  386. pktdata = (char *)malloc(INITDATASIZE);
  387. if (pktdata == NULL) {
  388. (void) fprintf(stderr, "%s: malloc() failed!\n", progname);
  389. exit(1);
  390. }
  391. pktdatasize = INITDATASIZE;
  392. if (numcmds == 0) {
  393. (void) openhost(chosts[0]);
  394. getcmds();
  395. } else {
  396. int ihost;
  397. int icmd;
  398. for (ihost = 0; ihost < numhosts; ihost++) {
  399. if (openhost(chosts[ihost]))
  400. for (icmd = 0; icmd < numcmds; icmd++) {
  401. if (numhosts > 1)
  402. printf ("--- %s ---\n",chosts[ihost]);
  403. docmd(ccmds[icmd]);
  404. }
  405. }
  406. }
  407. #ifdef SYS_WINNT
  408. WSACleanup();
  409. #endif
  410. return(0);
  411. } /* main end */
  412. /*
  413. * openhost - open a socket to a host
  414. */
  415. static int
  416. openhost(
  417. const char *hname
  418. )
  419. {
  420. char temphost[LENHOSTNAME];
  421. int a_info, i;
  422. struct addrinfo hints, *ai = NULL;
  423. register const char *cp;
  424. char name[LENHOSTNAME];
  425. char service[5];
  426. /*
  427. * We need to get by the [] if they were entered
  428. */
  429. cp = hname;
  430. if (*cp == '[') {
  431. cp++;
  432. for(i = 0; *cp != ']'; cp++, i++)
  433. name[i] = *cp;
  434. name[i] = '\0';
  435. hname = name;
  436. }
  437. /*
  438. * First try to resolve it as an ip address and if that fails,
  439. * do a fullblown (dns) lookup. That way we only use the dns
  440. * when it is needed and work around some implementations that
  441. * will return an "IPv4-mapped IPv6 address" address if you
  442. * give it an IPv4 address to lookup.
  443. */
  444. strcpy(service, "ntp");
  445. memset((char *)&hints, 0, sizeof(struct addrinfo));
  446. hints.ai_family = ai_fam_templ;
  447. hints.ai_protocol = IPPROTO_UDP;
  448. hints.ai_socktype = SOCK_DGRAM;
  449. hints.ai_flags = AI_NUMERICHOST;
  450. a_info = getaddrinfo(hname, service, &hints, &ai);
  451. if (a_info == EAI_NONAME
  452. #ifdef EAI_NODATA
  453. || a_info == EAI_NODATA
  454. #endif
  455. ) {
  456. hints.ai_flags = AI_CANONNAME;
  457. #ifdef AI_ADDRCONFIG
  458. hints.ai_flags |= AI_ADDRCONFIG;
  459. #endif
  460. a_info = getaddrinfo(hname, service, &hints, &ai);
  461. }
  462. /* Some older implementations don't like AI_ADDRCONFIG. */
  463. if (a_info == EAI_BADFLAGS) {
  464. hints.ai_flags = AI_CANONNAME;
  465. a_info = getaddrinfo(hname, service, &hints, &ai);
  466. }
  467. if (a_info != 0) {
  468. (void) fprintf(stderr, "%s\n", gai_strerror(a_info));
  469. if (ai != NULL)
  470. freeaddrinfo(ai);
  471. return 0;
  472. }
  473. if (ai->ai_canonname == NULL) {
  474. strncpy(temphost, stoa((struct sockaddr_storage *)ai->ai_addr),
  475. LENHOSTNAME);
  476. temphost[LENHOSTNAME-1] = '\0';
  477. } else {
  478. strncpy(temphost, ai->ai_canonname, LENHOSTNAME);
  479. temphost[LENHOSTNAME-1] = '\0';
  480. }
  481. if (debug > 2)
  482. printf("Opening host %s\n", temphost);
  483. if (havehost == 1) {
  484. if (debug > 2)
  485. printf("Closing old host %s\n", currenthost);
  486. (void) closesocket(sockfd);
  487. havehost = 0;
  488. }
  489. (void) strcpy(currenthost, temphost);
  490. /* port maps to the same in both families */
  491. s_port = ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port;
  492. #ifdef SYS_VXWORKS
  493. ((struct sockaddr_in6 *)&hostaddr)->sin6_port = htons(SERVER_PORT_NUM);
  494. if (ai->ai_family == AF_INET)
  495. *(struct sockaddr_in *)&hostaddr=
  496. *((struct sockaddr_in *)ai->ai_addr);
  497. else
  498. *(struct sockaddr_in6 *)&hostaddr=
  499. *((struct sockaddr_in6 *)ai->ai_addr);
  500. #endif /* SYS_VXWORKS */
  501. #ifdef SYS_WINNT
  502. {
  503. int optionValue = SO_SYNCHRONOUS_NONALERT;
  504. int err;
  505. err = setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&optionValue, sizeof(optionValue));
  506. if (err != NO_ERROR) {
  507. (void) fprintf(stderr, "cannot open nonoverlapped sockets\n");
  508. exit(1);
  509. }
  510. }
  511. sockfd = socket(ai->ai_family, SOCK_DGRAM, 0);
  512. if (sockfd == INVALID_SOCKET) {
  513. error("socket", "", "");
  514. exit(-1);
  515. }
  516. #else
  517. sockfd = socket(ai->ai_family, SOCK_DGRAM, 0);
  518. if (sockfd == -1)
  519. error("socket", "", "");
  520. #endif /* SYS_WINNT */
  521. #ifdef NEED_RCVBUF_SLOP
  522. # ifdef SO_RCVBUF
  523. {
  524. int rbufsize = INITDATASIZE + 2048; /* 2K for slop */
  525. if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
  526. &rbufsize, sizeof(int)) == -1)
  527. error("setsockopt", "", "");
  528. }
  529. # endif
  530. #endif
  531. #ifdef SYS_VXWORKS
  532. if (connect(sockfd, (struct sockaddr *)&hostaddr,
  533. sizeof(hostaddr)) == -1)
  534. #else
  535. if (connect(sockfd, (struct sockaddr *)ai->ai_addr,
  536. ai->ai_addrlen) == -1)
  537. #endif /* SYS_VXWORKS */
  538. error("connect", "", "");
  539. if (ai != NULL)
  540. freeaddrinfo(ai);
  541. havehost = 1;
  542. req_pkt_size = REQ_LEN_NOMAC;
  543. impl_ver = IMPL_XNTPD;
  544. return 1;
  545. }
  546. /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
  547. /*
  548. * sendpkt - send a packet to the remote host
  549. */
  550. static int
  551. sendpkt(
  552. char *xdata,
  553. int xdatalen
  554. )
  555. {
  556. if (send(sockfd, xdata, (size_t)xdatalen, 0) == -1) {
  557. warning("write to %s failed", currenthost, "");
  558. return -1;
  559. }
  560. return 0;
  561. }
  562. /*
  563. * growpktdata - grow the packet data area
  564. */
  565. static void
  566. growpktdata(void)
  567. {
  568. pktdatasize += INCDATASIZE;
  569. pktdata = (char *)realloc(pktdata, (unsigned)pktdatasize);
  570. if (pktdata == 0) {
  571. (void) fprintf(stderr, "%s: realloc() failed!\n", progname);
  572. exit(1);
  573. }
  574. }
  575. /*
  576. * getresponse - get a (series of) response packet(s) and return the data
  577. */
  578. static int
  579. getresponse(
  580. int implcode,
  581. int reqcode,
  582. int *ritems,
  583. int *rsize,
  584. char **rdata,
  585. int esize
  586. )
  587. {
  588. struct resp_pkt rpkt;
  589. struct timeval tvo;
  590. int items;
  591. int i;
  592. int size;
  593. int datasize;
  594. char *datap;
  595. char *tmp_data;
  596. char haveseq[MAXSEQ+1];
  597. int firstpkt;
  598. int lastseq;
  599. int numrecv;
  600. int seq;
  601. fd_set fds;
  602. int n;
  603. int pad;
  604. /*
  605. * This is pretty tricky. We may get between 1 and many packets
  606. * back in response to the request. We peel the data out of
  607. * each packet and collect it in one long block. When the last
  608. * packet in the sequence is received we'll know how many we
  609. * should have had. Note we use one long time out, should reconsider.
  610. */
  611. *ritems = 0;
  612. *rsize = 0;
  613. firstpkt = 1;
  614. numrecv = 0;
  615. *rdata = datap = pktdata;
  616. lastseq = 999; /* too big to be a sequence number */
  617. memset(haveseq, 0, sizeof(haveseq));
  618. FD_ZERO(&fds);
  619. again:
  620. if (firstpkt)
  621. tvo = tvout;
  622. else
  623. tvo = tvsout;
  624. FD_SET(sockfd, &fds);
  625. n = select(sockfd+1, &fds, (fd_set *)0, (fd_set *)0, &tvo);
  626. if (n == -1) {
  627. warning("select fails", "", "");
  628. return -1;
  629. }
  630. if (n == 0) {
  631. /*
  632. * Timed out. Return what we have
  633. */
  634. if (firstpkt) {
  635. (void) fprintf(stderr,
  636. "%s: timed out, nothing received\n", currenthost);
  637. return ERR_TIMEOUT;
  638. } else {
  639. (void) fprintf(stderr,
  640. "%s: timed out with incomplete data\n",
  641. currenthost);
  642. if (debug) {
  643. printf("Received sequence numbers");
  644. for (n = 0; n <= MAXSEQ; n++)
  645. if (haveseq[n])
  646. printf(" %d,", n);
  647. if (lastseq != 999)
  648. printf(" last frame received\n");
  649. else
  650. printf(" last frame not received\n");
  651. }
  652. return ERR_INCOMPLETE;
  653. }
  654. }
  655. n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0);
  656. if (n == -1) {
  657. warning("read", "", "");
  658. return -1;
  659. }
  660. /*
  661. * Check for format errors. Bug proofing.
  662. */
  663. if (n < RESP_HEADER_SIZE) {
  664. if (debug)
  665. printf("Short (%d byte) packet received\n", n);
  666. goto again;
  667. }
  668. if (INFO_VERSION(rpkt.rm_vn_mode) > NTP_VERSION ||
  669. INFO_VERSION(rpkt.rm_vn_mode) < NTP_OLDVERSION) {
  670. if (debug)
  671. printf("Packet received with version %d\n",
  672. INFO_VERSION(rpkt.rm_vn_mode));
  673. goto again;
  674. }
  675. if (INFO_MODE(rpkt.rm_vn_mode) != MODE_PRIVATE) {
  676. if (debug)
  677. printf("Packet received with mode %d\n",
  678. INFO_MODE(rpkt.rm_vn_mode));
  679. goto again;
  680. }
  681. if (INFO_IS_AUTH(rpkt.auth_seq)) {
  682. if (debug)
  683. printf("Encrypted packet received\n");
  684. goto again;
  685. }
  686. if (!ISRESPONSE(rpkt.rm_vn_mode)) {
  687. if (debug)
  688. printf("Received request packet, wanted response\n");
  689. goto again;
  690. }
  691. if (INFO_MBZ(rpkt.mbz_itemsize) != 0) {
  692. if (debug)
  693. printf("Received packet with nonzero MBZ field!\n");
  694. goto again;
  695. }
  696. /*
  697. * Check implementation/request. Could be old data getting to us.
  698. */
  699. if (rpkt.implementation != implcode || rpkt.request != reqcode) {
  700. if (debug)
  701. printf(
  702. "Received implementation/request of %d/%d, wanted %d/%d",
  703. rpkt.implementation, rpkt.request,
  704. implcode, reqcode);
  705. goto again;
  706. }
  707. /*
  708. * Check the error code. If non-zero, return it.
  709. */
  710. if (INFO_ERR(rpkt.err_nitems) != INFO_OKAY) {
  711. if (debug && ISMORE(rpkt.rm_vn_mode)) {
  712. printf("Error code %d received on not-final packet\n",
  713. INFO_ERR(rpkt.err_nitems));
  714. }
  715. return (int)INFO_ERR(rpkt.err_nitems);
  716. }
  717. /*
  718. * Collect items and size. Make sure they make sense.
  719. */
  720. items = INFO_NITEMS(rpkt.err_nitems);
  721. size = INFO_ITEMSIZE(rpkt.mbz_itemsize);
  722. if (esize > size)
  723. pad = esize - size;
  724. else
  725. pad = 0;
  726. if ((datasize = items*size) > (n-RESP_HEADER_SIZE)) {
  727. if (debug)
  728. printf(
  729. "Received items %d, size %d (total %d), data in packet is %d\n",
  730. items, size, datasize, n-RESP_HEADER_SIZE);
  731. goto again;
  732. }
  733. /*
  734. * If this isn't our first packet, make sure the size matches
  735. * the other ones.
  736. */
  737. if (!firstpkt && esize != *rsize) {
  738. if (debug)
  739. printf("Received itemsize %d, previous %d\n",
  740. size, *rsize);
  741. goto again;
  742. }
  743. /*
  744. * If we've received this before, +toss it
  745. */
  746. seq = INFO_SEQ(rpkt.auth_seq);
  747. if (haveseq[seq]) {
  748. if (debug)
  749. printf("Received duplicate sequence number %d\n", seq);
  750. goto again;
  751. }
  752. haveseq[seq] = 1;
  753. /*
  754. * If this is the last in the sequence, record that.
  755. */
  756. if (!ISMORE(rpkt.rm_vn_mode)) {
  757. if (lastseq != 999) {
  758. printf("Received second end sequence packet\n");
  759. goto again;
  760. }
  761. lastseq = seq;
  762. }
  763. /*
  764. * So far, so good. Copy this data into the output array.
  765. */
  766. if ((datap + datasize + (pad * items)) > (pktdata + pktdatasize)) {
  767. int offset = datap - pktdata;
  768. growpktdata();
  769. *rdata = pktdata; /* might have been realloced ! */
  770. datap = pktdata + offset;
  771. }
  772. /*
  773. * We now move the pointer along according to size and number of
  774. * items. This is so we can play nice with older implementations
  775. */
  776. tmp_data = (char *)rpkt.data;
  777. for(i = 0; i <items; i++){
  778. memmove(datap, tmp_data, (unsigned)size);
  779. tmp_data += size;
  780. memset(datap + size, 0, pad);
  781. datap += size + pad;
  782. }
  783. if (firstpkt) {
  784. firstpkt = 0;
  785. *rsize = size + pad;
  786. }
  787. *ritems += items;
  788. /*
  789. * Finally, check the count of received packets. If we've got them
  790. * all, return
  791. */
  792. ++numrecv;
  793. if (numrecv <= lastseq)
  794. goto again;
  795. return INFO_OKAY;
  796. }
  797. /*
  798. * sendrequest - format and send a request packet
  799. */
  800. static int
  801. sendrequest(
  802. int implcode,
  803. int reqcode,
  804. int auth,
  805. int qitems,
  806. int qsize,
  807. char *qdata
  808. )
  809. {
  810. struct req_pkt qpkt;
  811. int datasize;
  812. memset((char *)&qpkt, 0, sizeof qpkt);
  813. qpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0);
  814. qpkt.implementation = (u_char)implcode;
  815. qpkt.request = (u_char)reqcode;
  816. datasize = qitems * qsize;
  817. if (datasize != 0 && qdata != NULL) {
  818. memmove((char *)qpkt.data, qdata, (unsigned)datasize);
  819. qpkt.err_nitems = ERR_NITEMS(0, qitems);
  820. qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize);
  821. } else {
  822. qpkt.err_nitems = ERR_NITEMS(0, 0);
  823. qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize); /* allow for optional first item */
  824. }
  825. if (!auth || (keyid_entered && info_auth_keyid == 0)) {
  826. qpkt.auth_seq = AUTH_SEQ(0, 0);
  827. return sendpkt((char *)&qpkt, req_pkt_size);
  828. } else {
  829. l_fp ts;
  830. int maclen = 0;
  831. const char *pass = "\0";
  832. struct req_pkt_tail *qpktail;
  833. qpktail = (struct req_pkt_tail *)((char *)&qpkt + req_pkt_size
  834. + MAX_MAC_LEN - sizeof(struct req_pkt_tail));
  835. if (info_auth_keyid == 0) {
  836. if (((struct conf_peer *)qpkt.data)->keyid > 0)
  837. info_auth_keyid = ((struct conf_peer *)qpkt.data)->keyid;
  838. else {
  839. maclen = getkeyid("Keyid: ");
  840. if (maclen == 0) {
  841. (void) fprintf(stderr,
  842. "Invalid key identifier\n");
  843. return 1;
  844. }
  845. info_auth_keyid = maclen;
  846. }
  847. }
  848. if (!authistrusted(info_auth_keyid)) {
  849. pass = getpass("MD5 Password: ");
  850. if (*pass == '\0') {
  851. (void) fprintf(stderr,
  852. "Invalid password\n");
  853. return (1);
  854. }
  855. }
  856. authusekey(info_auth_keyid, info_auth_keytype, (const u_char *)pass);
  857. authtrust(info_auth_keyid, 1);
  858. qpkt.auth_seq = AUTH_SEQ(1, 0);
  859. qpktail->keyid = htonl(info_auth_keyid);
  860. get_systime(&ts);
  861. L_ADD(&ts, &delay_time);
  862. HTONL_FP(&ts, &qpktail->tstamp);
  863. maclen = authencrypt(info_auth_keyid, (u_int32 *)&qpkt,
  864. req_pkt_size);
  865. if (maclen == 0) {
  866. (void) fprintf(stderr, "Key not found\n");
  867. return (1);
  868. }
  869. return sendpkt((char *)&qpkt, (int)(req_pkt_size + maclen));
  870. }
  871. /*NOTREACHED*/
  872. }
  873. /*
  874. * doquery - send a request and process the response
  875. */
  876. int
  877. doquery(
  878. int implcode,
  879. int reqcode,
  880. int auth,
  881. int qitems,
  882. int qsize,
  883. char *qdata,
  884. int *ritems,
  885. int *rsize,
  886. char **rdata,
  887. int quiet_mask,
  888. int esize
  889. )
  890. {
  891. int res;
  892. char junk[512];
  893. fd_set fds;
  894. struct timeval tvzero;
  895. /*
  896. * Check to make sure host is open
  897. */
  898. if (!havehost) {
  899. (void) fprintf(stderr, "***No host open, use `host' command\n");
  900. return -1;
  901. }
  902. /*
  903. * Poll the socket and clear out any pending data
  904. */
  905. again:
  906. do {
  907. tvzero.tv_sec = tvzero.tv_usec = 0;
  908. FD_ZERO(&fds);
  909. FD_SET(sockfd, &fds);
  910. res = select(sockfd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero);
  911. if (res == -1) {
  912. warning("polling select", "", "");
  913. return -1;
  914. } else if (res > 0)
  915. (void) recv(sockfd, junk, sizeof junk, 0);
  916. } while (res > 0);
  917. /*
  918. * send a request
  919. */
  920. res = sendrequest(implcode, reqcode, auth, qitems, qsize, qdata);
  921. if (res != 0)
  922. return res;
  923. /*
  924. * Get the response. If we got a standard error, print a message
  925. */
  926. res = getresponse(implcode, reqcode, ritems, rsize, rdata, esize);
  927. /*
  928. * Try to be compatible with older implementations of ntpd.
  929. */
  930. if (res == INFO_ERR_FMT && req_pkt_size != 48) {
  931. int oldsize;
  932. oldsize = req_pkt_size;
  933. switch(req_pkt_size) {
  934. case REQ_LEN_NOMAC:
  935. req_pkt_size = 160;
  936. break;
  937. case 160:
  938. req_pkt_size = 48;
  939. break;
  940. }
  941. if (impl_ver == IMPL_XNTPD) {
  942. fprintf(stderr,
  943. "***Warning changing to older implementation\n");
  944. return INFO_ERR_IMPL;
  945. }
  946. fprintf(stderr,
  947. "***Warning changing the request packet size from %d to %d\n",
  948. oldsize, req_pkt_size);
  949. goto again;
  950. }
  951. /* log error message if not told to be quiet */
  952. if ((res > 0) && (((1 << res) & quiet_mask) == 0)) {
  953. switch(res) {
  954. case INFO_ERR_IMPL:
  955. /* Give us a chance to try the older implementation. */
  956. if (implcode == IMPL_XNTPD)
  957. break;
  958. (void) fprintf(stderr,
  959. "***Server implementation incompatable with our own\n");
  960. break;
  961. case INFO_ERR_REQ:
  962. (void) fprintf(stderr,
  963. "***Server doesn't implement this request\n");
  964. break;
  965. case INFO_ERR_FMT:
  966. (void) fprintf(stderr,
  967. "***Server reports a format error in the received packet (shouldn't happen)\n");
  968. break;
  969. case INFO_ERR_NODATA:
  970. (void) fprintf(stderr,
  971. "***Server reports data not found\n");
  972. break;
  973. case INFO_ERR_AUTH:
  974. (void) fprintf(stderr, "***Permission denied\n");
  975. break;
  976. case ERR_TIMEOUT:
  977. (void) fprintf(stderr, "***Request timed out\n");
  978. break;
  979. case ERR_INCOMPLETE:
  980. (void) fprintf(stderr,
  981. "***Response from server was incomplete\n");
  982. break;
  983. default:
  984. (void) fprintf(stderr,
  985. "***Server returns unknown error code %d\n", res);
  986. break;
  987. }
  988. }
  989. return res;
  990. }
  991. /*
  992. * getcmds - read commands from the standard input and execute them
  993. */
  994. static void
  995. getcmds(void)
  996. {
  997. #if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT)
  998. char *line;
  999. for (;;) {
  1000. if ((line = readline(interactive?prompt:"")) == NULL) return;
  1001. if (*line) add_history(line);
  1002. docmd(line);
  1003. free(line);
  1004. }
  1005. #else /* not (HAVE_LIBREADLINE || HAVE_LIBEDIT) */
  1006. char line[MAXLINE];
  1007. for (;;) {
  1008. if (interactive) {
  1009. #ifdef VMS /* work around a problem with mixing stdout & stderr */
  1010. fputs("",stdout);
  1011. #endif
  1012. (void) fputs(prompt, stderr);
  1013. (void) fflush(stderr);
  1014. }
  1015. if (fgets(line, sizeof line, stdin) == NULL)
  1016. return;
  1017. docmd(line);
  1018. }
  1019. #endif /* not HAVE_LIBREADLINE || HAVE_LIBEDIT */
  1020. }
  1021. #ifndef SYS_WINNT /* Under NT cannot handle SIGINT, WIN32 spawns a handler */
  1022. /*
  1023. * abortcmd - catch interrupts and abort the current command
  1024. */
  1025. static RETSIGTYPE
  1026. abortcmd(
  1027. int sig
  1028. )
  1029. {
  1030. if (current_output == stdout)
  1031. (void) fflush(stdout);
  1032. putc('\n', stderr);
  1033. (void) fflush(stderr);
  1034. if (jump) longjmp(interrupt_buf, 1);
  1035. }
  1036. #endif /* SYS_WINNT */
  1037. /*
  1038. * docmd - decode the command line and execute a command
  1039. */
  1040. static void
  1041. docmd(
  1042. const char *cmdline
  1043. )
  1044. {
  1045. char *tokens[1+MAXARGS+MOREARGS+2];
  1046. struct parse pcmd;
  1047. int ntok;
  1048. int i, ti;
  1049. int rval;
  1050. struct xcmd *xcmd;
  1051. ai_fam_templ = ai_fam_default;
  1052. /*
  1053. * Tokenize the command line. If nothing on it, return.
  1054. */
  1055. tokenize(cmdline, tokens, &ntok);
  1056. if (ntok == 0)
  1057. return;
  1058. /*
  1059. * Find the appropriate command description.
  1060. */
  1061. i = findcmd(tokens[0], builtins, opcmds, &xcmd);
  1062. if (i == 0) {
  1063. (void) fprintf(stderr, "***Command `%s' unknown\n",
  1064. tokens[0]);
  1065. return;
  1066. } else if (i >= 2) {
  1067. (void) fprintf(stderr, "***Command `%s' ambiguous\n",
  1068. tokens[0]);
  1069. return;
  1070. }
  1071. /*
  1072. * Save the keyword, then walk through the arguments, interpreting
  1073. * as we go.
  1074. */
  1075. pcmd.keyword = tokens[0];
  1076. pcmd.nargs = 0;
  1077. ti = 1;
  1078. for (i = 0; i < MAXARGS && xcmd->arg[i] != NO;) {
  1079. if ((i+ti) >= ntok) {
  1080. if (!(xcmd->arg[i] & OPT)) {
  1081. printusage(xcmd, stderr);
  1082. return;
  1083. }
  1084. break;
  1085. }
  1086. if ((xcmd->arg[i] & OPT) && (*tokens[i+ti] == '>'))
  1087. break;
  1088. rval = getarg(tokens[i+ti], (int)xcmd->arg[i], &pcmd.argval[i]);
  1089. if (rval == -1) {
  1090. ti++;
  1091. continue;
  1092. }
  1093. if (rval == 0)
  1094. return;
  1095. pcmd.nargs++;
  1096. i++;
  1097. }
  1098. /* Any extra args are assumed to be "OPT|NTP_STR". */
  1099. for ( ; i < MAXARGS + MOREARGS;) {
  1100. if ((i+ti) >= ntok)
  1101. break;
  1102. rval = getarg(tokens[i+ti], (int)(OPT|NTP_STR), &pcmd.argval[i]);
  1103. if (rval == -1) {
  1104. ti++;
  1105. continue;
  1106. }
  1107. if (rval == 0)
  1108. return;
  1109. pcmd.nargs++;
  1110. i++;
  1111. }
  1112. i += ti;
  1113. if (i < ntok && *tokens[i] == '>') {
  1114. char *fname;
  1115. if (*(tokens[i]+1) != '\0')
  1116. fname = tokens[i]+1;
  1117. else if ((i+1) < ntok)
  1118. fname = tokens[i+1];
  1119. else {
  1120. (void) fprintf(stderr, "***No file for redirect\n");
  1121. return;
  1122. }
  1123. current_output = fopen(fname, "w");
  1124. if (current_output == NULL) {
  1125. (void) fprintf(stderr, "***Error opening %s: ", fname);
  1126. perror("");
  1127. return;
  1128. }
  1129. } else {
  1130. current_output = stdout;
  1131. }
  1132. if (interactive && setjmp(interrupt_buf)) {
  1133. return;
  1134. } else {
  1135. jump = 1;
  1136. (xcmd->handler)(&pcmd, current_output);
  1137. jump = 0;
  1138. if (current_output != stdout)
  1139. (void) fclose(current_output);
  1140. current_output = NULL;
  1141. }
  1142. }
  1143. /*
  1144. * tokenize - turn a command line into tokens
  1145. */
  1146. static void
  1147. tokenize(
  1148. const char *line,
  1149. char **tokens,
  1150. int *ntok
  1151. )
  1152. {
  1153. register const char *cp;
  1154. register char *sp;
  1155. static char tspace[MAXLINE];
  1156. sp = tspace;
  1157. cp = line;
  1158. for (*ntok = 0; *ntok < MAXTOKENS; (*ntok)++) {
  1159. tokens[*ntok] = sp;
  1160. while (ISSPACE(*cp))
  1161. cp++;
  1162. if (ISEOL(*cp))
  1163. break;
  1164. do {
  1165. *sp++ = *cp++;
  1166. } while (!ISSPACE(*cp) && !ISEOL(*cp));
  1167. *sp++ = '\0';
  1168. }
  1169. }
  1170. /*
  1171. * findcmd - find a command in a command description table
  1172. */
  1173. static int
  1174. findcmd(
  1175. register char *str,
  1176. struct xcmd *clist1,
  1177. struct xcmd *clist2,
  1178. struct xcmd **cmd
  1179. )
  1180. {
  1181. register struct xcmd *cl;
  1182. register int clen;
  1183. int nmatch;
  1184. struct xcmd *nearmatch = NULL;
  1185. struct xcmd *clist;
  1186. clen = strlen(str);
  1187. nmatch = 0;
  1188. if (clist1 != 0)
  1189. clist = clist1;
  1190. else if (clist2 != 0)
  1191. clist = clist2;
  1192. else
  1193. return 0;
  1194. again:
  1195. for (cl = clist; cl->keyword != 0; cl++) {
  1196. /* do a first character check, for efficiency */
  1197. if (*str != *(cl->keyword))
  1198. continue;
  1199. if (strncmp(str, cl->keyword, (unsigned)clen) == 0) {
  1200. /*
  1201. * Could be extact match, could be approximate.
  1202. * Is exact if the length of the keyword is the
  1203. * same as the str.
  1204. */
  1205. if (*((cl->keyword) + clen) == '\0') {
  1206. *cmd = cl;
  1207. return 1;
  1208. }
  1209. nmatch++;
  1210. nearmatch = cl;
  1211. }
  1212. }
  1213. /*
  1214. * See if there is more to do. If so, go again. Sorry about the
  1215. * goto, too much looking at BSD sources...
  1216. */
  1217. if (clist == clist1 && clist2 != 0) {
  1218. clist = clist2;
  1219. goto again;
  1220. }
  1221. /*
  1222. * If we got extactly 1 near match, use it, else return number
  1223. * of matches.
  1224. */
  1225. if (nmatch == 1) {
  1226. *cmd = nearmatch;
  1227. return 1;
  1228. }
  1229. return nmatch;
  1230. }
  1231. /*
  1232. * getarg - interpret an argument token
  1233. *
  1234. * string is always set.
  1235. * type is set to the decoded type.
  1236. *
  1237. * return: 0 - failure
  1238. * 1 - success
  1239. * -1 - skip to next token
  1240. */
  1241. static int
  1242. getarg(
  1243. char *str,
  1244. int code,
  1245. arg_v *argp
  1246. )
  1247. {
  1248. int isneg;
  1249. char *cp, *np;
  1250. static const char *digits = "0123456789";
  1251. memset(argp, 0, sizeof(*argp));
  1252. argp->string = str;
  1253. argp->type = code & ~OPT;
  1254. switch (argp->type) {
  1255. case NTP_STR:
  1256. break;
  1257. case NTP_ADD:
  1258. if (!strcmp("-6", str)) {
  1259. ai_fam_templ = AF_INET6;
  1260. return -1;
  1261. } else if (!strcmp("-4", str)) {
  1262. ai_fam_templ = AF_INET;
  1263. return -1;
  1264. }
  1265. if (!getnetnum(str, &(argp->netnum), (char *)0, 0)) {
  1266. return 0;
  1267. }
  1268. break;
  1269. case NTP_INT:
  1270. case NTP_UINT:
  1271. isneg = 0;
  1272. np = str;
  1273. if (*np == '-') {
  1274. np++;
  1275. isneg = 1;
  1276. }
  1277. argp->uval = 0;
  1278. do {
  1279. cp = strchr(digits, *np);
  1280. if (cp == NULL) {
  1281. (void) fprintf(stderr,
  1282. "***Illegal integer value %s\n", str);
  1283. return 0;
  1284. }
  1285. argp->uval *= 10;
  1286. argp->uval += (cp - digits);
  1287. } while (*(++np) != '\0');
  1288. if (isneg) {
  1289. if ((code & ~OPT) == NTP_UINT) {
  1290. (void) fprintf(stderr,
  1291. "***Value %s should be unsigned\n", str);
  1292. return 0;
  1293. }
  1294. argp->ival = -argp->ival;
  1295. }
  1296. break;
  1297. case IP_VERSION:
  1298. if (!strcmp("-6", str))
  1299. argp->ival = 6 ;
  1300. else if (!strcmp("-4", str))
  1301. argp->ival = 4 ;
  1302. else {
  1303. (void) fprintf(stderr,
  1304. "***Version must be either 4 or 6\n");
  1305. return 0;
  1306. }
  1307. break;
  1308. }
  1309. return 1;
  1310. }
  1311. /*
  1312. * getnetnum - given a host name, return its net number
  1313. * and (optional) full name
  1314. */
  1315. static int
  1316. getnetnum(
  1317. const char *hname,
  1318. struct sockaddr_storage *num,
  1319. char *fullhost,
  1320. int af
  1321. )
  1322. {
  1323. int sockaddr_len;
  1324. struct addrinfo hints, *ai = NULL;
  1325. sockaddr_len = (af == AF_INET)
  1326. ? sizeof(struct sockaddr_in)
  1327. : sizeof(struct sockaddr_in6);
  1328. memset((char *)&hints, 0, sizeof(struct addrinfo));
  1329. hints.ai_flags = AI_CANONNAME;
  1330. #ifdef AI_ADDRCONFIG
  1331. hints.ai_flags |= AI_ADDRCONFIG;
  1332. #endif
  1333. /* decodenetnum only works with addresses */
  1334. if (decodenetnum(hname, num)) {
  1335. if (fullhost != 0) {
  1336. getnameinfo((struct sockaddr *)num, sockaddr_len,
  1337. fullhost, sizeof(fullhost), NULL, 0,
  1338. NI_NUMERICHOST);
  1339. }
  1340. return 1;
  1341. } else if (getaddrinfo(hname, "ntp", &hints, &ai) == 0) {
  1342. memmove((char *)num, ai->ai_addr, ai->ai_addrlen);
  1343. if (fullhost != 0)
  1344. (void) strcpy(fullhost, ai->ai_canonname);
  1345. return 1;
  1346. } else {
  1347. (void) fprintf(stderr, "***Can't find host %s\n", hname);
  1348. return 0;
  1349. }
  1350. /*NOTREACHED*/
  1351. }
  1352. /*
  1353. * nntohost - convert network number to host name. This routine enforces
  1354. * the showhostnames setting.
  1355. */
  1356. char *
  1357. nntohost(
  1358. struct sockaddr_storage *netnum
  1359. )
  1360. {
  1361. if (!showhostnames)
  1362. return stoa(netnum);
  1363. if ((netnum->ss_family == AF_INET) && ISREFCLOCKADR(netnum))
  1364. return refnumtoa(netnum);
  1365. return socktohost(netnum);
  1366. }
  1367. /*
  1368. * Finally, the built in command handlers
  1369. */
  1370. /*
  1371. * help - tell about commands, or details of a particular command
  1372. */
  1373. static void
  1374. help(
  1375. struct parse *pcmd,
  1376. FILE *fp
  1377. )
  1378. {
  1379. struct xcmd *xcp;
  1380. char *cmd;
  1381. const char *list[100];
  1382. int word, words;
  1383. int row, rows;
  1384. int col, cols;
  1385. if (pcmd->nargs == 0) {
  1386. words = 0;
  1387. for (xcp = builtins; xcp->keyword != 0; xcp++) {
  1388. if (*(xcp->keyword) != '?')
  1389. list[words++] = xcp->keyword;
  1390. }
  1391. for (xcp = opcmds; xcp->keyword != 0; xcp++)
  1392. list[words++] = xcp->keyword;
  1393. qsort(
  1394. #ifdef QSORT_USES_VOID_P
  1395. (void *)
  1396. #else
  1397. (char *)
  1398. #endif
  1399. (list), (size_t)(words), sizeof(char *), helpsort);
  1400. col = 0;
  1401. for (word = 0; word < words; word++) {
  1402. int length = strlen(list[word]);
  1403. if (col < length) {
  1404. col = length;
  1405. }
  1406. }
  1407. cols = SCREENWIDTH / ++col;
  1408. rows = (words + cols - 1) / cols;
  1409. (void) fprintf(fp, "ntpdc commands:\n");
  1410. for (row = 0; row < rows; row++) {
  1411. for (word = row; word < words; word += rows) {
  1412. (void) fprintf(fp, "%-*.*s", col, col-1, list[word]);
  1413. }
  1414. (void) fprintf(fp, "\n");
  1415. }
  1416. } else {
  1417. cmd = pcmd->argval[0].string;
  1418. words = findcmd(cmd, builtins, opcmds, &xcp);
  1419. if (words == 0) {
  1420. (void) fprintf(stderr,
  1421. "Command `%s' is unknown\n", cmd);
  1422. return;
  1423. } else if (words >= 2) {
  1424. (void) fprintf(stderr,
  1425. "Command `%s' is ambiguous\n", cmd);
  1426. return;
  1427. }
  1428. (void) fprintf(fp, "function: %s\n", xcp->comment);
  1429. printusage(xcp, fp);
  1430. }
  1431. }
  1432. /*
  1433. * helpsort - do hostname qsort comparisons
  1434. */
  1435. #ifdef QSORT_USES_VOID_P
  1436. static int
  1437. helpsort(
  1438. const void *t1,
  1439. const void *t2
  1440. )
  1441. {
  1442. char const * const * name1 = (char const * const *)t1;
  1443. char const * const * name2 = (char const * const *)t2;
  1444. return strcmp(*name1, *name2);
  1445. }
  1446. #else
  1447. static int
  1448. helpsort(
  1449. char **name1,
  1450. char **name2
  1451. )
  1452. {
  1453. return strcmp(*name1, *name2);
  1454. }
  1455. #endif
  1456. /*
  1457. * printusage - print usage information for a command
  1458. */
  1459. static void
  1460. printusage(
  1461. struct xcmd *xcp,
  1462. FILE *fp
  1463. )
  1464. {
  1465. int i, opt46;
  1466. opt46 = 0;
  1467. (void) fprintf(fp, "usage: %s", xcp->keyword);
  1468. for (i = 0; i < MAXARGS && xcp->arg[i] != NO; i++) {
  1469. if (opt46 == 0 && (xcp->arg[i] & ~OPT) == NTP_ADD) {
  1470. (void) fprintf(fp, " [ -4|-6 ]");
  1471. opt46 = 1;
  1472. }
  1473. if (xcp->arg[i] & OPT)
  1474. (void) fprintf(fp, " [ %s ]", xcp->desc[i]);
  1475. else
  1476. (void) fprintf(fp, " %s", xcp->desc[i]);
  1477. }
  1478. (void) fprintf(fp, "\n");
  1479. }
  1480. /*
  1481. * timeout - set time out time
  1482. */
  1483. static void
  1484. timeout(
  1485. struct parse *pcmd,
  1486. FILE *fp
  1487. )
  1488. {
  1489. int val;
  1490. if (pcmd->nargs == 0) {
  1491. val = tvout.tv_sec * 1000 + tvout.tv_usec / 1000;
  1492. (void) fprintf(fp, "primary timeout %d ms\n", val);
  1493. } else {
  1494. tvout.tv_sec = pcmd->argval[0].uval / 1000;
  1495. tvout.tv_usec = (pcmd->argval[0].uval - (tvout.tv_sec * 1000))
  1496. * 1000;
  1497. }
  1498. }
  1499. /*
  1500. * my_delay - set delay for auth requests
  1501. */
  1502. static void
  1503. my_delay(
  1504. struct parse *pcmd,
  1505. FILE *fp
  1506. )
  1507. {
  1508. int isneg;
  1509. u_long val;
  1510. if (pcmd->nargs == 0) {
  1511. val = delay_time.l_ui * 1000 + delay_time.l_uf / 4294967;
  1512. (void) fprintf(fp, "delay %lu ms\n", val);
  1513. } else {
  1514. if (pcmd->argval[0].ival < 0) {
  1515. isneg = 1;
  1516. val = (u_long)(-pcmd->argval[0].ival);
  1517. } else {
  1518. isneg = 0;
  1519. val = (u_long)pcmd->argval[0].ival;
  1520. }
  1521. delay_time.l_ui = val / 1000;
  1522. val %= 1000;
  1523. delay_time.l_uf = val * 4294967; /* 2**32/1000 */
  1524. if (isneg)
  1525. L_NEG(&delay_time);
  1526. }
  1527. }
  1528. /*
  1529. * host - set the host we are dealing with.
  1530. */
  1531. static void
  1532. host(
  1533. struct parse *pcmd,
  1534. FILE *fp
  1535. )
  1536. {
  1537. int i;
  1538. if (pcmd->nargs == 0) {
  1539. if (havehost)
  1540. (void) fprintf(fp, "current host is %s\n", currenthost);
  1541. else
  1542. (void) fprintf(fp, "no current host\n");
  1543. return;
  1544. }
  1545. i = 0;
  1546. if (pcmd->nargs == 2) {
  1547. if (!strcmp("-4", pcmd->argval[i].string))
  1548. ai_fam_templ = AF_INET;
  1549. else if (!strcmp("-6", pcmd->argval[i].string))
  1550. ai_fam_templ = AF_INET6;
  1551. else {
  1552. if (havehost)
  1553. (void) fprintf(fp,
  1554. "current host remains %s\n", currenthost);
  1555. else
  1556. (void) fprintf(fp, "still no current host\n");
  1557. return;
  1558. }
  1559. i = 1;
  1560. }
  1561. if (openhost(pcmd->argval[i].string)) {
  1562. (void) fprintf(fp, "current host set to %s\n", currenthost);
  1563. } else {
  1564. if (havehost)
  1565. (void) fprintf(fp,
  1566. "current host remains %s\n", currenthost);
  1567. else
  1568. (void) fprintf(fp, "still no current host\n");
  1569. }
  1570. }
  1571. /*
  1572. * keyid - get a keyid to use for authenticating requests
  1573. */
  1574. static void
  1575. keyid(
  1576. struct parse *pcmd,
  1577. FILE *fp
  1578. )
  1579. {
  1580. if (pcmd->nargs == 0) {
  1581. if (info_auth_keyid == 0 && !keyid_entered)
  1582. (void) fprintf(fp, "no keyid defined\n");
  1583. else if (info_auth_keyid == 0 && keyid_entered)
  1584. (void) fprintf(fp, "no keyid will be sent\n");
  1585. else
  1586. (void) fprintf(fp, "keyid is %lu\n", (u_long)info_auth_keyid);
  1587. } else {
  1588. info_auth_keyid = pcmd->argval[0].uval;
  1589. keyid_entered = 1;
  1590. }
  1591. }
  1592. /*
  1593. * keytype - get type of key to use for authenticating requests
  1594. */
  1595. static void
  1596. keytype(
  1597. struct parse *pcmd,
  1598. FILE *fp
  1599. )
  1600. {
  1601. if (pcmd->nargs == 0)
  1602. fprintf(fp, "keytype is %s\n",
  1603. (info_auth_keytype == KEY_TYPE_MD5) ? "MD5" : "???");
  1604. else
  1605. switch (*(pcmd->argval[0].string)) {
  1606. case 'm':
  1607. case 'M':
  1608. info_auth_keytype = KEY_TYPE_MD5;
  1609. break;
  1610. default:
  1611. fprintf(fp, "keytype must be 'md5'\n");
  1612. }
  1613. }
  1614. /*
  1615. * passwd - get an authentication key
  1616. */
  1617. /*ARGSUSED*/
  1618. static void
  1619. passwd(
  1620. struct parse *pcmd,
  1621. FILE *fp
  1622. )
  1623. {
  1624. char *pass;
  1625. if (info_auth_keyid == 0) {
  1626. info_auth_keyid = getkeyid("Keyid: ");
  1627. if (info_auth_keyid == 0) {
  1628. (void)fprintf(fp, "Keyid must be defined\n");
  1629. return;
  1630. }
  1631. }
  1632. if (!interactive) {
  1633. authusekey(info_auth_keyid, info_auth_keytype,
  1634. (u_char *)pcmd->argval[0].string);
  1635. authtrust(info_auth_keyid, 1);
  1636. } else {
  1637. pass = getpass("MD5 Password: ");
  1638. if (*pass == '\0')
  1639. (void) fprintf(fp, "Password unchanged\n");
  1640. else {
  1641. authusekey(info_auth_keyid, info_auth_keytype,
  1642. (u_char *)pass);
  1643. authtrust(info_auth_keyid, 1);
  1644. }
  1645. }
  1646. }
  1647. /*
  1648. * hostnames - set the showhostnames flag
  1649. */
  1650. static void
  1651. hostnames(
  1652. struct parse *pcmd,
  1653. FILE *fp
  1654. )
  1655. {
  1656. if (pcmd->nargs == 0) {
  1657. if (showhostnames)
  1658. (void) fprintf(fp, "hostnames being shown\n");
  1659. else
  1660. (void) fprintf(fp, "hostnames not being shown\n");
  1661. } else {
  1662. if (STREQ(pcmd->argval[0].string, "yes"))
  1663. showhostnames = 1;
  1664. else if (STREQ(pcmd->argval[0].string, "no"))
  1665. showhostnames = 0;
  1666. else
  1667. (void)fprintf(stderr, "What?\n");
  1668. }
  1669. }
  1670. /*
  1671. * setdebug - set/change debugging level
  1672. */
  1673. static void
  1674. setdebug(
  1675. struct parse *pcmd,
  1676. FILE *fp
  1677. )
  1678. {
  1679. if (pcmd->nargs == 0) {
  1680. (void) fprintf(fp, "debug level is %d\n", debug);
  1681. return;
  1682. } else if (STREQ(pcmd->argval[0].string, "no")) {
  1683. debug = 0;
  1684. } else if (STREQ(pcmd->argval[0].string, "more")) {
  1685. debug++;
  1686. } else if (STREQ(pcmd->argval[0].string, "less")) {
  1687. debug--;
  1688. } else {
  1689. (void) fprintf(fp, "What?\n");
  1690. return;
  1691. }
  1692. (void) fprintf(fp, "debug level set to %d\n", debug);
  1693. }
  1694. /*
  1695. * quit - stop this nonsense
  1696. */
  1697. /*ARGSUSED*/
  1698. static void
  1699. quit(
  1700. struct parse *pcmd,
  1701. FILE *fp
  1702. )
  1703. {
  1704. if (havehost)
  1705. closesocket(sockfd);
  1706. exit(0);
  1707. }
  1708. /*
  1709. * version - print the current version number
  1710. */
  1711. /*ARGSUSED*/
  1712. static void
  1713. version(
  1714. struct parse *pcmd,
  1715. FILE *fp
  1716. )
  1717. {
  1718. (void) fprintf(fp, "%s\n", Version);
  1719. return;
  1720. }
  1721. /*
  1722. * warning - print a warning message
  1723. */
  1724. static void
  1725. warning(
  1726. const char *fmt,
  1727. const char *st1,
  1728. const char *st2
  1729. )
  1730. {
  1731. (void) fprintf(stderr, "%s: ", progname);
  1732. (void) fprintf(stderr, fmt, st1, st2);
  1733. (void) fprintf(stderr, ": ");
  1734. perror("");
  1735. }
  1736. /*
  1737. * error - print a message and exit
  1738. */
  1739. static void
  1740. error(
  1741. const char *fmt,
  1742. const char *st1,
  1743. const char *st2
  1744. )
  1745. {
  1746. warning(fmt, st1, st2);
  1747. exit(1);
  1748. }
  1749. /*
  1750. * getkeyid - prompt the user for a keyid to use
  1751. */
  1752. static u_long
  1753. getkeyid(
  1754. const char *keyprompt
  1755. )
  1756. {
  1757. register char *p;
  1758. register int c;
  1759. FILE *fi;
  1760. char pbuf[20];
  1761. #ifndef SYS_WINNT
  1762. if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
  1763. #else
  1764. if ((fi = _fdopen((int)GetStdHandle(STD_INPUT_HANDLE), "r")) == NULL)
  1765. #endif /* SYS_WINNT */
  1766. fi = stdin;
  1767. else
  1768. setbuf(fi, (char *)NULL);
  1769. fprintf(stderr, "%s", keyprompt); fflush(stderr);
  1770. for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) {
  1771. if (p < &pbuf[18])
  1772. *p++ = (char) c;
  1773. }
  1774. *p = '\0';
  1775. if (fi != stdin)
  1776. fclose(fi);
  1777. return (u_int32)atoi(pbuf);
  1778. }