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 2754359Sroberto * source. This is useful if you want to use NTP in an isolated 2854359Sroberto * environment with no radio clock or NIST modem available. Pick a 2954359Sroberto * machine that you figure has a good clock oscillator and configure it 3054359Sroberto * with this driver. Set the clock using the best means available, like 3154359Sroberto * eyeball-and-wristwatch. Then, point all the other machines at this 3254359Sroberto * one or use broadcast (not multicast) mode to distribute time. 3354359Sroberto * 3454359Sroberto * Another application for this driver is if you want to use a 3554359Sroberto * particular server's clock as the clock of last resort when all other 3654359Sroberto * normal synchronization sources have gone away. This is especially 3754359Sroberto * useful if that server has an ovenized oscillator. For this you would 3882498Sroberto * configure this driver at a higher stratum (say 5) to prevent the 3954359Sroberto * server's stratum from falling below that. 4054359Sroberto * 4154359Sroberto * A third application for this driver is when an external discipline 4254359Sroberto * source is available, such as the NIST "lockclock" program, which 4354359Sroberto * synchronizes the local clock via a telephone modem and the NIST 4454359Sroberto * Automated Computer Time Service (ACTS), or the Digital Time 4554359Sroberto * Synchronization Service (DTSS), which runs on DCE machines. In this 4654359Sroberto * case the stratum should be set at zero, indicating a bona fide 4754359Sroberto * stratum-1 source. Exercise some caution with this, since there is no 4854359Sroberto * easy way to telegraph via NTP that something might be wrong in the 4954359Sroberto * discipline source itself. In the case of DTSS, the local clock can 5054359Sroberto * have a rather large jitter, depending on the interval between 5154359Sroberto * corrections and the intrinsic frequency error of the clock 5254359Sroberto * oscillator. In extreme cases, this can cause clients to exceed the 5354359Sroberto * 128-ms slew window and drop off the NTP subnet. 5454359Sroberto * 5554359Sroberto * THis driver includes provisions to telegraph synchronization state 5654359Sroberto * and related variables by means of kernel variables with specially 5754359Sroberto * modified kernels. This is done using the ntp_adjtime() syscall. 5854359Sroberto * In the cases where another protocol or device synchronizes the local 5954359Sroberto * host, the data given to the kernel can be slurped up by this driver 6054359Sroberto * and distributed to clients by ordinary NTP messaging. 6154359Sroberto * 6254359Sroberto * In the default mode the behavior of the clock selection algorithm is 6354359Sroberto * modified when this driver is in use. The algorithm is designed so 6454359Sroberto * that this driver will never be selected unless no other discipline 6554359Sroberto * source is available. This can be overriden with the prefer keyword of 6654359Sroberto * the server configuration command, in which case only this driver will 6754359Sroberto * be selected for synchronization and all other discipline sources will 6854359Sroberto * be ignored. This behavior is intended for use when an external 6954359Sroberto * discipline source controls the system clock. 7054359Sroberto * 7154359Sroberto * Fudge Factors 7254359Sroberto * 73132451Sroberto * The stratum for this driver set at 5 by default, but it can be 74132451Sroberto * changed by the fudge command and/or the ntpdc utility. The reference 75182007Sroberto * ID is 127.0.0.1 by default, but can be changed using the same mechanism. 76132451Sroberto * *NEVER* configure this driver to operate at a stratum which might 77132451Sroberto * possibly disrupt a client with access to a bona fide primary server, 78132451Sroberto * unless the local clock oscillator is reliably disciplined by another 79132451Sroberto * source. *NEVER NEVER* configure a server which might devolve to an 80132451Sroberto * undisciplined local clock to use multicast mode. Always remember that 81132451Sroberto * an improperly configured local clock driver let loose in the Internet 82132451Sroberto * can cause very serious disruption. This is why most of us who care 83132451Sroberto * about good time use cryptographic authentication. 8454359Sroberto * 8554359Sroberto * This driver provides a mechanism to trim the local clock in both time 8654359Sroberto * and frequency, as well as a way to manipulate the leap bits. The 8754359Sroberto * fudge time1 parameter adjusts the time, in seconds, and the fudge 88132451Sroberto * time2 parameter adjusts the frequency, in ppm. The fudge time1 89132451Sroberto * parameter is additive; that is, it adds an increment to the current 90132451Sroberto * time. The fudge time2 parameter directly sets the frequency. 9154359Sroberto */ 9254359Sroberto/* 9354359Sroberto * Local interface definitions 9454359Sroberto */ 9554359Sroberto#define PRECISION (-7) /* about 10 ms precision */ 9654359Sroberto#define DESCRIPTION "Undisciplined local clock" /* WRU */ 9782498Sroberto#define STRATUM 5 /* default stratum */ 9854359Sroberto#define DISPERSION .01 /* default dispersion (10 ms) */ 9954359Sroberto 10054359Sroberto/* 10154359Sroberto * Imported from the timer module 10254359Sroberto */ 10354359Srobertoextern u_long current_time; 10454359Sroberto 10554359Sroberto/* 10654359Sroberto * Imported from ntp_proto 10754359Sroberto */ 10854359Srobertoextern s_char sys_precision; 10954359Sroberto 11054359Sroberto#ifdef KERNEL_PLL 11154359Sroberto/* 11254359Sroberto * Imported from ntp_loopfilter 11354359Sroberto */ 11454359Srobertoextern int pll_control; /* kernel pll control */ 11554359Srobertoextern int kern_enable; /* kernel pll enabled */ 11654359Srobertoextern int ext_enable; /* external clock enable */ 11754359Sroberto#endif /* KERNEL_PLL */ 11854359Sroberto 11954359Sroberto/* 12054359Sroberto * Function prototypes 12154359Sroberto */ 12254359Srobertostatic int local_start P((int, struct peer *)); 12354359Srobertostatic void local_poll P((int, struct peer *)); 12454359Sroberto 12554359Sroberto/* 12654359Sroberto * Local variables 12754359Sroberto */ 12854359Srobertostatic u_long poll_time; /* last time polled */ 12954359Sroberto 13054359Sroberto/* 13154359Sroberto * Transfer vector 13254359Sroberto */ 13354359Srobertostruct refclock refclock_local = { 13454359Sroberto local_start, /* start up driver */ 13554359Sroberto noentry, /* shut down driver (not used) */ 13654359Sroberto local_poll, /* transmit poll message */ 13754359Sroberto noentry, /* not used (old lcl_control) */ 13854359Sroberto noentry, /* initialize driver (not used) */ 13954359Sroberto noentry, /* not used (old lcl_buginfo) */ 14054359Sroberto NOFLAGS /* not used */ 14154359Sroberto}; 14254359Sroberto 14354359Sroberto 14454359Sroberto/* 14554359Sroberto * local_start - start up the clock 14654359Sroberto */ 14754359Srobertostatic int 14854359Srobertolocal_start( 14954359Sroberto int unit, 15054359Sroberto struct peer *peer 15154359Sroberto ) 15254359Sroberto{ 15354359Sroberto struct refclockproc *pp; 15454359Sroberto 15554359Sroberto pp = peer->procptr; 15654359Sroberto 15754359Sroberto /* 15854359Sroberto * Initialize miscellaneous variables 15954359Sroberto */ 16054359Sroberto peer->precision = sys_precision; 161132451Sroberto pp->leap = LEAP_NOTINSYNC; 16254359Sroberto peer->stratum = STRATUM; 163132451Sroberto pp->stratum = STRATUM; 16454359Sroberto pp->clockdesc = DESCRIPTION; 165182007Sroberto memcpy(&pp->refid, "LOCL", 4); 16654359Sroberto poll_time = current_time; 16754359Sroberto return (1); 16854359Sroberto} 16954359Sroberto 17054359Sroberto 17154359Sroberto/* 17254359Sroberto * local_poll - called by the transmit procedure 173132451Sroberto * 174132451Sroberto * LOCKCLOCK: If the kernel supports the nanokernel or microkernel 175132451Sroberto * system calls, the leap bits are extracted from the kernel. If there 176132451Sroberto * is a kernel error or the kernel leap bits are set to 11, the NTP leap 177132451Sroberto * bits are set to 11 and the stratum is set to infinity. Otherwise, the 178132451Sroberto * NTP leap bits are set to the kernel leap bits and the stratum is set 179132451Sroberto * as fudged. This behavior does not faithfully follow the 180132451Sroberto * specification, but is probably more appropriate in a multiple-server 181132451Sroberto * national laboratory network. 18254359Sroberto */ 18354359Srobertostatic void 18454359Srobertolocal_poll( 18554359Sroberto int unit, 18654359Sroberto struct peer *peer 18754359Sroberto ) 18854359Sroberto{ 189132451Sroberto#if defined(KERNEL_PLL) && defined(LOCKCLOCK) 190132451Sroberto struct timex ntv; 191132451Sroberto#endif /* KERNEL_PLL LOCKCLOCK */ 19254359Sroberto struct refclockproc *pp; 19354359Sroberto 19454359Sroberto#if defined(VMS) && defined(VMS_LOCALUNIT) 195132451Sroberto if (unit == VMS_LOCALUNIT) { 19654359Sroberto extern void vms_local_poll(struct peer *); 19754359Sroberto 19854359Sroberto vms_local_poll(peer); 19954359Sroberto return; 20054359Sroberto } 201132451Sroberto#endif /* VMS && VMS_LOCALUNIT */ 20254359Sroberto pp = peer->procptr; 20354359Sroberto pp->polls++; 20454359Sroberto 20554359Sroberto /* 20654359Sroberto * Ramble through the usual filtering and grooming code, which 20754359Sroberto * is essentially a no-op and included mostly for pretty 20854359Sroberto * billboards. We allow a one-time time adjustment using fudge 20954359Sroberto * time1 (s) and a continuous frequency adjustment using fudge 21054359Sroberto * time 2 (ppm). 21154359Sroberto */ 21254359Sroberto get_systime(&pp->lastrec); 21354359Sroberto pp->fudgetime1 += pp->fudgetime2 * 1e-6 * (current_time - 21454359Sroberto poll_time); 21554359Sroberto poll_time = current_time; 216132451Sroberto refclock_process_offset(pp, pp->lastrec, pp->lastrec, 217132451Sroberto pp->fudgetime1); 21854359Sroberto 21954359Sroberto /* 220132451Sroberto * If another process is disciplining the system clock, we set 221132451Sroberto * the leap bits and quality indicators from the kernel. 22254359Sroberto */ 223132451Sroberto#if defined(KERNEL_PLL) && defined(LOCKCLOCK) 224132451Sroberto memset(&ntv, 0, sizeof ntv); 225132451Sroberto switch (ntp_adjtime(&ntv)) { 226132451Sroberto case TIME_OK: 227132451Sroberto pp->leap = LEAP_NOWARNING; 228132451Sroberto peer->stratum = pp->stratum; 229132451Sroberto break; 23054359Sroberto 231132451Sroberto case TIME_INS: 232132451Sroberto pp->leap = LEAP_ADDSECOND; 233132451Sroberto peer->stratum = pp->stratum; 234132451Sroberto break; 23554359Sroberto 236132451Sroberto case TIME_DEL: 237132451Sroberto pp->leap = LEAP_DELSECOND; 238132451Sroberto peer->stratum = pp->stratum; 239132451Sroberto break; 24054359Sroberto 241132451Sroberto default: 242132451Sroberto pp->leap = LEAP_NOTINSYNC; 243132451Sroberto peer->stratum = STRATUM_UNSPEC; 24454359Sroberto } 245132451Sroberto pp->disp = 0; 246132451Sroberto pp->jitter = 0; 247132451Sroberto#else /* KERNEL_PLL LOCKCLOCK */ 248132451Sroberto pp->leap = LEAP_NOWARNING; 249132451Sroberto pp->disp = DISPERSION; 250132451Sroberto pp->jitter = 0; 251132451Sroberto#endif /* KERNEL_PLL LOCKCLOCK */ 252106424Sroberto pp->lastref = pp->lastrec; 25354359Sroberto refclock_receive(peer); 25454359Sroberto pp->fudgetime1 = 0; 25554359Sroberto} 256106163Sroberto#else 257106163Srobertoint refclock_local_bs; 25854359Sroberto#endif /* REFCLOCK */ 259