xref: /freebsd/contrib/ntp/ntpd/ntp_refclock.c (revision 5129159789cc9d7bc514e4546b88e3427695002d)
1 /*
2  * ntp_refclock - processing support for reference clocks
3  */
4 #ifdef HAVE_CONFIG_H
5 # include <config.h>
6 #endif
7 
8 #include <stdio.h>
9 #include <sys/types.h>
10 #ifdef HAVE_SYS_IOCTL_H
11 # include <sys/ioctl.h>
12 #endif /* HAVE_SYS_IOCTL_H */
13 
14 #include "ntpd.h"
15 #include "ntp_io.h"
16 #include "ntp_unixtime.h"
17 #include "ntp_refclock.h"
18 #include "ntp_stdlib.h"
19 
20 #ifdef REFCLOCK
21 
22 #ifdef TTYCLK
23 # ifdef SCO5_CLOCK
24 #  include <sys/sio.h>
25 # else
26 #  include <sys/clkdefs.h>
27 # endif
28 #endif /* TTYCLK */
29 
30 #ifdef HAVE_PPSCLOCK_H
31 #include <sys/ppsclock.h>
32 #endif /* HAVE_PPSCLOCK_H */
33 
34 #ifdef HAVE_PPSAPI
35 #include <sys/timepps.h>
36 #endif /* HAVE_PPSAPI */
37 
38 /*
39  * Reference clock support is provided here by maintaining the fiction
40  * that the clock is actually a peer. As no packets are exchanged with a
41  * reference clock, however, we replace the transmit, receive and packet
42  * procedures with separate code to simulate them. Routines
43  * refclock_transmit() and refclock_receive() maintain the peer
44  * variables in a state analogous to an actual peer and pass reference
45  * clock data on through the filters. Routines refclock_peer() and
46  * refclock_unpeer() are called to initialize and terminate reference
47  * clock associations. A set of utility routines is included to open
48  * serial devices, process sample data, edit input lines to extract
49  * embedded timestamps and to peform various debugging functions.
50  *
51  * The main interface used by these routines is the refclockproc
52  * structure, which contains for most drivers the decimal equivalants of
53  * the year, day, month, hour, second and millisecond/microsecond
54  * decoded from the ASCII timecode. Additional information includes the
55  * receive timestamp, exception report, statistics tallies, etc. In
56  * addition, there may be a driver-specific unit structure used for
57  * local control of the device.
58  *
59  * The support routines are passed a pointer to the peer structure,
60  * which is used for all peer-specific processing and contains a pointer
61  * to the refclockproc structure, which in turn containes a pointer to
62  * the unit structure, if used. The peer structure is identified by an
63  * interface address in the dotted quad form 127.127.t.u, where t is the
64  * clock type and u the unit. Some legacy drivers derive the
65  * refclockproc structure pointer from the table typeunit[type][unit].
66  * This interface is strongly discouraged and may be abandoned in
67  * future.
68  *
69  * The routines include support for the 1-pps signal provided by some
70  * radios and connected via a level converted described in the gadget
71  * directory. The signal is captured using a serial port and one of
72  * three STREAMS modules described in the refclock_atom.c file. For the
73  * highest precision, the signal is captured using the carrier-detect
74  * line of a serial port and either the ppsclock or ppsapi streams
75  * module or some devilish ioctl() folks keep slipping in as a patch. Be
76  * advised ALL support for other than the duly standardized ppsapi
77  * interface will eventually be withdrawn.
78  */
79 #define MAXUNIT 	4	/* max units */
80 
81 #if defined(PPS) || defined(HAVE_PPSAPI)
82 int fdpps;			/* pps file descriptor */
83 #endif /* PPS HAVE_PPSAPI */
84 
85 #define FUDGEFAC	.1	/* fudge correction factor */
86 
87 /*
88  * Type/unit peer index. Used to find the peer structure for control and
89  * debugging. When all clock drivers have been converted to new style,
90  * this dissapears.
91  */
92 static struct peer *typeunit[REFCLK_MAX + 1][MAXUNIT];
93 
94 /*
95  * Forward declarations
96  */
97 #ifdef QSORT_USES_VOID_P
98 static int refclock_cmpl_fp P((const void *, const void *));
99 #else
100 static int refclock_cmpl_fp P((const double *, const double *));
101 #endif /* QSORT_USES_VOID_P */
102 static int refclock_sample P((struct refclockproc *));
103 
104 #ifdef HAVE_PPSAPI
105 extern int pps_assert;		/* capture edge 1:assert, 0:clear */
106 extern int pps_hardpps;		/* PPS kernel 1:on, 0:off */
107 #endif /* HAVE_PPSAPI */
108 
109 /*
110  * refclock_report - note the occurance of an event
111  *
112  * This routine presently just remembers the report and logs it, but
113  * does nothing heroic for the trap handler. It tries to be a good
114  * citizen and bothers the system log only if things change.
115  */
116 void
117 refclock_report(
118 	struct peer *peer,
119 	int code
120 	)
121 {
122 	struct refclockproc *pp;
123 
124 	if (!(pp = peer->procptr))
125 		return;
126 	if (code == CEVNT_BADREPLY)
127 		pp->badformat++;
128 	if (code == CEVNT_BADTIME)
129 		pp->baddata++;
130 	if (code == CEVNT_TIMEOUT)
131 		pp->noreply++;
132 	if (pp->currentstatus != code) {
133 		pp->currentstatus = code;
134 		pp->lastevent = code;
135 		if (code == CEVNT_FAULT)
136 			msyslog(LOG_ERR,
137 				"clock %s event '%s' (0x%02x)",
138 				refnumtoa(peer->srcadr.sin_addr.s_addr),
139 				ceventstr(code), code);
140 		else {
141 			NLOG(NLOG_CLOCKEVENT)
142 				msyslog(LOG_INFO,
143 				"clock %s event '%s' (0x%02x)",
144 				refnumtoa(peer->srcadr.sin_addr.s_addr),
145 				ceventstr(code), code);
146 		}
147 	}
148 #ifdef DEBUG
149 	if (debug)
150 		printf("clock %s event '%s' (0x%02x)\n",
151 			refnumtoa(peer->srcadr.sin_addr.s_addr),
152 			ceventstr(code), code);
153 #endif
154 }
155 
156 
157 /*
158  * init_refclock - initialize the reference clock drivers
159  *
160  * This routine calls each of the drivers in turn to initialize internal
161  * variables, if necessary. Most drivers have nothing to say at this
162  * point.
163  */
164 void
165 init_refclock(void)
166 {
167 	int i, j;
168 
169 	for (i = 0; i < (int)num_refclock_conf; i++) {
170 		if (refclock_conf[i]->clock_init != noentry)
171 			(refclock_conf[i]->clock_init)();
172 		for (j = 0; j < MAXUNIT; j++)
173 			typeunit[i][j] = 0;
174 	}
175 }
176 
177 
178 /*
179  * refclock_newpeer - initialize and start a reference clock
180  *
181  * This routine allocates and initializes the interface structure which
182  * supports a reference clock in the form of an ordinary NTP peer. A
183  * driver-specific support routine completes the initialization, if
184  * used. Default peer variables which identify the clock and establish
185  * its reference ID and stratum are set here. It returns one if success
186  * and zero if the clock address is invalid or already running,
187  * insufficient resources are available or the driver declares a bum
188  * rap.
189  */
190 int
191 refclock_newpeer(
192 	struct peer *peer	/* peer structure pointer */
193 	)
194 {
195 	struct refclockproc *pp;
196 	u_char clktype;
197 	int unit;
198 
199 	/*
200 	 * Check for valid clock address. If already running, shut it
201 	 * down first.
202 	 */
203 	if (!ISREFCLOCKADR(&peer->srcadr)) {
204 		msyslog(LOG_ERR,
205 			"refclock_newpeer: clock address %s invalid",
206 			ntoa(&peer->srcadr));
207 		return (0);
208 	}
209 	clktype = (u_char)REFCLOCKTYPE(&peer->srcadr);
210 	unit = REFCLOCKUNIT(&peer->srcadr);
211 	if (clktype >= num_refclock_conf || unit >= MAXUNIT ||
212 		refclock_conf[clktype]->clock_start == noentry) {
213 		msyslog(LOG_ERR,
214 			"refclock_newpeer: clock type %d invalid\n",
215 			clktype);
216 		return (0);
217 	}
218 	refclock_unpeer(peer);
219 
220 	/*
221 	 * Allocate and initialize interface structure
222 	 */
223 	if (!(pp = (struct refclockproc *)emalloc(sizeof(struct refclockproc))))
224 		return (0);
225 	memset((char *)pp, 0, sizeof(struct refclockproc));
226 	typeunit[clktype][unit] = peer;
227 	peer->procptr = pp;
228 
229 	/*
230 	 * Initialize structures
231 	 */
232 	peer->refclktype = clktype;
233 	peer->refclkunit = unit;
234 	peer->flags |= FLAG_REFCLOCK;
235 	peer->stratum = STRATUM_REFCLOCK;
236 	peer->refid = peer->srcadr.sin_addr.s_addr;
237 	peer->maxpoll = peer->minpoll;
238 
239 	pp->type = clktype;
240 	pp->timestarted = current_time;
241 
242 	/*
243 	 * If the interface has been set to any_interface, set it to the
244 	 * loopback address if we have one. This is so that peers which
245 	 * are unreachable are easy to see in the peer display.
246 	 */
247 	if (peer->dstadr == any_interface && loopback_interface != 0)
248 		peer->dstadr = loopback_interface;
249 
250 	/*
251 	 * Set peer.pmode based on the hmode. For appearances only.
252 	 */
253 	switch (peer->hmode) {
254 
255 		case MODE_ACTIVE:
256 		peer->pmode = MODE_PASSIVE;
257 		break;
258 
259 		default:
260 		peer->pmode = MODE_SERVER;
261 		break;
262 	}
263 
264 	/*
265 	 * Do driver dependent initialization. The above defaults
266 	 * can be wiggled, then finish up for consistency.
267 	 */
268 	if (!((refclock_conf[clktype]->clock_start)(unit, peer))) {
269 		free(pp);
270 		return (0);
271 	}
272 	peer->hpoll = peer->minpoll;
273 	peer->ppoll = peer->maxpoll;
274 	if (peer->stratum <= 1)
275 		peer->refid = pp->refid;
276 	else
277 		peer->refid = peer->srcadr.sin_addr.s_addr;
278 	return (1);
279 }
280 
281 
282 /*
283  * refclock_unpeer - shut down a clock
284  */
285 void
286 refclock_unpeer(
287 	struct peer *peer	/* peer structure pointer */
288 	)
289 {
290 	u_char clktype;
291 	int unit;
292 
293 	/*
294 	 * Wiggle the driver to release its resources, then give back
295 	 * the interface structure.
296 	 */
297 	if (!peer->procptr)
298 		return;
299 	clktype = peer->refclktype;
300 	unit = peer->refclkunit;
301 	if (refclock_conf[clktype]->clock_shutdown != noentry)
302 		(refclock_conf[clktype]->clock_shutdown)(unit, peer);
303 	free(peer->procptr);
304 	peer->procptr = 0;
305 }
306 
307 
308 /*
309  * refclock_transmit - simulate the transmit procedure
310  *
311  * This routine implements the NTP transmit procedure for a reference
312  * clock. This provides a mechanism to call the driver at the NTP poll
313  * interval, as well as provides a reachability mechanism to detect a
314  * broken radio or other madness.
315  */
316 void
317 refclock_transmit(
318 	struct peer *peer	/* peer structure pointer */
319 	)
320 {
321 	u_char clktype;
322 	int unit;
323 	int hpoll;
324 	u_long next;
325 
326 	clktype = peer->refclktype;
327 	unit = peer->refclkunit;
328 	peer->sent++;
329 
330 	/*
331 	 * This is a ripoff of the peer transmit routine, but
332 	 * specialized for reference clocks. We do a little less
333 	 * protocol here and call the driver-specific transmit routine.
334 	 */
335 	hpoll = peer->hpoll;
336 	next = peer->outdate;
337 	if (peer->burst == 0) {
338 		u_char oreach;
339 #ifdef DEBUG
340 		if (debug)
341 			printf("refclock_transmit: at %ld %s\n",
342 			    current_time, ntoa(&(peer->srcadr)));
343 #endif
344 
345 		/*
346 		 * Update reachability and poll variables like the
347 		 * network code.
348 		 */
349 		oreach = peer->reach;
350 		if (oreach & 0x01)
351 			peer->valid++;
352 		if (oreach & 0x80)
353 			peer->valid--;
354 				peer->reach <<= 1;
355 		if (peer->reach == 0) {
356 			if (oreach != 0) {
357 				report_event(EVNT_UNREACH, peer);
358 				peer->timereachable = current_time;
359 				peer_clear(peer);
360 			}
361 		} else {
362 			if ((oreach & 0x03) == 0) {
363 				clock_filter(peer, 0., 0., MAXDISPERSE);
364 				clock_select();
365 			}
366 			if (peer->valid <= 2) {
367 				hpoll--;
368 			} else if (peer->valid > NTP_SHIFT - 2)
369 				hpoll++;
370 			if (peer->flags & FLAG_BURST)
371 				peer->burst = NSTAGE;
372 		}
373 		next = current_time;
374 	}
375 	get_systime(&peer->xmt);
376 	if (refclock_conf[clktype]->clock_poll != noentry)
377 		(refclock_conf[clktype]->clock_poll)(unit, peer);
378 	peer->outdate = next;
379 	poll_update(peer, hpoll);
380 	if (peer->burst > 0)
381 		peer->burst--;
382 	poll_update(peer, hpoll);
383 }
384 
385 
386 /*
387  * Compare two doubles - used with qsort()
388  */
389 #ifdef QSORT_USES_VOID_P
390 static int
391 refclock_cmpl_fp(
392 	const void *p1,
393 	const void *p2
394 	)
395 {
396 	const double *dp1 = (const double *)p1;
397 	const double *dp2 = (const double *)p2;
398 
399 	if (*dp1 < *dp2)
400 		return (-1);
401 	if (*dp1 > *dp2)
402 		return (1);
403 	return (0);
404 }
405 #else
406 static int
407 refclock_cmpl_fp(
408 	const double *dp1,
409 	const double *dp2
410 	)
411 {
412 	if (*dp1 < *dp2)
413 		return (-1);
414 	if (*dp1 > *dp2)
415 		return (1);
416 	return (0);
417 }
418 #endif /* QSORT_USES_VOID_P */
419 
420 
421 /*
422  * refclock_process_offset - update median filter
423  *
424  * This routine uses the given offset and timestamps to construct a new entry in the median filter circular buffer. Samples that overflow the filter are quietly discarded.
425  */
426 void
427 refclock_process_offset(
428 	struct refclockproc *pp,
429 	l_fp offset,
430 	l_fp lastrec,
431 	double fudge
432 	)
433 {
434 	double doffset;
435 
436 	pp->lastref = offset;
437 	pp->lastrec = lastrec;
438 	pp->variance = 0;
439 	L_SUB(&offset, &lastrec);
440 	LFPTOD(&offset, doffset);
441 	SAMPLE(doffset + fudge);
442 }
443 
444 /*
445  * refclock_process - process a sample from the clock
446  *
447  * This routine converts the timecode in the form days, hours, minutes,
448  * seconds and milliseconds/microseconds to internal timestamp format,
449  * then constructs a new entry in the median filter circular buffer.
450  * Return success (1) if the data are correct and consistent with the
451  * converntional calendar.
452 */
453 int
454 refclock_process(
455 	struct refclockproc *pp
456 	)
457 {
458 	l_fp offset;
459 
460 	/*
461 	 * Compute the timecode timestamp from the days, hours, minutes,
462 	 * seconds and milliseconds/microseconds of the timecode. Use
463 	 * clocktime() for the aggregate seconds and the msec/usec for
464 	 * the fraction, when present. Note that this code relies on the
465 	 * filesystem time for the years and does not use the years of
466 	 * the timecode.
467 	 */
468 	if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT,
469 		pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui))
470 		return (0);
471 	if (pp->usec) {
472 		TVUTOTSF(pp->usec, offset.l_uf);
473 	} else {
474 		MSUTOTSF(pp->msec, offset.l_uf);
475 	}
476 	refclock_process_offset(pp, offset, pp->lastrec,
477 	    pp->fudgetime1);
478 	return (1);
479 }
480 
481 /*
482  * refclock_sample - process a pile of samples from the clock
483  *
484  * This routine implements a recursive median filter to suppress spikes
485  * in the data, as well as determine a performance statistic. It
486  * calculates the mean offset and mean-square variance. A time
487  * adjustment fudgetime1 can be added to the final offset to compensate
488  * for various systematic errors. The routine returns the number of
489  * samples processed, which could be 0.
490  */
491 static int
492 refclock_sample(
493 	struct refclockproc *pp
494 	)
495 {
496 	int i, j, k, n;
497 	double offset, disp;
498 	double off[MAXSTAGE];
499 
500 	/*
501 	 * Copy the raw offsets and sort into ascending order. Don't do
502 	 * anything if the buffer is empty.
503 	 */
504 	if (pp->codeproc == pp->coderecv)
505 		return (0);
506 	n = 0;
507 	while (pp->codeproc != pp->coderecv)
508 		off[n++] = pp->filter[pp->codeproc++ % MAXSTAGE];
509 	if (n > 1)
510 		qsort((char *)off, n, sizeof(double), refclock_cmpl_fp);
511 
512 	/*
513 	 * Reject the furthest from the median of the samples until
514 	 * approximately 60 percent of the samples remain.
515 	 */
516 	i = 0; j = n;
517 	k = n - (n * 2) / NSTAGE;
518 	while ((j - i) > k) {
519 		offset = off[(j + i) / 2];
520 		if (off[j - 1] - offset < offset - off[i])
521 			i++;	/* reject low end */
522 		else
523 			j--;	/* reject high end */
524 	}
525 
526 	/*
527 	 * Determine the offset and variance.
528 	 */
529 	offset = disp = 0;
530 	for (; i < j; i++) {
531 		offset += off[i];
532 		disp += SQUARE(off[i]);
533 	}
534 	offset /= k;
535 	pp->offset = offset;
536 	pp->variance += disp / k - SQUARE(offset);
537 #ifdef DEBUG
538 	if (debug)
539 		printf(
540 		    "refclock_sample: n %d offset %.6f disp %.6f std %.6f\n",
541 		    n, pp->offset, pp->disp, SQRT(pp->variance));
542 #endif
543 	return (n);
544 }
545 
546 
547 /*
548  * refclock_receive - simulate the receive and packet procedures
549  *
550  * This routine simulates the NTP receive and packet procedures for a
551  * reference clock. This provides a mechanism in which the ordinary NTP
552  * filter, selection and combining algorithms can be used to suppress
553  * misbehaving radios and to mitigate between them when more than one is
554  * available for backup.
555  */
556 void
557 refclock_receive(
558 	struct peer *peer	/* peer structure pointer */
559 	)
560 {
561 	struct refclockproc *pp;
562 
563 #ifdef DEBUG
564 	if (debug)
565 		printf("refclock_receive: at %lu %s\n",
566 		    current_time, ntoa(&peer->srcadr));
567 #endif
568 
569 	/*
570 	 * Do a little sanity dance and update the peer structure. Groom
571 	 * the median filter samples and give the data to the clock
572 	 * filter.
573 	 */
574 	peer->received++;
575 	pp = peer->procptr;
576 	peer->processed++;
577 	peer->timereceived = current_time;
578 	peer->leap = pp->leap;
579 	if (peer->leap == LEAP_NOTINSYNC) {
580 		refclock_report(peer, CEVNT_FAULT);
581 		return;
582 	}
583 	if (peer->reach == 0)
584 		report_event(EVNT_REACH, peer);
585 	peer->reach |= 1;
586 	peer->reftime = peer->org = pp->lastrec;
587 	peer->rootdispersion = pp->disp + SQRT(pp->variance);
588 	get_systime(&peer->rec);
589 	if (!refclock_sample(pp))
590 		return;
591 	clock_filter(peer, pp->offset, 0., 0.);
592 	clock_select();
593 	record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),
594 	    peer->offset, peer->delay, CLOCK_PHI * (current_time -
595 	    peer->epoch), SQRT(peer->variance));
596 	if (pps_control && pp->sloppyclockflag & CLK_FLAG1)
597 		pp->fudgetime1 -= pp->offset * FUDGEFAC;
598 }
599 
600 /*
601  * refclock_gtlin - groom next input line and extract timestamp
602  *
603  * This routine processes the timecode received from the clock and
604  * removes the parity bit and control characters. If a timestamp is
605  * present in the timecode, as produced by the tty_clk STREAMS module,
606  * it returns that as the timestamp; otherwise, it returns the buffer
607  *  timestamp. The routine return code is the number of characters in
608  * the line.
609  */
610 int
611 refclock_gtlin(
612 	struct recvbuf *rbufp,	/* receive buffer pointer */
613 	char *lineptr,		/* current line pointer */
614 	int bmax,		/* remaining characters in line */
615 	l_fp *tsptr 	/* pointer to timestamp returned */
616 	)
617 {
618 	char *dpt, *dpend, *dp;
619 	int i;
620 	l_fp trtmp, tstmp;
621 	char c;
622 #ifdef TIOCDCDTIMESTAMP
623 	struct timeval dcd_time;
624 #endif /* TIOCDCDTIMESTAMP */
625 #ifdef HAVE_PPSAPI
626 	pps_info_t pi;
627 	struct timespec timeout, *tsp;
628 	double a;
629 #endif /* HAVE_PPSAPI */
630 
631 	/*
632 	 * Check for the presence of a timestamp left by the tty_clock
633 	 * module and, if present, use that instead of the buffer
634 	 * timestamp captured by the I/O routines. We recognize a
635 	 * timestamp by noting its value is earlier than the buffer
636 	 * timestamp, but not more than one second earlier.
637 	 */
638 	dpt = (char *)&rbufp->recv_space;
639 	dpend = dpt + rbufp->recv_length;
640 	trtmp = rbufp->recv_time;
641 
642 #ifdef HAVE_PPSAPI
643 	timeout.tv_sec = 0;
644 	timeout.tv_nsec = 0;
645 	if ((rbufp->fd == fdpps) &&
646 	    (time_pps_fetch(fdpps, PPS_TSFMT_TSPEC, &pi, &timeout) >= 0)) {
647 		if(pps_assert)
648 			tsp = &pi.assert_timestamp;
649 		else
650 			tsp = &pi.clear_timestamp;
651 		a = tsp->tv_nsec;
652 		a /= 1e9;
653 		tstmp.l_uf =  a * 4294967296.0;
654 		tstmp.l_ui = tsp->tv_sec;
655 		tstmp.l_ui += JAN_1970;
656 		L_SUB(&trtmp, &tstmp);
657 		if (trtmp.l_ui == 0) {
658 #ifdef DEBUG
659 			if (debug > 1) {
660 				printf(
661 				    "refclock_gtlin: fd %d time_pps_fetch %s",
662 				    fdpps, lfptoa(&tstmp, 6));
663 				printf(" sigio %s\n", lfptoa(&trtmp, 6));
664 			}
665 #endif
666 			trtmp = tstmp;
667 			goto gotit;
668 		} else
669 			trtmp = rbufp->recv_time;
670 	}
671 #endif /* HAVE_PPSAPI */
672 #ifdef TIOCDCDTIMESTAMP
673 	if(ioctl(rbufp->fd, TIOCDCDTIMESTAMP, &dcd_time) != -1) {
674 		TVTOTS(&dcd_time, &tstmp);
675 		tstmp.l_ui += JAN_1970;
676 		L_SUB(&trtmp, &tstmp);
677 		if (trtmp.l_ui == 0) {
678 #ifdef DEBUG
679 			if (debug > 1) {
680 				printf(
681 				    "refclock_gtlin: fd %d DCDTIMESTAMP %s",
682 				    rbufp->fd, lfptoa(&tstmp, 6));
683 				printf(" sigio %s\n", lfptoa(&trtmp, 6));
684 			}
685 #endif
686 			trtmp = tstmp;
687 			goto gotit;
688 		} else
689 			trtmp = rbufp->recv_time;
690 	}
691 	else
692 	/* XXX fallback to old method if kernel refuses TIOCDCDTIMESTAMP */
693 #endif  /* TIOCDCDTIMESTAMP */
694 	if (dpend >= dpt + 8) {
695 		if (buftvtots(dpend - 8, &tstmp)) {
696 			L_SUB(&trtmp, &tstmp);
697 			if (trtmp.l_ui == 0) {
698 #ifdef DEBUG
699 				if (debug > 1) {
700 					printf(
701 					    "refclock_gtlin: fd %d ldisc %s",
702 					    rbufp->fd, lfptoa(&trtmp, 6));
703 					get_systime(&trtmp);
704 					L_SUB(&trtmp, &tstmp);
705 					printf(" sigio %s\n", lfptoa(&trtmp, 6));
706 				}
707 #endif
708 				dpend -= 8;
709 				trtmp = tstmp;
710 			} else
711 				trtmp = rbufp->recv_time;
712 		}
713 	}
714 
715 #if defined(HAVE_PPSAPI) || defined(TIOCDCDTIMESTAMP)
716 gotit:
717 #endif
718 	/*
719 	 * Edit timecode to remove control chars. Don't monkey with the
720 	 * line buffer if the input buffer contains no ASCII printing
721 	 * characters.
722 	 */
723 	if (dpend - dpt > bmax - 1)
724 		dpend = dpt + bmax - 1;
725 	for (dp = lineptr; dpt < dpend; dpt++) {
726 		c = *dpt & 0x7f;
727 		if (c >= ' ')
728 			*dp++ = c;
729 	}
730 	i = dp - lineptr;
731 	if (i > 0)
732 		*dp = '\0';
733 #ifdef DEBUG
734 	if (debug > 1 && i > 0)
735 		printf("refclock_gtlin: fd %d time %s timecode %d %s\n",
736 		    rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr);
737 #endif
738 	*tsptr = trtmp;
739 	return (i);
740 }
741 
742 /*
743  * The following code does not apply to WINNT & VMS ...
744  */
745 #if !defined SYS_VXWORKS && !defined SYS_WINNT
746 #if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)
747 
748 /*
749  * refclock_open - open serial port for reference clock
750  *
751  * This routine opens a serial port for I/O and sets default options. It
752  * returns the file descriptor if success and zero if failure.
753  */
754 int
755 refclock_open(
756 	char *dev,		/* device name pointer */
757 	int speed,		/* serial port speed (code) */
758 	int flags		/* line discipline flags */
759 	)
760 {
761 	int fd, i;
762 #ifdef HAVE_TERMIOS
763 	struct termios ttyb, *ttyp;
764 #endif /* HAVE_TERMIOS */
765 #ifdef HAVE_SYSV_TTYS
766 	struct termio ttyb, *ttyp;
767 #endif /* HAVE_SYSV_TTYS */
768 #ifdef HAVE_BSD_TTYS
769 	struct sgttyb ttyb, *ttyp;
770 #endif /* HAVE_BSD_TTYS */
771 #ifdef TIOCMGET
772 	u_long ltemp;
773 #endif /* TIOCMGET */
774 
775 	/*
776 	 * Open serial port and set default options
777 	 */
778 #ifdef O_NONBLOCK
779 	fd = open(dev, O_RDWR | O_NONBLOCK, 0777);
780 #else
781 	fd = open(dev, O_RDWR, 0777);
782 #endif /* O_NONBLOCK */
783 	if (fd == -1) {
784 		msyslog(LOG_ERR, "refclock_open: %s: %m", dev);
785 		return (0);
786 	}
787 
788 	/*
789 	 * The following sections initialize the serial line port in
790 	 * canonical (line-oriented) mode and set the specified line
791 	 * speed, 8 bits and no parity. The modem control, break, erase
792 	 * and kill functions are normally disabled. There is a
793 	 * different section for each terminal interface, as selected at
794 	 * compile time.
795 	 */
796 	ttyp = &ttyb;
797 
798 #ifdef HAVE_TERMIOS
799 	/*
800 	 * POSIX serial line parameters (termios interface)
801 	 */
802 	if (tcgetattr(fd, ttyp) < 0) {
803 		msyslog(LOG_ERR,
804 			"refclock_open: fd %d tcgetattr: %m", fd);
805 		return (0);
806 	}
807 
808 	/*
809 	 * Set canonical mode and local connection; set specified speed,
810 	 * 8 bits and no parity; map CR to NL; ignore break.
811 	 */
812 	ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
813 	ttyp->c_oflag = 0;
814 	ttyp->c_cflag = CS8 | CLOCAL | CREAD;
815 	(void)cfsetispeed(&ttyb, (u_int)speed);
816 	(void)cfsetospeed(&ttyb, (u_int)speed);
817 	ttyp->c_lflag = ICANON;
818 	for (i = 0; i < NCCS; ++i)
819 	{
820 		ttyp->c_cc[i] = '\0';
821 	}
822 
823 	/*
824 	 * Some special cases
825 	 */
826 	if (flags & LDISC_RAW) {
827 		ttyp->c_iflag = 0;
828 		ttyp->c_lflag = 0;
829 		ttyp->c_cc[VMIN] = 1;
830 	}
831 #if defined(TIOCMGET) && !defined(SCO5_CLOCK)
832 	/*
833 	 * If we have modem control, check to see if modem leads are
834 	 * active; if so, set remote connection. This is necessary for
835 	 * the kernel pps mods to work.
836 	 */
837 	ltemp = 0;
838 	if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
839 		msyslog(LOG_ERR,
840 			"refclock_open: fd %d TIOCMGET failed: %m", fd);
841 #ifdef DEBUG
842 	if (debug)
843 		printf("refclock_open: fd %d modem status 0x%lx\n",
844 		    fd, ltemp);
845 #endif
846 	if (ltemp & TIOCM_DSR)
847 		ttyp->c_cflag &= ~CLOCAL;
848 #endif /* TIOCMGET */
849 	if (tcsetattr(fd, TCSANOW, ttyp) < 0) {
850 		msyslog(LOG_ERR,
851 		    "refclock_open: fd %d TCSANOW failed: %m", fd);
852 		return (0);
853 	}
854 	if (tcflush(fd, TCIOFLUSH) < 0) {
855 		msyslog(LOG_ERR,
856 		    "refclock_open: fd %d TCIOFLUSH failed: %m", fd);
857 		return (0);
858 	}
859 #endif /* HAVE_TERMIOS */
860 
861 #ifdef HAVE_SYSV_TTYS
862 
863 	/*
864 	 * System V serial line parameters (termio interface)
865 	 *
866 	 */
867 	if (ioctl(fd, TCGETA, ttyp) < 0) {
868 		msyslog(LOG_ERR,
869 		    "refclock_open: fd %d TCGETA failed: %m", fd);
870 		return (0);
871 	}
872 
873 	/*
874 	 * Set canonical mode and local connection; set specified speed,
875 	 * 8 bits and no parity; map CR to NL; ignore break.
876 	 */
877 	ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
878 	ttyp->c_oflag = 0;
879 	ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD;
880 	ttyp->c_lflag = ICANON;
881 	ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
882 
883 	/*
884 	 * Some special cases
885 	 */
886 	if (flags & LDISC_RAW) {
887 		ttyp->c_iflag = 0;
888 		ttyp->c_lflag = 0;
889 	}
890 #ifdef TIOCMGET
891 	/*
892 	 * If we have modem control, check to see if modem leads are
893 	 * active; if so, set remote connection. This is necessary for
894 	 * the kernel pps mods to work.
895 	 */
896 	ltemp = 0;
897 	if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
898 		msyslog(LOG_ERR,
899 		    "refclock_open: fd %d TIOCMGET failed: %m", fd);
900 #ifdef DEBUG
901 	if (debug)
902 		printf("refclock_open: fd %d modem status %lx\n",
903 		    fd, ltemp);
904 #endif
905 	if (ltemp & TIOCM_DSR)
906 		ttyp->c_cflag &= ~CLOCAL;
907 #endif /* TIOCMGET */
908 	if (ioctl(fd, TCSETA, ttyp) < 0) {
909 		msyslog(LOG_ERR,
910 		    "refclock_open: fd %d TCSETA failed: %m", fd);
911 		return (0);
912 	}
913 #endif /* HAVE_SYSV_TTYS */
914 
915 #ifdef HAVE_BSD_TTYS
916 
917 	/*
918 	 * 4.3bsd serial line parameters (sgttyb interface)
919 	 */
920 	if (ioctl(fd, TIOCGETP, (char *)ttyp) < 0) {
921 		msyslog(LOG_ERR,
922 		    "refclock_open: fd %d TIOCGETP %m", fd);
923 		return (0);
924 	}
925 	ttyp->sg_ispeed = ttyp->sg_ospeed = speed;
926 	ttyp->sg_flags = EVENP | ODDP | CRMOD;
927 	if (ioctl(fd, TIOCSETP, (char *)ttyp) < 0) {
928 		msyslog(LOG_ERR,
929 		    "refclock_open: TIOCSETP failed: %m");
930 		return (0);
931 	}
932 #endif /* HAVE_BSD_TTYS */
933 	if (!refclock_ioctl(fd, flags)) {
934 		(void)close(fd);
935 		msyslog(LOG_ERR,
936 		    "refclock_open: fd %d ioctl failed: %m", fd);
937 		return (0);
938 	}
939 
940 	/*
941 	 * If this is the PPS device, so say and initialize the thing.
942 	 */
943 	if (strcmp(dev, pps_device) == 0)
944 		(void)refclock_ioctl(fd, LDISC_PPS);
945 	return (fd);
946 }
947 #endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */
948 #endif /* SYS_VXWORKS SYS_WINNT */
949 
950 /*
951  * refclock_ioctl - set serial port control functions
952  *
953  * This routine attempts to hide the internal, system-specific details
954  * of serial ports. It can handle POSIX (termios), SYSV (termio) and BSD
955  * (sgtty) interfaces with varying degrees of success. The routine sets
956  * up optional features such as tty_clk, ppsclock and ppsapi, as well as
957  * their many other variants. The routine returns 1 if success and 0 if
958  * failure.
959  */
960 int
961 refclock_ioctl(
962 	int fd, 		/* file descriptor */
963 	int flags		/* line discipline flags */
964 	)
965 {
966 	/* simply return 1 if no UNIX line discipline is supported */
967 #if !defined SYS_VXWORKS && !defined SYS_WINNT
968 #if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)
969 
970 #ifdef TTYCLK
971 #ifdef HAVE_TERMIOS
972 	struct termios ttyb, *ttyp;
973 #endif /* HAVE_TERMIOS */
974 #ifdef HAVE_SYSV_TTYS
975 	struct termio ttyb, *ttyp;
976 #endif /* HAVE_SYSV_TTYS */
977 #ifdef HAVE_BSD_TTYS
978 	struct sgttyb ttyb, *ttyp;
979 #endif /* HAVE_BSD_TTYS */
980 #endif /* TTYCLK */
981 
982 #ifdef DEBUG
983 	if (debug)
984 		printf("refclock_ioctl: fd %d flags 0x%x\n", fd, flags);
985 #endif
986 
987 	/*
988 	 * The following sections select optional features, such as
989 	 * modem control, PPS capture and so forth. Some require
990 	 * specific operating system support in the form of STREAMS
991 	 * modules, which can be loaded and unloaded at run time without
992 	 * rebooting the kernel. The STREAMS modules require System
993 	 * V STREAMS support. The checking frenzy is attenuated here,
994 	 * since the device is already open.
995 	 *
996 	 * Note that the tty_clk and ppsclock modules are optional; if
997 	 * configured and unavailable, the dang thing still works, but
998 	 * the accuracy improvement using them will not be available.
999 	 * The only known implmentations of these moldules are specific
1000 	 * to SunOS 4.x. Use the ppsclock module ONLY with Sun baseboard
1001 	 * ttya or ttyb. Using it with the SPIF multipexor crashes the
1002 	 * kernel.
1003 	 *
1004 	 * The preferred way to capture PPS timestamps is using the
1005 	 * ppsapi interface, which is machine independent. The SunOS 4.x
1006 	 * and Digital Unix 4.x interfaces use STREAMS modules and
1007 	 * support both the ppsapi specification and ppsclock
1008 	 * functionality, but other systems may vary widely.
1009 	 */
1010 	if (flags == 0)
1011 		return (1);
1012 #if !(defined(HAVE_TERMIOS) || defined(HAVE_BSD_TTYS))
1013 	if (flags & (LDISC_CLK | LDISC_PPS | LDISC_ACTS)) {
1014 		msyslog(LOG_ERR,
1015 			"refclock_ioctl: unsupported terminal interface");
1016 		return (0);
1017 	}
1018 #endif /* HAVE_TERMIOS HAVE_BSD_TTYS */
1019 #ifdef TTYCLK
1020 	ttyp = &ttyb;
1021 #endif /* TTYCLK */
1022 
1023 	/*
1024 	 * The following features may or may not require System V
1025 	 * STREAMS support, depending on the particular implementation.
1026 	 */
1027 #if defined(TTYCLK)
1028 	/*
1029 	 * The TTYCLK option provides timestamping at the driver level.
1030 	 * It requires the tty_clk streams module and System V STREAMS
1031 	 * support. If not available, don't complain.
1032 	 */
1033 	if (flags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) {
1034 		int rval = 0;
1035 
1036 		if (ioctl(fd, I_PUSH, "clk") < 0) {
1037 			msyslog(LOG_NOTICE,
1038 			    "refclock_ioctl: I_PUSH clk failed: %m");
1039 		} else {
1040 			char *str;
1041 
1042 			if (flags & LDISC_CLKPPS)
1043 				str = "\377";
1044 			else if (flags & LDISC_ACTS)
1045 				str = "*";
1046 			else
1047 				str = "\n";
1048 #ifdef CLK_SETSTR
1049 			if ((rval = ioctl(fd, CLK_SETSTR, str)) < 0)
1050 				msyslog(LOG_ERR,
1051 				    "refclock_ioctl: CLK_SETSTR failed: %m");
1052 			if (debug)
1053 				printf("refclock_ioctl: fd %d CLK_SETSTR %d str %s\n",
1054 				    fd, rval, str);
1055 #endif
1056 		}
1057 	}
1058 #endif /* TTYCLK */
1059 
1060 #if defined(PPS) && !defined(HAVE_PPSAPI)
1061 	/*
1062 	 * The PPS option provides timestamping at the driver level.
1063 	 * It uses a 1-pps signal and level converter (gadget box) and
1064 	 * requires the ppsclock streams module and System V STREAMS
1065 	 * support. This option has been superseded by the ppsapi
1066 	 * option and may be withdrawn in future.
1067 	 */
1068 	if (flags & LDISC_PPS) {
1069 		int rval = 0;
1070 #ifdef HAVE_TIOCSPPS		/* Solaris */
1071 		int one = 1;
1072 #endif /* HAVE_TIOCSPPS */
1073 
1074 		if (fdpps > 0) {
1075 			msyslog(LOG_ERR,
1076 				"refclock_ioctl: PPS already configured");
1077 			return (0);
1078 		}
1079 #ifdef HAVE_TIOCSPPS		/* Solaris */
1080 		if (ioctl(fd, TIOCSPPS, &one) < 0) {
1081 			msyslog(LOG_NOTICE,
1082 				"refclock_ioctl: TIOCSPPS failed: %m");
1083 			return (0);
1084 		}
1085 		if (debug)
1086 			printf("refclock_ioctl: fd %d TIOCSPPS %d\n",
1087 			    fd, rval);
1088 #else
1089 		if (ioctl(fd, I_PUSH, "ppsclock") < 0) {
1090 			msyslog(LOG_NOTICE,
1091 				"refclock_ioctl: I_PUSH ppsclock failed: %m");
1092 			return (0);
1093 		}
1094 		if (debug)
1095 			printf("refclock_ioctl: fd %d ppsclock %d\n",
1096 			    fd, rval);
1097 #endif /* not HAVE_TIOCSPPS */
1098 		fdpps = fd;
1099 	}
1100 #endif /* PPS HAVE_PPSAPI */
1101 
1102 #ifdef HAVE_PPSAPI
1103 	/*
1104 	 * The PPSAPI option provides timestamping at the driver level.
1105 	 * It uses a 1-pps signal and level converter (gadget box) and
1106 	 * requires ppsapi compiled into the kernel on non STREAMS
1107 	 * systems. This is the preferred way to capture PPS timestamps
1108 	 * and is expected to become an IETF cross-platform standard.
1109 	 */
1110 	if (flags & (LDISC_PPS | LDISC_CLKPPS)) {
1111 		pps_params_t pp;
1112 		int mode, temp;
1113 		pps_handle_t handle;
1114 
1115 		memset((char *)&pp, 0, sizeof(pp));
1116 		if (fdpps > 0) {
1117 			msyslog(LOG_ERR,
1118 			    "refclock_ioctl: ppsapi already configured");
1119 			return (0);
1120 		}
1121 		if (time_pps_create(fd, &handle) < 0) {
1122 			msyslog(LOG_ERR,
1123 			    "refclock_ioctl: time_pps_create failed: %m");
1124 			return (0);
1125 		}
1126 		if (time_pps_getcap(handle, &mode) < 0) {
1127 			msyslog(LOG_ERR,
1128 			    "refclock_ioctl: time_pps_getcap failed: %m");
1129 			return (0);
1130 		}
1131 		pp.mode = mode & PPS_CAPTUREBOTH;
1132 		if (time_pps_setparams(handle, &pp) < 0) {
1133 			msyslog(LOG_ERR,
1134 			    "refclock_ioctl: time_pps_setparams failed: %m");
1135 			return (0);
1136 		}
1137 		if (!pps_hardpps)
1138 			temp = 0;
1139 		else if (pps_assert)
1140 			temp = mode & PPS_CAPTUREASSERT;
1141 		else
1142 			temp = mode & PPS_CAPTURECLEAR;
1143 		if (time_pps_kcbind(handle, PPS_KC_HARDPPS, temp,
1144 		    PPS_TSFMT_TSPEC) < 0) {
1145 			msyslog(LOG_ERR,
1146 			    "refclock_ioctl: time_pps_kcbind failed: %m");
1147 			return (0);
1148 		}
1149 		(void)time_pps_getparams(handle, &pp);
1150 		fdpps = (int)handle;
1151 		if (debug)
1152 			printf(
1153 			    "refclock_ioctl: fd %d ppsapi vers %d mode 0x%x cap 0x%x\n",
1154 			    fdpps, pp.api_version, pp.mode, mode);
1155 	}
1156 #endif /* HAVE_PPSAPI */
1157 #endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */
1158 #endif /* SYS_VXWORKS SYS_WINNT */
1159 	return (1);
1160 }
1161 
1162 /*
1163  * refclock_control - set and/or return clock values
1164  *
1165  * This routine is used mainly for debugging. It returns designated
1166  * values from the interface structure that can be displayed using
1167  * ntpdc and the clockstat command. It can also be used to initialize
1168  * configuration variables, such as fudgetimes, fudgevalues, reference
1169  * ID and stratum.
1170  */
1171 void
1172 refclock_control(
1173 	struct sockaddr_in *srcadr,
1174 	struct refclockstat *in,
1175 	struct refclockstat *out
1176 	)
1177 {
1178 	struct peer *peer;
1179 	struct refclockproc *pp;
1180 	u_char clktype;
1181 	int unit;
1182 
1183 	/*
1184 	 * Check for valid address and running peer
1185 	 */
1186 	if (!ISREFCLOCKADR(srcadr))
1187 		return;
1188 	clktype = (u_char)REFCLOCKTYPE(srcadr);
1189 	unit = REFCLOCKUNIT(srcadr);
1190 	if (clktype >= num_refclock_conf || unit >= MAXUNIT)
1191 		return;
1192 	if (!(peer = typeunit[clktype][unit]))
1193 		return;
1194 	pp = peer->procptr;
1195 
1196 	/*
1197 	 * Initialize requested data
1198 	 */
1199 	if (in != 0) {
1200 		if (in->haveflags & CLK_HAVETIME1)
1201 			pp->fudgetime1 = in->fudgetime1;
1202 		if (in->haveflags & CLK_HAVETIME2)
1203 			pp->fudgetime2 = in->fudgetime2;
1204 		if (in->haveflags & CLK_HAVEVAL1)
1205 			peer->stratum = (u_char) in->fudgeval1;
1206 		if (in->haveflags & CLK_HAVEVAL2)
1207 			pp->refid = in->fudgeval2;
1208 		if (peer->stratum <= 1)
1209 			peer->refid = pp->refid;
1210 		else
1211 			peer->refid = peer->srcadr.sin_addr.s_addr;
1212 		if (in->haveflags & CLK_HAVEFLAG1) {
1213 			pp->sloppyclockflag &= ~CLK_FLAG1;
1214 			pp->sloppyclockflag |= in->flags & CLK_FLAG1;
1215 		}
1216 		if (in->haveflags & CLK_HAVEFLAG2) {
1217 			pp->sloppyclockflag &= ~CLK_FLAG2;
1218 			pp->sloppyclockflag |= in->flags & CLK_FLAG2;
1219 		}
1220 		if (in->haveflags & CLK_HAVEFLAG3) {
1221 			pp->sloppyclockflag &= ~CLK_FLAG3;
1222 			pp->sloppyclockflag |= in->flags & CLK_FLAG3;
1223 		}
1224 		if (in->haveflags & CLK_HAVEFLAG4) {
1225 			pp->sloppyclockflag &= ~CLK_FLAG4;
1226 			pp->sloppyclockflag |= in->flags & CLK_FLAG4;
1227 		}
1228 	}
1229 
1230 	/*
1231 	 * Readback requested data
1232 	 */
1233 	if (out != 0) {
1234 		out->haveflags = CLK_HAVETIME1 | CLK_HAVEVAL1 |
1235 			CLK_HAVEVAL2 | CLK_HAVEFLAG4;
1236 		out->fudgetime1 = pp->fudgetime1;
1237 		out->fudgetime2 = pp->fudgetime2;
1238 		out->fudgeval1 = peer->stratum;
1239 		out->fudgeval2 = pp->refid;
1240 		out->flags = (u_char) pp->sloppyclockflag;
1241 
1242 		out->timereset = current_time - pp->timestarted;
1243 		out->polls = pp->polls;
1244 		out->noresponse = pp->noreply;
1245 		out->badformat = pp->badformat;
1246 		out->baddata = pp->baddata;
1247 
1248 		out->lastevent = pp->lastevent;
1249 		out->currentstatus = pp->currentstatus;
1250 		out->type = pp->type;
1251 		out->clockdesc = pp->clockdesc;
1252 		out->lencode = pp->lencode;
1253 		out->p_lastcode = pp->a_lastcode;
1254 	}
1255 
1256 	/*
1257 	 * Give the stuff to the clock
1258 	 */
1259 	if (refclock_conf[clktype]->clock_control != noentry)
1260 		(refclock_conf[clktype]->clock_control)(unit, in, out, peer);
1261 }
1262 
1263 
1264 /*
1265  * refclock_buginfo - return debugging info
1266  *
1267  * This routine is used mainly for debugging. It returns designated
1268  * values from the interface structure that can be displayed using
1269  * ntpdc and the clkbug command.
1270  */
1271 void
1272 refclock_buginfo(
1273 	struct sockaddr_in *srcadr, /* clock address */
1274 	struct refclockbug *bug /* output structure */
1275 	)
1276 {
1277 	struct peer *peer;
1278 	struct refclockproc *pp;
1279 	u_char clktype;
1280 	int unit;
1281 	int i;
1282 
1283 	/*
1284 	 * Check for valid address and peer structure
1285 	 */
1286 	if (!ISREFCLOCKADR(srcadr))
1287 		return;
1288 	clktype = (u_char) REFCLOCKTYPE(srcadr);
1289 	unit = REFCLOCKUNIT(srcadr);
1290 	if (clktype >= num_refclock_conf || unit >= MAXUNIT)
1291 		return;
1292 	if (!(peer = typeunit[clktype][unit]))
1293 		return;
1294 	pp = peer->procptr;
1295 
1296 	/*
1297 	 * Copy structure values
1298 	 */
1299 	bug->nvalues = 8;
1300 	bug->svalues = 0x0000003f;
1301 	bug->values[0] = pp->year;
1302 	bug->values[1] = pp->day;
1303 	bug->values[2] = pp->hour;
1304 	bug->values[3] = pp->minute;
1305 	bug->values[4] = pp->second;
1306 	bug->values[5] = pp->msec;
1307 	bug->values[6] = pp->yearstart;
1308 	bug->values[7] = pp->coderecv;
1309 	bug->stimes = 0xfffffffc;
1310 	bug->times[0] = pp->lastref;
1311 	bug->times[1] = pp->lastrec;
1312 	for (i = 2; i < (int)bug->ntimes; i++)
1313 		DTOLFP(pp->filter[i - 2], &bug->times[i]);
1314 
1315 	/*
1316 	 * Give the stuff to the clock
1317 	 */
1318 	if (refclock_conf[clktype]->clock_buginfo != noentry)
1319 		(refclock_conf[clktype]->clock_buginfo)(unit, bug, peer);
1320 }
1321 
1322 #endif /* REFCLOCK */
1323