Home | History | Annotate | Line # | Download | only in ntpd
refclock_local.c revision 1.1.1.1.8.1
      1  1.1.1.1.8.1     snj /*	$NetBSD: refclock_local.c,v 1.1.1.1.8.1 2014/12/25 02:34:38 snj Exp $	*/
      2          1.1  kardel 
      3          1.1  kardel 
      4          1.1  kardel /*
      5          1.1  kardel  * refclock_local - local pseudo-clock driver
      6          1.1  kardel  *
      7          1.1  kardel  * wjm 17-aug-1995: add a hook for special treatment of VMS_LOCALUNIT
      8          1.1  kardel  */
      9          1.1  kardel #ifdef HAVE_CONFIG_H
     10          1.1  kardel #include <config.h>
     11          1.1  kardel #endif
     12          1.1  kardel 
     13          1.1  kardel #ifdef REFCLOCK
     14          1.1  kardel 
     15          1.1  kardel #include "ntpd.h"
     16          1.1  kardel #include "ntp_refclock.h"
     17          1.1  kardel #include "ntp_stdlib.h"
     18          1.1  kardel 
     19          1.1  kardel #include <stdio.h>
     20          1.1  kardel #include <ctype.h>
     21          1.1  kardel 
     22          1.1  kardel #ifdef KERNEL_PLL
     23          1.1  kardel #include "ntp_syscall.h"
     24          1.1  kardel #endif
     25          1.1  kardel 
     26          1.1  kardel /*
     27          1.1  kardel  * This is a hack to allow a machine to use its own system clock as a
     28          1.1  kardel  * reference clock, i.e., to free-run using no outside clock discipline
     29          1.1  kardel  * source. Note that the clock selection algorithm will not select this
     30          1.1  kardel  * driver unless all other sources of synchronization have been lost.
     31          1.1  kardel  * This is useful if you want to use NTP in an isolated environment
     32          1.1  kardel  * with no radio clock or NIST modem available. Pick a machine that you
     33          1.1  kardel  * figure has a good clock oscillator and configure it with this
     34          1.1  kardel  * driver. Set the clock using the best means available, like
     35          1.1  kardel  * eyeball-and-wristwatch. Then, point all the other machines at this
     36          1.1  kardel  * one or use broadcast (not multicast) mode to distribute time.
     37          1.1  kardel  *
     38          1.1  kardel  * Another application for this driver is if you want to use a
     39          1.1  kardel  * particular server's clock as the clock of last resort when all other
     40          1.1  kardel  * normal synchronization sources have gone away. This is especially
     41          1.1  kardel  * useful if that server has an ovenized oscillator. However, the
     42          1.1  kardel  * preferred was to do this is using orphan mode. See the documentation.
     43          1.1  kardel  *
     44          1.1  kardel  * A third application for this driver is when an external discipline
     45          1.1  kardel  * source is available, such as the NIST "lockclock" program, which
     46          1.1  kardel  * synchronizes the local clock via a telephone modem and the NIST
     47          1.1  kardel  * Automated Computer Time Service (ACTS), or the Digital Time
     48          1.1  kardel  * Synchronization Service (DTSS), which runs on DCE machines. In this
     49          1.1  kardel  * case the stratum should be set at zero, indicating a bona fide
     50          1.1  kardel  * stratum-1 source. Exercise some caution with this, since there is no
     51          1.1  kardel  * easy way to telegraph via NTP that something might be wrong in the
     52          1.1  kardel  * discipline source itself. In the case of DTSS, the local clock can
     53          1.1  kardel  * have a rather large jitter, depending on the interval between
     54          1.1  kardel  * corrections and the intrinsic frequency error of the clock
     55          1.1  kardel  * oscillator. In extreme cases, this can cause clients to exceed the
     56          1.1  kardel  * 128-ms slew window and drop off the NTP subnet.
     57          1.1  kardel  *
     58          1.1  kardel  * Fudge Factors
     59          1.1  kardel  *
     60          1.1  kardel  * If fudge flag1 is lit, the leap second bit is set in the peer
     61          1.1  kardel  * status word. It should be set early in the day of a leap second
     62          1.1  kardel  * event and set dark on the day after the event.
     63          1.1  kardel  *
     64          1.1  kardel  * Note the fudge time1 and time2 have been deprecated. The fudge time1
     65          1.1  kardel  * was intended to apply a bias offset. This can be done using the Unix
     66          1.1  kardel  * date command. The fudge time2 was intended to apply a bias frequency.
     67          1.1  kardel  * This can be done using the frequency file and/or the freq
     68          1.1  kardel  * configuration command.
     69          1.1  kardel  */
     70          1.1  kardel /*
     71          1.1  kardel  * Local interface definitions
     72          1.1  kardel  */
     73          1.1  kardel #define PRECISION	(-7)	/* about 10 ms precision */
     74          1.1  kardel #define DESCRIPTION "Undisciplined local clock" /* WRU */
     75          1.1  kardel #define STRATUM 	5	/* default stratum */
     76          1.1  kardel #define DISPERSION	.01	/* default dispersion (10 ms) */
     77          1.1  kardel 
     78          1.1  kardel /*
     79          1.1  kardel  * Imported from the timer module
     80          1.1  kardel  */
     81          1.1  kardel extern u_long current_time;
     82          1.1  kardel 
     83          1.1  kardel /*
     84          1.1  kardel  * Imported from ntp_proto
     85          1.1  kardel  */
     86          1.1  kardel extern s_char sys_precision;
     87          1.1  kardel 
     88          1.1  kardel /*
     89          1.1  kardel  * Function prototypes
     90          1.1  kardel  */
     91          1.1  kardel static	int local_start (int, struct peer *);
     92          1.1  kardel static	void	local_poll	(int, struct peer *);
     93          1.1  kardel 
     94          1.1  kardel /*
     95          1.1  kardel  * Local variables
     96          1.1  kardel  */
     97          1.1  kardel static	u_long poll_time;	/* last time polled */
     98          1.1  kardel 
     99          1.1  kardel /*
    100          1.1  kardel  * Transfer vector
    101          1.1  kardel  */
    102          1.1  kardel struct	refclock refclock_local = {
    103          1.1  kardel 	local_start,		/* start up driver */
    104          1.1  kardel 	noentry,		/* shut down driver (not used) */
    105          1.1  kardel 	local_poll,	 	/* transmit poll message */
    106          1.1  kardel 	noentry,		/* not used (old lcl_control) */
    107          1.1  kardel 	noentry,		/* initialize driver (not used) */
    108          1.1  kardel 	noentry,		/* not used (old lcl_buginfo) */
    109          1.1  kardel 	NOFLAGS 		/* not used */
    110          1.1  kardel };
    111          1.1  kardel 
    112          1.1  kardel 
    113          1.1  kardel /*
    114          1.1  kardel  * local_start - start up the clock
    115          1.1  kardel  */
    116          1.1  kardel static int
    117          1.1  kardel local_start(
    118          1.1  kardel 	int unit,
    119          1.1  kardel 	struct peer *peer
    120          1.1  kardel 	)
    121          1.1  kardel {
    122          1.1  kardel 	struct refclockproc *pp;
    123          1.1  kardel 
    124          1.1  kardel 	pp = peer->procptr;
    125          1.1  kardel 
    126          1.1  kardel 	/*
    127          1.1  kardel 	 * Initialize miscellaneous variables
    128          1.1  kardel 	 */
    129          1.1  kardel 	peer->precision = sys_precision;
    130          1.1  kardel 	pp->leap = LEAP_NOTINSYNC;
    131          1.1  kardel 	peer->stratum = STRATUM;
    132          1.1  kardel 	pp->stratum = STRATUM;
    133          1.1  kardel 	pp->clockdesc = DESCRIPTION;
    134          1.1  kardel 	memcpy(&pp->refid, "LOCL", 4);
    135          1.1  kardel 	poll_time = current_time;
    136          1.1  kardel 	return (1);
    137          1.1  kardel }
    138          1.1  kardel 
    139          1.1  kardel 
    140          1.1  kardel /*
    141          1.1  kardel  * local_poll - called by the transmit procedure
    142          1.1  kardel  *
    143          1.1  kardel  * LOCKCLOCK: If the kernel supports the nanokernel or microkernel
    144          1.1  kardel  * system calls, the leap bits are extracted from the kernel. If there
    145          1.1  kardel  * is a kernel error or the kernel leap bits are set to 11, the NTP leap
    146          1.1  kardel  * bits are set to 11 and the stratum is set to infinity. Otherwise, the
    147          1.1  kardel  * NTP leap bits are set to the kernel leap bits and the stratum is set
    148          1.1  kardel  * as fudged. This behavior does not faithfully follow the
    149          1.1  kardel  * specification, but is probably more appropriate in a multiple-server
    150          1.1  kardel  * national laboratory network.
    151          1.1  kardel  */
    152          1.1  kardel static void
    153          1.1  kardel local_poll(
    154          1.1  kardel 	int unit,
    155          1.1  kardel 	struct peer *peer
    156          1.1  kardel 	)
    157          1.1  kardel {
    158          1.1  kardel #if defined(KERNEL_PLL) && defined(LOCKCLOCK)
    159          1.1  kardel 	struct timex ntv;
    160          1.1  kardel #endif /* KERNEL_PLL LOCKCLOCK */
    161          1.1  kardel 	struct refclockproc *pp;
    162          1.1  kardel 
    163          1.1  kardel 	/*
    164          1.1  kardel 	 * Do no evil unless the house is dark or lit with our own lamp.
    165          1.1  kardel 	 */
    166          1.1  kardel 	if (!(sys_peer == NULL || sys_peer == peer))
    167          1.1  kardel 		return;
    168          1.1  kardel 
    169          1.1  kardel #if defined(VMS) && defined(VMS_LOCALUNIT)
    170          1.1  kardel 	if (unit == VMS_LOCALUNIT) {
    171          1.1  kardel 		extern void vms_local_poll(struct peer *);
    172          1.1  kardel 
    173          1.1  kardel 		vms_local_poll(peer);
    174          1.1  kardel 		return;
    175          1.1  kardel 	}
    176          1.1  kardel #endif /* VMS && VMS_LOCALUNIT */
    177          1.1  kardel 
    178          1.1  kardel 	pp = peer->procptr;
    179          1.1  kardel 	pp->polls++;
    180          1.1  kardel 
    181          1.1  kardel 	/*
    182          1.1  kardel 	 * Ramble through the usual filtering and grooming code, which
    183          1.1  kardel 	 * is essentially a no-op and included mostly for pretty
    184          1.1  kardel 	 * billboards. We allow a one-time time adjustment using fudge
    185          1.1  kardel 	 * time1 (s) and a continuous frequency adjustment using fudge
    186          1.1  kardel 	 * time 2 (ppm).
    187          1.1  kardel 	 */
    188          1.1  kardel 	poll_time = current_time;
    189          1.1  kardel 	refclock_process_offset(pp, pp->lastrec, pp->lastrec, 0);
    190          1.1  kardel 
    191          1.1  kardel 	/*
    192          1.1  kardel 	 * If another process is disciplining the system clock, we set
    193          1.1  kardel 	 * the leap bits and quality indicators from the kernel.
    194          1.1  kardel 	 */
    195          1.1  kardel #if defined(KERNEL_PLL) && defined(LOCKCLOCK)
    196          1.1  kardel 	memset(&ntv,  0, sizeof ntv);
    197          1.1  kardel 	switch (ntp_adjtime(&ntv)) {
    198          1.1  kardel 	case TIME_OK:
    199          1.1  kardel 		pp->leap = LEAP_NOWARNING;
    200          1.1  kardel 		peer->stratum = pp->stratum;
    201          1.1  kardel 		break;
    202          1.1  kardel 
    203          1.1  kardel 	case TIME_INS:
    204          1.1  kardel 		pp->leap = LEAP_ADDSECOND;
    205          1.1  kardel 		peer->stratum = pp->stratum;
    206          1.1  kardel 		break;
    207          1.1  kardel 
    208          1.1  kardel 	case TIME_DEL:
    209          1.1  kardel 		pp->leap = LEAP_DELSECOND;
    210          1.1  kardel 		peer->stratum = pp->stratum;
    211          1.1  kardel 		break;
    212          1.1  kardel 
    213          1.1  kardel 	default:
    214          1.1  kardel 		pp->leap = LEAP_NOTINSYNC;
    215          1.1  kardel 		peer->stratum = STRATUM_UNSPEC;
    216          1.1  kardel 	}
    217          1.1  kardel 	pp->disp = 0;
    218          1.1  kardel 	pp->jitter = 0;
    219          1.1  kardel #else /* KERNEL_PLL LOCKCLOCK */
    220          1.1  kardel 	if (pp->sloppyclockflag & CLK_FLAG1)
    221          1.1  kardel 		pp->leap = LEAP_ADDSECOND;
    222          1.1  kardel 	else
    223          1.1  kardel 		pp->leap = LEAP_NOWARNING;
    224          1.1  kardel 	pp->disp = DISPERSION;
    225          1.1  kardel 	pp->jitter = 0;
    226          1.1  kardel #endif /* KERNEL_PLL LOCKCLOCK */
    227          1.1  kardel 	pp->lastref = pp->lastrec;
    228          1.1  kardel 	refclock_receive(peer);
    229          1.1  kardel }
    230          1.1  kardel #else
    231          1.1  kardel int refclock_local_bs;
    232          1.1  kardel #endif /* REFCLOCK */
    233