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