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