154359Sroberto 254359Sroberto/* 354359Sroberto * refclock_local - local pseudo-clock driver 4132451Sroberto * 5132451Sroberto * wjm 17-aug-1995: add a hook for special treatment of VMS_LOCALUNIT 654359Sroberto */ 754359Sroberto#ifdef HAVE_CONFIG_H 854359Sroberto#include <config.h> 954359Sroberto#endif 1054359Sroberto 1154359Sroberto#ifdef REFCLOCK 1254359Sroberto 1354359Sroberto#include "ntpd.h" 1454359Sroberto#include "ntp_refclock.h" 1554359Sroberto#include "ntp_stdlib.h" 1654359Sroberto 1782498Sroberto#include <stdio.h> 1882498Sroberto#include <ctype.h> 1982498Sroberto 2054359Sroberto#ifdef KERNEL_PLL 2154359Sroberto#include "ntp_syscall.h" 2254359Sroberto#endif 2354359Sroberto 2454359Sroberto/* 2554359Sroberto * This is a hack to allow a machine to use its own system clock as a 2654359Sroberto * reference clock, i.e., to free-run using no outside clock discipline 27280849Scy * source. Note that the clock selection algorithm will not select this 28280849Scy * driver unless all other sources of synchronization have been lost. 29280849Scy * This is useful if you want to use NTP in an isolated environment 30280849Scy * with no radio clock or NIST modem available. Pick a machine that you 31280849Scy * figure has a good clock oscillator and configure it with this 32280849Scy * driver. Set the clock using the best means available, like 3354359Sroberto * eyeball-and-wristwatch. Then, point all the other machines at this 3454359Sroberto * one or use broadcast (not multicast) mode to distribute time. 3554359Sroberto * 3654359Sroberto * Another application for this driver is if you want to use a 3754359Sroberto * particular server's clock as the clock of last resort when all other 3854359Sroberto * normal synchronization sources have gone away. This is especially 39280849Scy * useful if that server has an ovenized oscillator. However, the 40280849Scy * preferred was to do this is using orphan mode. See the documentation. 4154359Sroberto * 4254359Sroberto * A third application for this driver is when an external discipline 4354359Sroberto * source is available, such as the NIST "lockclock" program, which 4454359Sroberto * synchronizes the local clock via a telephone modem and the NIST 4554359Sroberto * Automated Computer Time Service (ACTS), or the Digital Time 4654359Sroberto * Synchronization Service (DTSS), which runs on DCE machines. In this 4754359Sroberto * case the stratum should be set at zero, indicating a bona fide 4854359Sroberto * stratum-1 source. Exercise some caution with this, since there is no 4954359Sroberto * easy way to telegraph via NTP that something might be wrong in the 5054359Sroberto * discipline source itself. In the case of DTSS, the local clock can 5154359Sroberto * have a rather large jitter, depending on the interval between 5254359Sroberto * corrections and the intrinsic frequency error of the clock 5354359Sroberto * oscillator. In extreme cases, this can cause clients to exceed the 5454359Sroberto * 128-ms slew window and drop off the NTP subnet. 5554359Sroberto * 5654359Sroberto * Fudge Factors 5754359Sroberto * 58289764Sglebius * None currently supported. 5954359Sroberto */ 6054359Sroberto/* 6154359Sroberto * Local interface definitions 6254359Sroberto */ 6354359Sroberto#define PRECISION (-7) /* about 10 ms precision */ 6454359Sroberto#define DESCRIPTION "Undisciplined local clock" /* WRU */ 6582498Sroberto#define STRATUM 5 /* default stratum */ 6654359Sroberto#define DISPERSION .01 /* default dispersion (10 ms) */ 6754359Sroberto 6854359Sroberto/* 6954359Sroberto * Imported from the timer module 7054359Sroberto */ 7154359Srobertoextern u_long current_time; 7254359Sroberto 7354359Sroberto/* 7454359Sroberto * Imported from ntp_proto 7554359Sroberto */ 7654359Srobertoextern s_char sys_precision; 7754359Sroberto 7854359Sroberto/* 7954359Sroberto * Function prototypes 8054359Sroberto */ 81280849Scystatic int local_start (int, struct peer *); 82280849Scystatic void local_poll (int, struct peer *); 8354359Sroberto 8454359Sroberto/* 8554359Sroberto * Local variables 8654359Sroberto */ 8754359Srobertostatic u_long poll_time; /* last time polled */ 8854359Sroberto 8954359Sroberto/* 9054359Sroberto * Transfer vector 9154359Sroberto */ 9254359Srobertostruct refclock refclock_local = { 9354359Sroberto local_start, /* start up driver */ 9454359Sroberto noentry, /* shut down driver (not used) */ 9554359Sroberto local_poll, /* transmit poll message */ 9654359Sroberto noentry, /* not used (old lcl_control) */ 9754359Sroberto noentry, /* initialize driver (not used) */ 9854359Sroberto noentry, /* not used (old lcl_buginfo) */ 9954359Sroberto NOFLAGS /* not used */ 10054359Sroberto}; 10154359Sroberto 10254359Sroberto 10354359Sroberto/* 10454359Sroberto * local_start - start up the clock 10554359Sroberto */ 10654359Srobertostatic int 10754359Srobertolocal_start( 10854359Sroberto int unit, 10954359Sroberto struct peer *peer 11054359Sroberto ) 11154359Sroberto{ 11254359Sroberto struct refclockproc *pp; 11354359Sroberto 11454359Sroberto pp = peer->procptr; 11554359Sroberto 11654359Sroberto /* 11754359Sroberto * Initialize miscellaneous variables 11854359Sroberto */ 11954359Sroberto peer->precision = sys_precision; 120132451Sroberto pp->leap = LEAP_NOTINSYNC; 12154359Sroberto peer->stratum = STRATUM; 122132451Sroberto pp->stratum = STRATUM; 12354359Sroberto pp->clockdesc = DESCRIPTION; 124182007Sroberto memcpy(&pp->refid, "LOCL", 4); 12554359Sroberto poll_time = current_time; 12654359Sroberto return (1); 12754359Sroberto} 12854359Sroberto 12954359Sroberto 13054359Sroberto/* 13154359Sroberto * local_poll - called by the transmit procedure 132132451Sroberto * 133132451Sroberto * LOCKCLOCK: If the kernel supports the nanokernel or microkernel 134132451Sroberto * system calls, the leap bits are extracted from the kernel. If there 135132451Sroberto * is a kernel error or the kernel leap bits are set to 11, the NTP leap 136132451Sroberto * bits are set to 11 and the stratum is set to infinity. Otherwise, the 137132451Sroberto * NTP leap bits are set to the kernel leap bits and the stratum is set 138132451Sroberto * as fudged. This behavior does not faithfully follow the 139132451Sroberto * specification, but is probably more appropriate in a multiple-server 140132451Sroberto * national laboratory network. 14154359Sroberto */ 14254359Srobertostatic void 14354359Srobertolocal_poll( 14454359Sroberto int unit, 14554359Sroberto struct peer *peer 14654359Sroberto ) 14754359Sroberto{ 148132451Sroberto#if defined(KERNEL_PLL) && defined(LOCKCLOCK) 149132451Sroberto struct timex ntv; 150132451Sroberto#endif /* KERNEL_PLL LOCKCLOCK */ 15154359Sroberto struct refclockproc *pp; 15254359Sroberto 153280849Scy /* 154280849Scy * Do no evil unless the house is dark or lit with our own lamp. 155280849Scy */ 156280849Scy if (!(sys_peer == NULL || sys_peer == peer)) 157280849Scy return; 158280849Scy 15954359Sroberto#if defined(VMS) && defined(VMS_LOCALUNIT) 160132451Sroberto if (unit == VMS_LOCALUNIT) { 16154359Sroberto extern void vms_local_poll(struct peer *); 16254359Sroberto 16354359Sroberto vms_local_poll(peer); 16454359Sroberto return; 16554359Sroberto } 166132451Sroberto#endif /* VMS && VMS_LOCALUNIT */ 167280849Scy 16854359Sroberto pp = peer->procptr; 16954359Sroberto pp->polls++; 17054359Sroberto 17154359Sroberto /* 17254359Sroberto * Ramble through the usual filtering and grooming code, which 17354359Sroberto * is essentially a no-op and included mostly for pretty 174289764Sglebius * billboards. 17554359Sroberto */ 17654359Sroberto poll_time = current_time; 177280849Scy refclock_process_offset(pp, pp->lastrec, pp->lastrec, 0); 17854359Sroberto 17954359Sroberto /* 180132451Sroberto * If another process is disciplining the system clock, we set 181132451Sroberto * the leap bits and quality indicators from the kernel. 18254359Sroberto */ 183132451Sroberto#if defined(KERNEL_PLL) && defined(LOCKCLOCK) 184132451Sroberto memset(&ntv, 0, sizeof ntv); 185132451Sroberto switch (ntp_adjtime(&ntv)) { 186132451Sroberto case TIME_OK: 187132451Sroberto pp->leap = LEAP_NOWARNING; 188132451Sroberto peer->stratum = pp->stratum; 189132451Sroberto break; 19054359Sroberto 191132451Sroberto case TIME_INS: 192132451Sroberto pp->leap = LEAP_ADDSECOND; 193132451Sroberto peer->stratum = pp->stratum; 194132451Sroberto break; 19554359Sroberto 196132451Sroberto case TIME_DEL: 197132451Sroberto pp->leap = LEAP_DELSECOND; 198132451Sroberto peer->stratum = pp->stratum; 199132451Sroberto break; 20054359Sroberto 201132451Sroberto default: 202132451Sroberto pp->leap = LEAP_NOTINSYNC; 203132451Sroberto peer->stratum = STRATUM_UNSPEC; 20454359Sroberto } 205132451Sroberto pp->disp = 0; 206132451Sroberto pp->jitter = 0; 207132451Sroberto#else /* KERNEL_PLL LOCKCLOCK */ 208293423Sdelphij pp->leap = LEAP_NOWARNING; 209132451Sroberto pp->disp = DISPERSION; 210132451Sroberto pp->jitter = 0; 211132451Sroberto#endif /* KERNEL_PLL LOCKCLOCK */ 212106424Sroberto pp->lastref = pp->lastrec; 21354359Sroberto refclock_receive(peer); 21454359Sroberto} 215106163Sroberto#else 216106163Srobertoint refclock_local_bs; 21754359Sroberto#endif /* REFCLOCK */ 218