xref: /dragonfly/usr.sbin/dntpd/client.h (revision 279dd846)
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/client.h,v 1.7 2007/06/25 21:33:36 dillon Exp $
35  */
36 
37 struct server_info {
38 	int fd;			/* udp descriptor */
39 	int server_state;	/* -1 (no dns), 0 (dns good), or 1 (pkt good) */
40 	int server_insane;	/* insanity check */
41 	int poll_sleep;		/* countdown for poll (in seconds) */
42 	int poll_mode;		/* mode of operation */
43 	int poll_count;		/* number of polls in current mode */
44 	int poll_failed;	/* count of NTP failures */
45 	struct sockaddr *sam; 	/* udp connection info */
46 	struct sockaddr_storage sam_st; 	/* udp connection info (stor) */
47 	char *target;		/* target hostname or IP (string) */
48 	char *ipstr;		/* IP string */
49 
50 	/*
51 	 * A second linear regression playing hopskip with the first.  This
52 	 * is maintained by the check function.
53 	 */
54 	struct server_info *altinfo;
55 
56 	/*
57 	 * Linear regression accumulator
58 	 *
59 	 * note: the starting base time is where all corrections get applied
60 	 * to eventually.  The linear regression makes a relative microseconds
61 	 * calculation between the current base time and the starting base
62 	 * time to figure out what corrections the system has made to the
63 	 * clock.
64 	 */
65 	struct timeval lin_tv;	/* starting real time */
66 	struct timeval lin_btv;	/* starting base time */
67 	double lin_count;	/* samples	*/
68 	double lin_sumx;	/* sum(x)	*/
69 	double lin_sumy;	/* sum(y)	*/
70 	double lin_sumxy;	/* sum(x*y)	*/
71 	double lin_sumx2;	/* sum(x^2) 	*/
72 	double lin_sumy2;	/* sum(y^2) 	*/
73 
74 	/*
75 	 * Offsets are accumulated for a straight average.  When a
76 	 * correction is made we have to reset the averaging code
77 	 * or follow-up corrections will oscillate wildly because
78 	 * the new offsets simply cannot compete with the dozens
79 	 * of previously polls in the sum.
80 	 */
81 	double lin_sumoffset;	/* sum of compensated offsets */
82 	double lin_sumoffset2;	/* sum of compensated offsets^2 */
83 	double lin_countoffset;	/* count is reset after a correction is made */
84 
85 	/*
86 	 * Cached results
87 	 */
88 	double lin_cache_slope;	/* (freq calculations) */
89 	double lin_cache_yint;	/* (freq calculations) */
90 	double lin_cache_corr;	/* (freq calculations) */
91 	double lin_cache_stddev; /* (offset calculations) */
92 
93 	double lin_cache_offset; /* last sampled offset (NOT an average) */
94 	double lin_cache_freq;	/* last frequency correction (s/s) */
95 };
96 
97 /*
98  * Polling modes and max polls for specific modes.  Note that the polling
99  * mode basically just effects the polling rate.  It does not effect the
100  * linear regression.
101  */
102 #define POLL_FIXED	0	/* fixed internal (nom_sleep_opt seconds) */
103 #define POLL_STARTUP	1	/* startup poll for offset adjust (min) */
104 #define POLL_ACQUIRE	2	/* acquisition for frequency adjust (nom) */
105 #define POLL_MAINTAIN	3	/* maintainance mode (max) */
106 #define POLL_FAILED	4	/* failure state (nom) */
107 
108 #define POLL_STARTUP_MAX	6	/* max polls in this mode */
109 #define POLL_ACQUIRE_MAX	16	/* max polls in this mode */
110 #define POLL_FAIL_RESET		3	/* reset the regression after 3 fails */
111 #define POLL_RECOVERY_RESTART	10	/* ->ACQ vs ->STARTUP after recovery */
112 
113 /*
114  * We start a second linear regression a LIN_RESTART / 2 and it
115  * replaces the first one (and we start a third) at LIN_RESTART.
116  */
117 #define LIN_RESTART	30
118 
119 /*
120  * A course correction is made if the time gets more then 2 minutes
121  * off.
122  */
123 #define COURSE_OFFSET_CORRECTION_LIMIT	120.0
124 
125 typedef struct server_info *server_info_t;
126 
127 void client_init(void);
128 int client_main(struct server_info **info_ary, int count);
129 void client_poll(server_info_t info, int poll_interval,
130 		  int calc_offset_correction);
131 void client_check(struct server_info **check,
132 		  struct server_info **best_off,
133 		  struct server_info **best_freq);
134 void client_check_duplicate_ips(struct server_info **info_ary, int count);
135 void client_manage_polling_mode(struct server_info *info, int *didreconnect);
136 void client_setserverstate(server_info_t info, int state, const char *str);
137 
138 void lin_regress(server_info_t info,
139 		 struct timeval *ltv, struct timeval *lbtv,
140 		 double offset, int calc_offset_correction);
141 void lin_reset(server_info_t info);
142 void lin_resetalloffsets(struct server_info **info_ary, int count);
143 void lin_resetoffsets(server_info_t info);
144 
145