1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) David L. Mills 1993, 1994 8 * 9 * Permission to use, copy, modify, and distribute this software and its 10 * documentation for any purpose and without fee is hereby granted, provided 11 * that the above copyright notice appears in all copies and that both the 12 * copyright notice and this permission notice appear in supporting 13 * documentation, and that the name University of Delaware not be used in 14 * advertising or publicity pertaining to distribution of the software 15 * without specific, written prior permission. The University of Delaware 16 * makes no representations about the suitability this software for any 17 * purpose. It is provided "as is" without express or implied warranty. 18 */ 19 20 #pragma ident "%Z%%M% %I% %E% SMI" 21 22 /* 23 * Modification history kern_ntptime.c 24 * 25 * 24 Sep 94 David L. Mills 26 * Tightened code at exits. 27 * 28 * 24 Mar 94 David L. Mills 29 * Revised syscall interface to include new variables for PPS 30 * time discipline. 31 * 32 * 14 Feb 94 David L. Mills 33 * Added code for external clock 34 * 35 * 28 Nov 93 David L. Mills 36 * Revised frequency scaling to conform with adjusted parameters 37 * 38 * 17 Sep 93 David L. Mills 39 * Created file 40 */ 41 /* 42 * ntp_gettime(), ntp_adjtime() - precision time interface 43 * 44 * These routines consitute the Network Time Protocol (NTP) interfaces 45 * for user and daemon application programs. The ntp_gettime() routine 46 * provides the time, maximum error (synch distance) and estimated error 47 * (dispersion) to client user application programs. The ntp_adjtime() 48 * routine is used by the NTP daemon to adjust the system clock to an 49 * externally derived time. The time offset and related variables set by 50 * this routine are used by clock() to adjust the phase and 51 * frequency of the phase-lock loop which controls the system clock. 52 */ 53 #include <sys/param.h> 54 #include <sys/user.h> 55 #include <sys/vnode.h> 56 #include <sys/proc.h> 57 #include <sys/time.h> 58 #include <sys/systm.h> 59 #include <sys/kmem.h> 60 #include <sys/cmn_err.h> 61 #include <sys/cpuvar.h> 62 #include <sys/timer.h> 63 #include <sys/debug.h> 64 #include <sys/timex.h> 65 #include <sys/model.h> 66 #include <sys/policy.h> 67 68 /* 69 * ntp_gettime() - NTP user application interface 70 */ 71 int 72 ntp_gettime(struct ntptimeval *tp) 73 { 74 timestruc_t tod; 75 struct ntptimeval ntv; 76 model_t datamodel = get_udatamodel(); 77 78 gethrestime(&tod); 79 if (tod.tv_sec > TIME32_MAX) 80 return (set_errno(EOVERFLOW)); 81 ntv.time.tv_sec = tod.tv_sec; 82 ntv.time.tv_usec = tod.tv_nsec / (NANOSEC / MICROSEC); 83 ntv.maxerror = time_maxerror; 84 ntv.esterror = time_esterror; 85 86 if (datamodel == DATAMODEL_NATIVE) { 87 if (copyout(&ntv, tp, sizeof (ntv))) 88 return (set_errno(EFAULT)); 89 } else { 90 struct ntptimeval32 ntv32; 91 92 if (TIMEVAL_OVERFLOW(&ntv.time)) 93 return (set_errno(EOVERFLOW)); 94 95 TIMEVAL_TO_TIMEVAL32(&ntv32.time, &ntv.time); 96 97 ntv32.maxerror = ntv.maxerror; 98 ntv32.esterror = ntv.esterror; 99 100 if (copyout(&ntv32, tp, sizeof (ntv32))) 101 return (set_errno(EFAULT)); 102 } 103 104 /* 105 * Status word error decode. If any of these conditions 106 * occur, an error is returned, instead of the status 107 * word. Most applications will care only about the fact 108 * the system clock may not be trusted, not about the 109 * details. 110 * 111 * Hardware or software error 112 */ 113 if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) || 114 /* 115 * PPS signal lost when either time or frequency 116 * synchronization requested 117 */ 118 (time_status & (STA_PPSFREQ | STA_PPSTIME) && 119 !(time_status & STA_PPSSIGNAL)) || 120 121 /* 122 * PPS jitter exceeded when time synchronization 123 * requested 124 */ 125 (time_status & STA_PPSTIME && time_status & STA_PPSJITTER) || 126 127 /* 128 * PPS wander exceeded or calibration error when 129 * frequency synchronization requested 130 */ 131 (time_status & STA_PPSFREQ && time_status & 132 (STA_PPSWANDER | STA_PPSERROR))) 133 return (TIME_ERROR); 134 135 return (time_state); 136 } 137 138 /* 139 * ntp_adjtime() - NTP daemon application interface 140 */ 141 int 142 ntp_adjtime(struct timex *tp) 143 { 144 struct timex ntv; 145 int modes; 146 147 if (copyin(tp, &ntv, sizeof (ntv))) 148 return (set_errno(EFAULT)); 149 150 /* 151 * Update selected clock variables - only privileged users can 152 * change anything. Note that there is no error checking here on 153 * the assumption privileged users know what they're doing. 154 */ 155 modes = ntv.modes; 156 157 if (modes != 0 && secpolicy_settime(CRED()) != 0) 158 return (set_errno(EPERM)); 159 160 if (ntv.constant < 0 || ntv.constant > 30) 161 return (set_errno(EINVAL)); 162 163 mutex_enter(&tod_lock); 164 if (modes & MOD_MAXERROR) 165 time_maxerror = ntv.maxerror; 166 if (modes & MOD_ESTERROR) 167 time_esterror = ntv.esterror; 168 if (modes & MOD_STATUS) { 169 time_status &= STA_RONLY; 170 time_status |= ntv.status & ~STA_RONLY; 171 } 172 if (modes & MOD_TIMECONST) 173 time_constant = ntv.constant; 174 if (modes & MOD_OFFSET) 175 clock_update(ntv.offset); 176 if (modes & MOD_FREQUENCY) 177 time_freq = ntv.freq - pps_freq; 178 /* 179 * Retrieve all clock variables 180 */ 181 ntv.offset = time_offset / SCALE_UPDATE; 182 ntv.freq = time_freq + pps_freq; 183 ntv.maxerror = time_maxerror; 184 ntv.esterror = time_esterror; 185 ntv.status = time_status; 186 ntv.constant = time_constant; 187 ntv.precision = time_precision; 188 ntv.tolerance = time_tolerance; 189 ntv.shift = pps_shift; 190 ntv.ppsfreq = pps_freq; 191 ntv.jitter = pps_jitter >> PPS_AVG; 192 ntv.stabil = pps_stabil; 193 ntv.calcnt = pps_calcnt; 194 ntv.errcnt = pps_errcnt; 195 ntv.jitcnt = pps_jitcnt; 196 ntv.stbcnt = pps_stbcnt; 197 mutex_exit(&tod_lock); 198 199 if (copyout(&ntv, tp, sizeof (ntv))) 200 return (set_errno(EFAULT)); 201 202 /* 203 * Status word error decode. See comments in 204 * ntp_gettime() routine. 205 */ 206 if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) || 207 (time_status & (STA_PPSFREQ | STA_PPSTIME) && 208 !(time_status & STA_PPSSIGNAL)) || 209 (time_status & STA_PPSTIME && 210 time_status & STA_PPSJITTER) || 211 (time_status & STA_PPSFREQ && 212 time_status & (STA_PPSWANDER | STA_PPSERROR))) 213 return (TIME_ERROR); 214 215 return (time_state); 216 } 217