Change client_check() to calculate the best offset and the best frequency
[dragonfly.git] / usr.sbin / dntpd / system.c
1 /*
2  * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  * 
34  * $DragonFly: src/usr.sbin/dntpd/system.c,v 1.1 2005/04/24 02:36:50 dillon Exp $
35  */
36
37 #include "defs.h"
38 #include <sys/sysctl.h>
39
40 void
41 sysntp_getbasetime(struct timeval *tvp)
42 {
43     struct timespec ts;
44     int error;
45     int ts_size;
46
47     ts_size = sizeof(ts);
48     error = sysctlbyname("kern.basetime", &ts, &ts_size, NULL, 0);
49     if (error < 0) {
50         logerr("sysctlbyname(\"kern.basetime\") failed, cannot continue");
51         exit(1);
52     }
53     ts_to_tv(&ts, tvp);
54 }
55
56 /*
57  * The offset error is passed as seconds per second.
58  *
59  * The 64 bit delta is calculated as nanoseconds per second.  Since we are
60  * passed an offset error we must negate the result to correct the error.
61  *
62  * Because offset corrections skew the accuracy of the clock while the
63  * correction is in progress, we do not want to use them once we are
64  * reasonably well synchronized.  We can make small offset corrections
65  * by shifting the frequency a bit.  XXX
66  */
67 double
68 sysntp_correct_offset(double offset)
69 {
70     int64_t delta;
71
72     /*
73      * Course correction
74      */
75     if (offset < -0.001 || offset > 0.001) {
76         if (debug_opt)
77             fprintf(stderr, "issuing offset adjustment: %7.6f\n", -offset);
78         delta = -(int64_t)(offset * 1.0E+9);
79         sysctlbyname("kern.ntp.delta", NULL, 0, &delta, sizeof(delta));
80         return(0.0);
81     }
82
83     /*
84      * Fine correction - do it by adjusting the frequency.
85      * XXX
86      */
87     return(0.0);
88 }
89
90 /*
91  * freq is passed as seconds per second.
92  *
93  * The calculated 64 bit correction is nanoseconds per second shifted
94  * left 32.
95  *
96  * Frequency errors greater then 1 second per second will not be corrected.
97  * It doesn't hurt to continue correcting the frequency.
98  */
99 void
100 sysntp_correct_freq(double freq)
101 {
102     int64_t delta;
103
104     if (freq >= -1.0 && freq < 1.0) {
105         if (debug_opt) {
106             fprintf(stderr, "issuing frequency adjustment: %6.3fppm\n", 
107                     -freq * 1000000.0);
108         }
109         delta = -((int64_t)(freq * 1.0E+9) << 32);
110         sysctlbyname("kern.ntp.permanent", NULL, 0, &delta, sizeof(delta));
111     }
112 }
113