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