/contrib/ntp/ntpd/ntp_refclock.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1229 lines · 762 code · 134 blank · 333 comment · 155 complexity · a8a7d33697cd7f64653a63518f78c652 MD5 · raw file

  1. /*
  2. * ntp_refclock - processing support for reference clocks
  3. */
  4. #ifdef HAVE_CONFIG_H
  5. # include <config.h>
  6. #endif
  7. #include "ntpd.h"
  8. #include "ntp_io.h"
  9. #include "ntp_unixtime.h"
  10. #include "ntp_tty.h"
  11. #include "ntp_refclock.h"
  12. #include "ntp_stdlib.h"
  13. #include <stdio.h>
  14. #ifdef HAVE_SYS_IOCTL_H
  15. # include <sys/ioctl.h>
  16. #endif /* HAVE_SYS_IOCTL_H */
  17. #ifdef REFCLOCK
  18. #ifdef TTYCLK
  19. # ifdef HAVE_SYS_CLKDEFS_H
  20. # include <sys/clkdefs.h>
  21. # include <stropts.h>
  22. # endif
  23. # ifdef HAVE_SYS_SIO_H
  24. # include <sys/sio.h>
  25. # endif
  26. #endif /* TTYCLK */
  27. #ifdef KERNEL_PLL
  28. #include "ntp_syscall.h"
  29. #endif /* KERNEL_PLL */
  30. /*
  31. * Reference clock support is provided here by maintaining the fiction
  32. * that the clock is actually a peer. As no packets are exchanged with a
  33. * reference clock, however, we replace the transmit, receive and packet
  34. * procedures with separate code to simulate them. Routines
  35. * refclock_transmit() and refclock_receive() maintain the peer
  36. * variables in a state analogous to an actual peer and pass reference
  37. * clock data on through the filters. Routines refclock_peer() and
  38. * refclock_unpeer() are called to initialize and terminate reference
  39. * clock associations. A set of utility routines is included to open
  40. * serial devices, process sample data, edit input lines to extract
  41. * embedded timestamps and to peform various debugging functions.
  42. *
  43. * The main interface used by these routines is the refclockproc
  44. * structure, which contains for most drivers the decimal equivalants of
  45. * the year, day, month, hour, second and millisecond/microsecond
  46. * decoded from the ASCII timecode. Additional information includes the
  47. * receive timestamp, exception report, statistics tallies, etc. In
  48. * addition, there may be a driver-specific unit structure used for
  49. * local control of the device.
  50. *
  51. * The support routines are passed a pointer to the peer structure,
  52. * which is used for all peer-specific processing and contains a pointer
  53. * to the refclockproc structure, which in turn containes a pointer to
  54. * the unit structure, if used. The peer structure is identified by an
  55. * interface address in the dotted quad form 127.127.t.u (for now only
  56. * IPv4 addresses are used, so we need to be sure the address is it),
  57. * where t is the clock type and u the unit. Some legacy drivers derive
  58. * the refclockproc structure pointer from the table
  59. * typeunit[type][unit]. This interface is strongly discouraged and may
  60. * be abandoned in future.
  61. */
  62. #define MAXUNIT 4 /* max units */
  63. #define FUDGEFAC .1 /* fudge correction factor */
  64. #define LF 0x0a /* ASCII LF */
  65. #ifdef PPS
  66. int fdpps; /* ppsclock legacy */
  67. #endif /* PPS */
  68. int cal_enable; /* enable refclock calibrate */
  69. /*
  70. * Type/unit peer index. Used to find the peer structure for control and
  71. * debugging. When all clock drivers have been converted to new style,
  72. * this dissapears.
  73. */
  74. static struct peer *typeunit[REFCLK_MAX + 1][MAXUNIT];
  75. /*
  76. * Forward declarations
  77. */
  78. #ifdef QSORT_USES_VOID_P
  79. static int refclock_cmpl_fp P((const void *, const void *));
  80. #else
  81. static int refclock_cmpl_fp P((const double *, const double *));
  82. #endif /* QSORT_USES_VOID_P */
  83. static int refclock_sample P((struct refclockproc *));
  84. /*
  85. * refclock_report - note the occurance of an event
  86. *
  87. * This routine presently just remembers the report and logs it, but
  88. * does nothing heroic for the trap handler. It tries to be a good
  89. * citizen and bothers the system log only if things change.
  90. */
  91. void
  92. refclock_report(
  93. struct peer *peer,
  94. int code
  95. )
  96. {
  97. struct refclockproc *pp;
  98. pp = peer->procptr;
  99. if (pp == NULL)
  100. return;
  101. switch (code) {
  102. case CEVNT_NOMINAL:
  103. break;
  104. case CEVNT_TIMEOUT:
  105. pp->noreply++;
  106. break;
  107. case CEVNT_BADREPLY:
  108. pp->badformat++;
  109. break;
  110. case CEVNT_FAULT:
  111. break;
  112. case CEVNT_PROP:
  113. break;
  114. case CEVNT_BADDATE:
  115. case CEVNT_BADTIME:
  116. pp->baddata++;
  117. break;
  118. default:
  119. /* shouldn't happen */
  120. break;
  121. }
  122. if (pp->currentstatus != code) {
  123. pp->currentstatus = (u_char)code;
  124. /* RFC1305: copy only iff not CEVNT_NOMINAL */
  125. if (code != CEVNT_NOMINAL)
  126. pp->lastevent = (u_char)code;
  127. if (code == CEVNT_FAULT)
  128. msyslog(LOG_ERR,
  129. "clock %s event '%s' (0x%02x)",
  130. refnumtoa(&peer->srcadr),
  131. ceventstr(code), code);
  132. else {
  133. NLOG(NLOG_CLOCKEVENT)
  134. msyslog(LOG_INFO,
  135. "clock %s event '%s' (0x%02x)",
  136. refnumtoa(&peer->srcadr),
  137. ceventstr(code), code);
  138. }
  139. /* RFC1305: post peer clock event */
  140. report_event(EVNT_PEERCLOCK, peer);
  141. }
  142. }
  143. /*
  144. * init_refclock - initialize the reference clock drivers
  145. *
  146. * This routine calls each of the drivers in turn to initialize internal
  147. * variables, if necessary. Most drivers have nothing to say at this
  148. * point.
  149. */
  150. void
  151. init_refclock(void)
  152. {
  153. int i, j;
  154. for (i = 0; i < (int)num_refclock_conf; i++) {
  155. if (refclock_conf[i]->clock_init != noentry)
  156. (refclock_conf[i]->clock_init)();
  157. for (j = 0; j < MAXUNIT; j++)
  158. typeunit[i][j] = 0;
  159. }
  160. }
  161. /*
  162. * refclock_newpeer - initialize and start a reference clock
  163. *
  164. * This routine allocates and initializes the interface structure which
  165. * supports a reference clock in the form of an ordinary NTP peer. A
  166. * driver-specific support routine completes the initialization, if
  167. * used. Default peer variables which identify the clock and establish
  168. * its reference ID and stratum are set here. It returns one if success
  169. * and zero if the clock address is invalid or already running,
  170. * insufficient resources are available or the driver declares a bum
  171. * rap.
  172. */
  173. int
  174. refclock_newpeer(
  175. struct peer *peer /* peer structure pointer */
  176. )
  177. {
  178. struct refclockproc *pp;
  179. u_char clktype;
  180. int unit;
  181. /*
  182. * Check for valid clock address. If already running, shut it
  183. * down first.
  184. */
  185. if (peer->srcadr.ss_family != AF_INET) {
  186. msyslog(LOG_ERR,
  187. "refclock_newpeer: clock address %s invalid, address family not implemented for refclock",
  188. stoa(&peer->srcadr));
  189. return (0);
  190. }
  191. if (!ISREFCLOCKADR(&peer->srcadr)) {
  192. msyslog(LOG_ERR,
  193. "refclock_newpeer: clock address %s invalid",
  194. stoa(&peer->srcadr));
  195. return (0);
  196. }
  197. clktype = (u_char)REFCLOCKTYPE(&peer->srcadr);
  198. unit = REFCLOCKUNIT(&peer->srcadr);
  199. if (clktype >= num_refclock_conf || unit >= MAXUNIT ||
  200. refclock_conf[clktype]->clock_start == noentry) {
  201. msyslog(LOG_ERR,
  202. "refclock_newpeer: clock type %d invalid\n",
  203. clktype);
  204. return (0);
  205. }
  206. /*
  207. * Allocate and initialize interface structure
  208. */
  209. pp = (struct refclockproc *)emalloc(sizeof(struct refclockproc));
  210. if (pp == NULL)
  211. return (0);
  212. memset((char *)pp, 0, sizeof(struct refclockproc));
  213. typeunit[clktype][unit] = peer;
  214. peer->procptr = pp;
  215. /*
  216. * Initialize structures
  217. */
  218. peer->refclktype = clktype;
  219. peer->refclkunit = (u_char)unit;
  220. peer->flags |= FLAG_REFCLOCK | FLAG_FIXPOLL;
  221. peer->leap = LEAP_NOTINSYNC;
  222. peer->stratum = STRATUM_REFCLOCK;
  223. peer->ppoll = peer->maxpoll;
  224. pp->type = clktype;
  225. pp->timestarted = current_time;
  226. /*
  227. * Set peer.pmode based on the hmode. For appearances only.
  228. */
  229. switch (peer->hmode) {
  230. case MODE_ACTIVE:
  231. peer->pmode = MODE_PASSIVE;
  232. break;
  233. default:
  234. peer->pmode = MODE_SERVER;
  235. break;
  236. }
  237. /*
  238. * Do driver dependent initialization. The above defaults
  239. * can be wiggled, then finish up for consistency.
  240. */
  241. if (!((refclock_conf[clktype]->clock_start)(unit, peer))) {
  242. refclock_unpeer(peer);
  243. return (0);
  244. }
  245. peer->refid = pp->refid;
  246. return (1);
  247. }
  248. /*
  249. * refclock_unpeer - shut down a clock
  250. */
  251. void
  252. refclock_unpeer(
  253. struct peer *peer /* peer structure pointer */
  254. )
  255. {
  256. u_char clktype;
  257. int unit;
  258. /*
  259. * Wiggle the driver to release its resources, then give back
  260. * the interface structure.
  261. */
  262. if (!peer->procptr)
  263. return;
  264. clktype = peer->refclktype;
  265. unit = peer->refclkunit;
  266. if (refclock_conf[clktype]->clock_shutdown != noentry)
  267. (refclock_conf[clktype]->clock_shutdown)(unit, peer);
  268. free(peer->procptr);
  269. peer->procptr = 0;
  270. }
  271. /*
  272. * refclock_timer - called once per second for housekeeping.
  273. */
  274. void
  275. refclock_timer(
  276. struct peer *peer /* peer structure pointer */
  277. )
  278. {
  279. u_char clktype;
  280. int unit;
  281. clktype = peer->refclktype;
  282. unit = peer->refclkunit;
  283. if (refclock_conf[clktype]->clock_timer != noentry)
  284. (refclock_conf[clktype]->clock_timer)(unit, peer);
  285. }
  286. /*
  287. * refclock_transmit - simulate the transmit procedure
  288. *
  289. * This routine implements the NTP transmit procedure for a reference
  290. * clock. This provides a mechanism to call the driver at the NTP poll
  291. * interval, as well as provides a reachability mechanism to detect a
  292. * broken radio or other madness.
  293. */
  294. void
  295. refclock_transmit(
  296. struct peer *peer /* peer structure pointer */
  297. )
  298. {
  299. u_char clktype;
  300. int unit;
  301. clktype = peer->refclktype;
  302. unit = peer->refclkunit;
  303. peer->sent++;
  304. get_systime(&peer->xmt);
  305. /*
  306. * This is a ripoff of the peer transmit routine, but
  307. * specialized for reference clocks. We do a little less
  308. * protocol here and call the driver-specific transmit routine.
  309. */
  310. if (peer->burst == 0) {
  311. u_char oreach;
  312. #ifdef DEBUG
  313. if (debug)
  314. printf("refclock_transmit: at %ld %s\n",
  315. current_time, stoa(&(peer->srcadr)));
  316. #endif
  317. /*
  318. * Update reachability and poll variables like the
  319. * network code.
  320. */
  321. oreach = peer->reach;
  322. peer->reach <<= 1;
  323. peer->outdate = current_time;
  324. if (!peer->reach) {
  325. if (oreach) {
  326. report_event(EVNT_UNREACH, peer);
  327. peer->timereachable = current_time;
  328. }
  329. } else {
  330. if (!(oreach & 0x07)) {
  331. clock_filter(peer, 0., 0., MAXDISPERSE);
  332. clock_select();
  333. }
  334. if (peer->flags & FLAG_BURST)
  335. peer->burst = NSTAGE;
  336. }
  337. } else {
  338. peer->burst--;
  339. }
  340. if (refclock_conf[clktype]->clock_poll != noentry)
  341. (refclock_conf[clktype]->clock_poll)(unit, peer);
  342. poll_update(peer, peer->hpoll);
  343. }
  344. /*
  345. * Compare two doubles - used with qsort()
  346. */
  347. #ifdef QSORT_USES_VOID_P
  348. static int
  349. refclock_cmpl_fp(
  350. const void *p1,
  351. const void *p2
  352. )
  353. {
  354. const double *dp1 = (const double *)p1;
  355. const double *dp2 = (const double *)p2;
  356. if (*dp1 < *dp2)
  357. return (-1);
  358. if (*dp1 > *dp2)
  359. return (1);
  360. return (0);
  361. }
  362. #else
  363. static int
  364. refclock_cmpl_fp(
  365. const double *dp1,
  366. const double *dp2
  367. )
  368. {
  369. if (*dp1 < *dp2)
  370. return (-1);
  371. if (*dp1 > *dp2)
  372. return (1);
  373. return (0);
  374. }
  375. #endif /* QSORT_USES_VOID_P */
  376. /*
  377. * refclock_process_offset - update median filter
  378. *
  379. * This routine uses the given offset and timestamps to construct a new
  380. * entry in the median filter circular buffer. Samples that overflow the
  381. * filter are quietly discarded.
  382. */
  383. void
  384. refclock_process_offset(
  385. struct refclockproc *pp, /* refclock structure pointer */
  386. l_fp lasttim, /* last timecode timestamp */
  387. l_fp lastrec, /* last receive timestamp */
  388. double fudge
  389. )
  390. {
  391. l_fp lftemp;
  392. double doffset;
  393. pp->lastrec = lastrec;
  394. lftemp = lasttim;
  395. L_SUB(&lftemp, &lastrec);
  396. LFPTOD(&lftemp, doffset);
  397. SAMPLE(doffset + fudge);
  398. }
  399. /*
  400. * refclock_process - process a sample from the clock
  401. *
  402. * This routine converts the timecode in the form days, hours, minutes,
  403. * seconds and milliseconds/microseconds to internal timestamp format,
  404. * then constructs a new entry in the median filter circular buffer.
  405. * Return success (1) if the data are correct and consistent with the
  406. * converntional calendar.
  407. *
  408. * Important for PPS users: Normally, the pp->lastrec is set to the
  409. * system time when the on-time character is received and the pp->year,
  410. * ..., pp->second decoded and the seconds fraction pp->nsec in
  411. * nanoseconds). When a PPS offset is available, pp->nsec is forced to
  412. * zero and the fraction for pp->lastrec is set to the PPS offset.
  413. */
  414. int
  415. refclock_process(
  416. struct refclockproc *pp /* refclock structure pointer */
  417. )
  418. {
  419. l_fp offset, ltemp;
  420. /*
  421. * Compute the timecode timestamp from the days, hours, minutes,
  422. * seconds and milliseconds/microseconds of the timecode. Use
  423. * clocktime() for the aggregate seconds and the msec/usec for
  424. * the fraction, when present. Note that this code relies on the
  425. * filesystem time for the years and does not use the years of
  426. * the timecode.
  427. */
  428. if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT,
  429. pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui))
  430. return (0);
  431. offset.l_uf = 0;
  432. DTOLFP(pp->nsec / 1e9, &ltemp);
  433. L_ADD(&offset, &ltemp);
  434. refclock_process_offset(pp, offset, pp->lastrec,
  435. pp->fudgetime1);
  436. return (1);
  437. }
  438. /*
  439. * refclock_sample - process a pile of samples from the clock
  440. *
  441. * This routine implements a recursive median filter to suppress spikes
  442. * in the data, as well as determine a performance statistic. It
  443. * calculates the mean offset and RMS jitter. A time adjustment
  444. * fudgetime1 can be added to the final offset to compensate for various
  445. * systematic errors. The routine returns the number of samples
  446. * processed, which could be zero.
  447. */
  448. static int
  449. refclock_sample(
  450. struct refclockproc *pp /* refclock structure pointer */
  451. )
  452. {
  453. int i, j, k, m, n;
  454. double off[MAXSTAGE];
  455. double offset;
  456. /*
  457. * Copy the raw offsets and sort into ascending order. Don't do
  458. * anything if the buffer is empty.
  459. */
  460. n = 0;
  461. while (pp->codeproc != pp->coderecv) {
  462. pp->codeproc = (pp->codeproc + 1) % MAXSTAGE;
  463. off[n] = pp->filter[pp->codeproc];
  464. n++;
  465. }
  466. if (n == 0)
  467. return (0);
  468. if (n > 1)
  469. qsort(
  470. #ifdef QSORT_USES_VOID_P
  471. (void *)
  472. #else
  473. (char *)
  474. #endif
  475. off, (size_t)n, sizeof(double), refclock_cmpl_fp);
  476. /*
  477. * Reject the furthest from the median of the samples until
  478. * approximately 60 percent of the samples remain.
  479. */
  480. i = 0; j = n;
  481. m = n - (n * 4) / 10;
  482. while ((j - i) > m) {
  483. offset = off[(j + i) / 2];
  484. if (off[j - 1] - offset < offset - off[i])
  485. i++; /* reject low end */
  486. else
  487. j--; /* reject high end */
  488. }
  489. /*
  490. * Determine the offset and jitter.
  491. */
  492. pp->offset = 0;
  493. pp->jitter = 0;
  494. for (k = i; k < j; k++) {
  495. pp->offset += off[k];
  496. if (k > i)
  497. pp->jitter += SQUARE(off[k] - off[k - 1]);
  498. }
  499. pp->offset /= m;
  500. pp->jitter = max(SQRT(pp->jitter / m), LOGTOD(sys_precision));
  501. #ifdef DEBUG
  502. if (debug)
  503. printf(
  504. "refclock_sample: n %d offset %.6f disp %.6f jitter %.6f\n",
  505. n, pp->offset, pp->disp, pp->jitter);
  506. #endif
  507. return (n);
  508. }
  509. /*
  510. * refclock_receive - simulate the receive and packet procedures
  511. *
  512. * This routine simulates the NTP receive and packet procedures for a
  513. * reference clock. This provides a mechanism in which the ordinary NTP
  514. * filter, selection and combining algorithms can be used to suppress
  515. * misbehaving radios and to mitigate between them when more than one is
  516. * available for backup.
  517. */
  518. void
  519. refclock_receive(
  520. struct peer *peer /* peer structure pointer */
  521. )
  522. {
  523. struct refclockproc *pp;
  524. #ifdef DEBUG
  525. if (debug)
  526. printf("refclock_receive: at %lu %s\n",
  527. current_time, stoa(&peer->srcadr));
  528. #endif
  529. /*
  530. * Do a little sanity dance and update the peer structure. Groom
  531. * the median filter samples and give the data to the clock
  532. * filter.
  533. */
  534. pp = peer->procptr;
  535. peer->leap = pp->leap;
  536. if (peer->leap == LEAP_NOTINSYNC)
  537. return;
  538. peer->received++;
  539. peer->timereceived = current_time;
  540. if (!peer->reach) {
  541. report_event(EVNT_REACH, peer);
  542. peer->timereachable = current_time;
  543. }
  544. peer->reach |= 1;
  545. peer->reftime = pp->lastref;
  546. peer->org = pp->lastrec;
  547. peer->rootdispersion = pp->disp;
  548. get_systime(&peer->rec);
  549. if (!refclock_sample(pp))
  550. return;
  551. clock_filter(peer, pp->offset, 0., pp->jitter);
  552. record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),
  553. peer->offset, peer->delay, clock_phi * (current_time -
  554. peer->epoch), peer->jitter);
  555. if (cal_enable && last_offset < MINDISPERSE) {
  556. #ifdef KERNEL_PLL
  557. if (peer != sys_peer || pll_status & STA_PPSTIME)
  558. #else
  559. if (peer != sys_peer)
  560. #endif /* KERNEL_PLL */
  561. pp->fudgetime1 -= pp->offset * FUDGEFAC;
  562. else
  563. pp->fudgetime1 -= pp->fudgetime1 * FUDGEFAC;
  564. }
  565. }
  566. /*
  567. * refclock_gtlin - groom next input line and extract timestamp
  568. *
  569. * This routine processes the timecode received from the clock and
  570. * strips the parity bit and control characters. It returns the number
  571. * of characters in the line followed by a NULL character ('\0'), which
  572. * is not included in the count. In case of an empty line, the previous
  573. * line is preserved.
  574. */
  575. int
  576. refclock_gtlin(
  577. struct recvbuf *rbufp, /* receive buffer pointer */
  578. char *lineptr, /* current line pointer */
  579. int bmax, /* remaining characters in line */
  580. l_fp *tsptr /* pointer to timestamp returned */
  581. )
  582. {
  583. char s[BMAX];
  584. char *dpt, *dpend, *dp;
  585. dpt = s;
  586. dpend = s + refclock_gtraw(rbufp, s, BMAX - 1, tsptr);
  587. if (dpend - dpt > bmax - 1)
  588. dpend = dpt + bmax - 1;
  589. for (dp = lineptr; dpt < dpend; dpt++) {
  590. char c;
  591. c = *dpt & 0x7f;
  592. if (c >= 0x20 && c < 0x7f)
  593. *dp++ = c;
  594. }
  595. if (dp == lineptr)
  596. return (0);
  597. *dp = '\0';
  598. return (dp - lineptr);
  599. }
  600. /*
  601. * refclock_gtraw - get next line/chunk of data
  602. *
  603. * This routine returns the raw data received from the clock in both
  604. * canonical or raw modes. The terminal interface routines map CR to LF.
  605. * In canonical mode this results in two lines, one containing data
  606. * followed by LF and another containing only LF. In raw mode the
  607. * interface routines can deliver arbitraty chunks of data from one
  608. * character to a maximum specified by the calling routine. In either
  609. * mode the routine returns the number of characters in the line
  610. * followed by a NULL character ('\0'), which is not included in the
  611. * count.
  612. *
  613. * If a timestamp is present in the timecode, as produced by the tty_clk
  614. * STREAMS module, it returns that as the timestamp; otherwise, it
  615. * returns the buffer timestamp.
  616. */
  617. int
  618. refclock_gtraw(
  619. struct recvbuf *rbufp, /* receive buffer pointer */
  620. char *lineptr, /* current line pointer */
  621. int bmax, /* remaining characters in line */
  622. l_fp *tsptr /* pointer to timestamp returned */
  623. )
  624. {
  625. char *dpt, *dpend, *dp;
  626. l_fp trtmp, tstmp;
  627. int i;
  628. /*
  629. * Check for the presence of a timestamp left by the tty_clock
  630. * module and, if present, use that instead of the buffer
  631. * timestamp captured by the I/O routines. We recognize a
  632. * timestamp by noting its value is earlier than the buffer
  633. * timestamp, but not more than one second earlier.
  634. */
  635. dpt = (char *)rbufp->recv_buffer;
  636. dpend = dpt + rbufp->recv_length;
  637. trtmp = rbufp->recv_time;
  638. if (dpend >= dpt + 8) {
  639. if (buftvtots(dpend - 8, &tstmp)) {
  640. L_SUB(&trtmp, &tstmp);
  641. if (trtmp.l_ui == 0) {
  642. #ifdef DEBUG
  643. if (debug > 1) {
  644. printf(
  645. "refclock_gtlin: fd %d ldisc %s",
  646. rbufp->fd, lfptoa(&trtmp,
  647. 6));
  648. get_systime(&trtmp);
  649. L_SUB(&trtmp, &tstmp);
  650. printf(" sigio %s\n",
  651. lfptoa(&trtmp, 6));
  652. }
  653. #endif
  654. dpend -= 8;
  655. trtmp = tstmp;
  656. } else
  657. trtmp = rbufp->recv_time;
  658. }
  659. }
  660. /*
  661. * Copy the raw buffer to the user string. The string is padded
  662. * with a NULL, which is not included in the character count.
  663. */
  664. if (dpend - dpt > bmax - 1)
  665. dpend = dpt + bmax - 1;
  666. for (dp = lineptr; dpt < dpend; dpt++)
  667. *dp++ = *dpt;
  668. *dp = '\0';
  669. i = dp - lineptr;
  670. #ifdef DEBUG
  671. if (debug > 1)
  672. printf("refclock_gtraw: fd %d time %s timecode %d %s\n",
  673. rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr);
  674. #endif
  675. *tsptr = trtmp;
  676. return (i);
  677. }
  678. /*
  679. * The following code does not apply to WINNT & VMS ...
  680. */
  681. #if !defined SYS_VXWORKS && !defined SYS_WINNT
  682. #if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)
  683. /*
  684. * refclock_open - open serial port for reference clock
  685. *
  686. * This routine opens a serial port for I/O and sets default options. It
  687. * returns the file descriptor if success and zero if failure.
  688. */
  689. int
  690. refclock_open(
  691. char *dev, /* device name pointer */
  692. u_int speed, /* serial port speed (code) */
  693. u_int lflags /* line discipline flags */
  694. )
  695. {
  696. int fd;
  697. int omode;
  698. /*
  699. * Open serial port and set default options
  700. */
  701. omode = O_RDWR;
  702. #ifdef O_NONBLOCK
  703. omode |= O_NONBLOCK;
  704. #endif
  705. #ifdef O_NOCTTY
  706. omode |= O_NOCTTY;
  707. #endif
  708. fd = open(dev, omode, 0777);
  709. if (fd < 0) {
  710. msyslog(LOG_ERR, "refclock_open %s: %m", dev);
  711. return (0);
  712. }
  713. if (!refclock_setup(fd, speed, lflags)) {
  714. close(fd);
  715. return (0);
  716. }
  717. if (!refclock_ioctl(fd, lflags)) {
  718. close(fd);
  719. return (0);
  720. }
  721. return (fd);
  722. }
  723. /*
  724. * refclock_setup - initialize terminal interface structure
  725. */
  726. int
  727. refclock_setup(
  728. int fd, /* file descriptor */
  729. u_int speed, /* serial port speed (code) */
  730. u_int lflags /* line discipline flags */
  731. )
  732. {
  733. int i;
  734. TTY ttyb, *ttyp;
  735. #ifdef PPS
  736. fdpps = fd; /* ppsclock legacy */
  737. #endif /* PPS */
  738. /*
  739. * By default, the serial line port is initialized in canonical
  740. * (line-oriented) mode at specified line speed, 8 bits and no
  741. * parity. LF ends the line and CR is mapped to LF. The break,
  742. * erase and kill functions are disabled. There is a different
  743. * section for each terminal interface, as selected at compile
  744. * time. The flag bits can be used to set raw mode and echo.
  745. */
  746. ttyp = &ttyb;
  747. #ifdef HAVE_TERMIOS
  748. /*
  749. * POSIX serial line parameters (termios interface)
  750. */
  751. if (tcgetattr(fd, ttyp) < 0) {
  752. msyslog(LOG_ERR,
  753. "refclock_setup fd %d tcgetattr: %m", fd);
  754. return (0);
  755. }
  756. /*
  757. * Set canonical mode and local connection; set specified speed,
  758. * 8 bits and no parity; map CR to NL; ignore break.
  759. */
  760. if (speed) {
  761. u_int ltemp = 0;
  762. ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
  763. ttyp->c_oflag = 0;
  764. ttyp->c_cflag = CS8 | CLOCAL | CREAD;
  765. if (lflags & LDISC_7O1) {
  766. /* HP Z3801A needs 7-bit, odd parity */
  767. ttyp->c_cflag = CS7 | PARENB | PARODD | CLOCAL | CREAD;
  768. }
  769. cfsetispeed(&ttyb, speed);
  770. cfsetospeed(&ttyb, speed);
  771. for (i = 0; i < NCCS; ++i)
  772. ttyp->c_cc[i] = '\0';
  773. #if defined(TIOCMGET) && !defined(SCO5_CLOCK)
  774. /*
  775. * If we have modem control, check to see if modem leads
  776. * are active; if so, set remote connection. This is
  777. * necessary for the kernel pps mods to work.
  778. */
  779. if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
  780. msyslog(LOG_ERR,
  781. "refclock_setup fd %d TIOCMGET: %m", fd);
  782. #ifdef DEBUG
  783. if (debug)
  784. printf("refclock_setup fd %d modem status: 0x%x\n",
  785. fd, ltemp);
  786. #endif
  787. if (ltemp & TIOCM_DSR && lflags & LDISC_REMOTE)
  788. ttyp->c_cflag &= ~CLOCAL;
  789. #endif /* TIOCMGET */
  790. }
  791. /*
  792. * Set raw and echo modes. These can be changed on-fly.
  793. */
  794. ttyp->c_lflag = ICANON;
  795. if (lflags & LDISC_RAW) {
  796. ttyp->c_lflag = 0;
  797. ttyp->c_iflag = 0;
  798. ttyp->c_cc[VMIN] = 1;
  799. }
  800. if (lflags & LDISC_ECHO)
  801. ttyp->c_lflag |= ECHO;
  802. if (tcsetattr(fd, TCSANOW, ttyp) < 0) {
  803. msyslog(LOG_ERR,
  804. "refclock_setup fd %d TCSANOW: %m", fd);
  805. return (0);
  806. }
  807. #endif /* HAVE_TERMIOS */
  808. #ifdef HAVE_SYSV_TTYS
  809. /*
  810. * System V serial line parameters (termio interface)
  811. *
  812. */
  813. if (ioctl(fd, TCGETA, ttyp) < 0) {
  814. msyslog(LOG_ERR,
  815. "refclock_setup fd %d TCGETA: %m", fd);
  816. return (0);
  817. }
  818. /*
  819. * Set canonical mode and local connection; set specified speed,
  820. * 8 bits and no parity; map CR to NL; ignore break.
  821. */
  822. if (speed) {
  823. u_int ltemp = 0;
  824. ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
  825. ttyp->c_oflag = 0;
  826. ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD;
  827. for (i = 0; i < NCCS; ++i)
  828. ttyp->c_cc[i] = '\0';
  829. #if defined(TIOCMGET) && !defined(SCO5_CLOCK)
  830. /*
  831. * If we have modem control, check to see if modem leads
  832. * are active; if so, set remote connection. This is
  833. * necessary for the kernel pps mods to work.
  834. */
  835. if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
  836. msyslog(LOG_ERR,
  837. "refclock_setup fd %d TIOCMGET: %m", fd);
  838. #ifdef DEBUG
  839. if (debug)
  840. printf("refclock_setup fd %d modem status: %x\n",
  841. fd, ltemp);
  842. #endif
  843. if (ltemp & TIOCM_DSR)
  844. ttyp->c_cflag &= ~CLOCAL;
  845. #endif /* TIOCMGET */
  846. }
  847. /*
  848. * Set raw and echo modes. These can be changed on-fly.
  849. */
  850. ttyp->c_lflag = ICANON;
  851. if (lflags & LDISC_RAW) {
  852. ttyp->c_lflag = 0;
  853. ttyp->c_iflag = 0;
  854. ttyp->c_cc[VMIN] = 1;
  855. }
  856. if (ioctl(fd, TCSETA, ttyp) < 0) {
  857. msyslog(LOG_ERR,
  858. "refclock_setup fd %d TCSETA: %m", fd);
  859. return (0);
  860. }
  861. #endif /* HAVE_SYSV_TTYS */
  862. #ifdef HAVE_BSD_TTYS
  863. /*
  864. * 4.3bsd serial line parameters (sgttyb interface)
  865. */
  866. if (ioctl(fd, TIOCGETP, (char *)ttyp) < 0) {
  867. msyslog(LOG_ERR,
  868. "refclock_setup fd %d TIOCGETP: %m", fd);
  869. return (0);
  870. }
  871. if (speed)
  872. ttyp->sg_ispeed = ttyp->sg_ospeed = speed;
  873. ttyp->sg_flags = EVENP | ODDP | CRMOD;
  874. if (ioctl(fd, TIOCSETP, (char *)ttyp) < 0) {
  875. msyslog(LOG_ERR,
  876. "refclock_setup TIOCSETP: %m");
  877. return (0);
  878. }
  879. #endif /* HAVE_BSD_TTYS */
  880. return(1);
  881. }
  882. #endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */
  883. #endif /* SYS_VXWORKS SYS_WINNT */
  884. /*
  885. * refclock_ioctl - set serial port control functions
  886. *
  887. * This routine attempts to hide the internal, system-specific details
  888. * of serial ports. It can handle POSIX (termios), SYSV (termio) and BSD
  889. * (sgtty) interfaces with varying degrees of success. The routine sets
  890. * up optional features such as tty_clk. The routine returns 1 if
  891. * success and 0 if failure.
  892. */
  893. int
  894. refclock_ioctl(
  895. int fd, /* file descriptor */
  896. u_int lflags /* line discipline flags */
  897. )
  898. {
  899. /*
  900. * simply return 1 if no UNIX line discipline is supported
  901. */
  902. #if !defined SYS_VXWORKS && !defined SYS_WINNT
  903. #if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)
  904. #ifdef DEBUG
  905. if (debug)
  906. printf("refclock_ioctl: fd %d flags 0x%x\n", fd,
  907. lflags);
  908. #endif
  909. #ifdef TTYCLK
  910. /*
  911. * The TTYCLK option provides timestamping at the driver level.
  912. * It requires the tty_clk streams module and System V STREAMS
  913. * support. If not available, don't complain.
  914. */
  915. if (lflags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) {
  916. int rval = 0;
  917. if (ioctl(fd, I_PUSH, "clk") < 0) {
  918. msyslog(LOG_NOTICE,
  919. "refclock_ioctl fd %d I_PUSH: %m", fd);
  920. return (0);
  921. #ifdef CLK_SETSTR
  922. } else {
  923. char *str;
  924. if (lflags & LDISC_CLKPPS)
  925. str = "\377";
  926. else if (lflags & LDISC_ACTS)
  927. str = "*";
  928. else
  929. str = "\n";
  930. if (ioctl(fd, CLK_SETSTR, str) < 0) {
  931. msyslog(LOG_ERR,
  932. "refclock_ioctl fd %d CLK_SETSTR: %m", fd);
  933. return (0);
  934. }
  935. #endif /*CLK_SETSTR */
  936. }
  937. }
  938. #endif /* TTYCLK */
  939. #endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */
  940. #endif /* SYS_VXWORKS SYS_WINNT */
  941. return (1);
  942. }
  943. /*
  944. * refclock_control - set and/or return clock values
  945. *
  946. * This routine is used mainly for debugging. It returns designated
  947. * values from the interface structure that can be displayed using
  948. * ntpdc and the clockstat command. It can also be used to initialize
  949. * configuration variables, such as fudgetimes, fudgevalues, reference
  950. * ID and stratum.
  951. */
  952. void
  953. refclock_control(
  954. struct sockaddr_storage *srcadr,
  955. struct refclockstat *in,
  956. struct refclockstat *out
  957. )
  958. {
  959. struct peer *peer;
  960. struct refclockproc *pp;
  961. u_char clktype;
  962. int unit;
  963. /*
  964. * Check for valid address and running peer
  965. */
  966. if (srcadr->ss_family != AF_INET)
  967. return;
  968. if (!ISREFCLOCKADR(srcadr))
  969. return;
  970. clktype = (u_char)REFCLOCKTYPE(srcadr);
  971. unit = REFCLOCKUNIT(srcadr);
  972. if (clktype >= num_refclock_conf || unit >= MAXUNIT)
  973. return;
  974. peer = typeunit[clktype][unit];
  975. if (peer == NULL)
  976. return;
  977. if (peer->procptr == NULL)
  978. return;
  979. pp = peer->procptr;
  980. /*
  981. * Initialize requested data
  982. */
  983. if (in != 0) {
  984. if (in->haveflags & CLK_HAVETIME1)
  985. pp->fudgetime1 = in->fudgetime1;
  986. if (in->haveflags & CLK_HAVETIME2)
  987. pp->fudgetime2 = in->fudgetime2;
  988. if (in->haveflags & CLK_HAVEVAL1)
  989. peer->stratum = pp->stratum = (u_char)in->fudgeval1;
  990. if (in->haveflags & CLK_HAVEVAL2)
  991. peer->refid = pp->refid = in->fudgeval2;
  992. if (in->haveflags & CLK_HAVEFLAG1) {
  993. pp->sloppyclockflag &= ~CLK_FLAG1;
  994. pp->sloppyclockflag |= in->flags & CLK_FLAG1;
  995. }
  996. if (in->haveflags & CLK_HAVEFLAG2) {
  997. pp->sloppyclockflag &= ~CLK_FLAG2;
  998. pp->sloppyclockflag |= in->flags & CLK_FLAG2;
  999. }
  1000. if (in->haveflags & CLK_HAVEFLAG3) {
  1001. pp->sloppyclockflag &= ~CLK_FLAG3;
  1002. pp->sloppyclockflag |= in->flags & CLK_FLAG3;
  1003. }
  1004. if (in->haveflags & CLK_HAVEFLAG4) {
  1005. pp->sloppyclockflag &= ~CLK_FLAG4;
  1006. pp->sloppyclockflag |= in->flags & CLK_FLAG4;
  1007. }
  1008. }
  1009. /*
  1010. * Readback requested data
  1011. */
  1012. if (out != 0) {
  1013. out->haveflags = CLK_HAVETIME1 | CLK_HAVEVAL1 |
  1014. CLK_HAVEVAL2 | CLK_HAVEFLAG4;
  1015. out->fudgetime1 = pp->fudgetime1;
  1016. out->fudgetime2 = pp->fudgetime2;
  1017. out->fudgeval1 = pp->stratum;
  1018. out->fudgeval2 = pp->refid;
  1019. out->flags = (u_char) pp->sloppyclockflag;
  1020. out->timereset = current_time - pp->timestarted;
  1021. out->polls = pp->polls;
  1022. out->noresponse = pp->noreply;
  1023. out->badformat = pp->badformat;
  1024. out->baddata = pp->baddata;
  1025. out->lastevent = pp->lastevent;
  1026. out->currentstatus = pp->currentstatus;
  1027. out->type = pp->type;
  1028. out->clockdesc = pp->clockdesc;
  1029. out->lencode = pp->lencode;
  1030. out->p_lastcode = pp->a_lastcode;
  1031. }
  1032. /*
  1033. * Give the stuff to the clock
  1034. */
  1035. if (refclock_conf[clktype]->clock_control != noentry)
  1036. (refclock_conf[clktype]->clock_control)(unit, in, out, peer);
  1037. }
  1038. /*
  1039. * refclock_buginfo - return debugging info
  1040. *
  1041. * This routine is used mainly for debugging. It returns designated
  1042. * values from the interface structure that can be displayed using
  1043. * ntpdc and the clkbug command.
  1044. */
  1045. void
  1046. refclock_buginfo(
  1047. struct sockaddr_storage *srcadr, /* clock address */
  1048. struct refclockbug *bug /* output structure */
  1049. )
  1050. {
  1051. struct peer *peer;
  1052. struct refclockproc *pp;
  1053. u_char clktype;
  1054. int unit;
  1055. int i;
  1056. /*
  1057. * Check for valid address and peer structure
  1058. */
  1059. if (srcadr->ss_family != AF_INET)
  1060. return;
  1061. if (!ISREFCLOCKADR(srcadr))
  1062. return;
  1063. clktype = (u_char) REFCLOCKTYPE(srcadr);
  1064. unit = REFCLOCKUNIT(srcadr);
  1065. if (clktype >= num_refclock_conf || unit >= MAXUNIT)
  1066. return;
  1067. peer = typeunit[clktype][unit];
  1068. if (peer == NULL)
  1069. return;
  1070. pp = peer->procptr;
  1071. /*
  1072. * Copy structure values
  1073. */
  1074. bug->nvalues = 8;
  1075. bug->svalues = 0x0000003f;
  1076. bug->values[0] = pp->year;
  1077. bug->values[1] = pp->day;
  1078. bug->values[2] = pp->hour;
  1079. bug->values[3] = pp->minute;
  1080. bug->values[4] = pp->second;
  1081. bug->values[5] = pp->nsec;
  1082. bug->values[6] = pp->yearstart;
  1083. bug->values[7] = pp->coderecv;
  1084. bug->stimes = 0xfffffffc;
  1085. bug->times[0] = pp->lastref;
  1086. bug->times[1] = pp->lastrec;
  1087. for (i = 2; i < (int)bug->ntimes; i++)
  1088. DTOLFP(pp->filter[i - 2], &bug->times[i]);
  1089. /*
  1090. * Give the stuff to the clock
  1091. */
  1092. if (refclock_conf[clktype]->clock_buginfo != noentry)
  1093. (refclock_conf[clktype]->clock_buginfo)(unit, bug, peer);
  1094. }
  1095. #endif /* REFCLOCK */