Fix a serious bug in the NTPD loopfilter. Basically what happens is that
[dragonfly.git] / contrib / ntp / ntpd / ntp_refclock.c
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 */