1 | /* |
---|
2 | * ntp_request.c - respond to information requests |
---|
3 | */ |
---|
4 | #ifdef HAVE_CONFIG_H |
---|
5 | #include <config.h> |
---|
6 | #endif |
---|
7 | |
---|
8 | #include <sys/types.h> |
---|
9 | #include <stdio.h> |
---|
10 | #include <signal.h> |
---|
11 | #include <errno.h> |
---|
12 | #include <sys/time.h> |
---|
13 | |
---|
14 | #include "ntpd.h" |
---|
15 | #include "ntp_io.h" |
---|
16 | #include "ntp_request.h" |
---|
17 | #include "ntp_control.h" |
---|
18 | #include "ntp_refclock.h" |
---|
19 | #include "ntp_if.h" |
---|
20 | #include "ntp_stdlib.h" |
---|
21 | |
---|
22 | #ifdef KERNEL_PLL |
---|
23 | # include <sys/timex.h> |
---|
24 | # ifdef NTP_SYSCALLS_STD |
---|
25 | # define ntp_gettime(t) syscall(SYS_ntp_gettime, (t)) |
---|
26 | # define ntp_adjtime(t) syscall(SYS_ntp_adjtime, (t)) |
---|
27 | # else /* NOT NTP_SYSCALLS_STD */ |
---|
28 | # ifdef HAVE___NTP_GETTIME |
---|
29 | # define ntp_gettime(t) __ntp_gettime((t)) |
---|
30 | # endif |
---|
31 | # ifdef HAVE___ADJTIMEX |
---|
32 | # define ntp_adjtime(t) __adjtimex((t)) |
---|
33 | # endif |
---|
34 | # endif /* NOT NTP_SYSCALLS_STD */ |
---|
35 | #endif /* KERNEL_PLL */ |
---|
36 | |
---|
37 | /* |
---|
38 | * Structure to hold request procedure information |
---|
39 | */ |
---|
40 | #define NOAUTH 0 |
---|
41 | #define AUTH 1 |
---|
42 | |
---|
43 | #define NO_REQUEST (-1) |
---|
44 | |
---|
45 | struct req_proc { |
---|
46 | short request_code; /* defined request code */ |
---|
47 | short needs_auth; /* true when authentication needed */ |
---|
48 | short sizeofitem; /* size of request data item */ |
---|
49 | void (*handler) P((struct sockaddr_in *, struct interface *, |
---|
50 | struct req_pkt *)); /* routine to handle request */ |
---|
51 | }; |
---|
52 | |
---|
53 | /* |
---|
54 | * Universal request codes |
---|
55 | */ |
---|
56 | static struct req_proc univ_codes[] = { |
---|
57 | { NO_REQUEST, NOAUTH, 0, 0 } |
---|
58 | }; |
---|
59 | |
---|
60 | static void req_ack P((struct sockaddr_in *, struct interface *, struct req_pkt *, int)); |
---|
61 | static char * prepare_pkt P((struct sockaddr_in *, struct interface *, struct req_pkt *, u_int)); |
---|
62 | static char * more_pkt P((void)); |
---|
63 | static void flush_pkt P((void)); |
---|
64 | static void peer_list P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
65 | static void peer_list_sum P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
66 | static void peer_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
67 | static void peer_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
68 | static void sys_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
69 | static void sys_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
70 | static void mem_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
71 | static void io_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
72 | static void timer_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
73 | static void loop_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
74 | static void do_conf P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
75 | static void do_unconf P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
76 | static void set_sys_flag P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
77 | static void clr_sys_flag P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
78 | static void setclr_flags P((struct sockaddr_in *, struct interface *, struct req_pkt *, u_long)); |
---|
79 | static void list_restrict P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
80 | static void do_resaddflags P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
81 | static void do_ressubflags P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
82 | static void do_unrestrict P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
83 | static void do_restrict P((struct sockaddr_in *, struct interface *, struct req_pkt *, int)); |
---|
84 | static void mon_getlist_0 P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
85 | static void mon_getlist_1 P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
86 | static void reset_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
87 | static void reset_peer P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
88 | static void do_key_reread P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
89 | static void trust_key P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
90 | static void untrust_key P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
91 | static void do_trustkey P((struct sockaddr_in *, struct interface *, struct req_pkt *, int)); |
---|
92 | static void get_auth_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
93 | static void reset_auth_stats P((void)); |
---|
94 | static void req_get_traps P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
95 | static void req_set_trap P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
96 | static void req_clr_trap P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
97 | static void do_setclr_trap P((struct sockaddr_in *, struct interface *, struct req_pkt *, int)); |
---|
98 | static void set_request_keyid P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
99 | static void set_control_keyid P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
100 | static void get_ctl_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
101 | static void get_leap_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
102 | #ifdef KERNEL_PLL |
---|
103 | static void get_kernel_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
104 | #endif /* KERNEL_PLL */ |
---|
105 | #ifdef REFCLOCK |
---|
106 | static void get_clock_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
107 | static void set_clock_fudge P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
108 | #endif /* REFCLOCK */ |
---|
109 | #ifdef REFCLOCK |
---|
110 | static void get_clkbug_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); |
---|
111 | #endif /* REFCLOCK */ |
---|
112 | |
---|
113 | /* |
---|
114 | * Xntpd request codes |
---|
115 | */ |
---|
116 | static struct req_proc xntp_codes[] = { |
---|
117 | { REQ_PEER_LIST, NOAUTH, 0, peer_list }, |
---|
118 | { REQ_PEER_LIST_SUM, NOAUTH, 0, peer_list_sum }, |
---|
119 | { REQ_PEER_INFO, NOAUTH, sizeof(struct info_peer_list), peer_info }, |
---|
120 | { REQ_PEER_STATS, NOAUTH, sizeof(struct info_peer_list), peer_stats }, |
---|
121 | { REQ_SYS_INFO, NOAUTH, 0, sys_info }, |
---|
122 | { REQ_SYS_STATS, NOAUTH, 0, sys_stats }, |
---|
123 | { REQ_IO_STATS, NOAUTH, 0, io_stats }, |
---|
124 | { REQ_MEM_STATS, NOAUTH, 0, mem_stats }, |
---|
125 | { REQ_LOOP_INFO, NOAUTH, 0, loop_info }, |
---|
126 | { REQ_TIMER_STATS, NOAUTH, 0, timer_stats }, |
---|
127 | { REQ_CONFIG, AUTH, sizeof(struct conf_peer), do_conf }, |
---|
128 | { REQ_UNCONFIG, AUTH, sizeof(struct conf_unpeer), do_unconf }, |
---|
129 | { REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), set_sys_flag }, |
---|
130 | { REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), clr_sys_flag }, |
---|
131 | { REQ_GET_RESTRICT, NOAUTH, 0, list_restrict }, |
---|
132 | { REQ_RESADDFLAGS, AUTH, sizeof(struct conf_restrict), do_resaddflags }, |
---|
133 | { REQ_RESSUBFLAGS, AUTH, sizeof(struct conf_restrict), do_ressubflags }, |
---|
134 | { REQ_UNRESTRICT, AUTH, sizeof(struct conf_restrict), do_unrestrict }, |
---|
135 | { REQ_MON_GETLIST, NOAUTH, 0, mon_getlist_0 }, |
---|
136 | { REQ_MON_GETLIST_1, NOAUTH, 0, mon_getlist_1 }, |
---|
137 | { REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), reset_stats }, |
---|
138 | { REQ_RESET_PEER, AUTH, sizeof(struct conf_unpeer), reset_peer }, |
---|
139 | { REQ_REREAD_KEYS, AUTH, 0, do_key_reread }, |
---|
140 | { REQ_TRUSTKEY, AUTH, sizeof(u_int32), trust_key }, |
---|
141 | { REQ_UNTRUSTKEY, AUTH, sizeof(u_int32), untrust_key }, |
---|
142 | { REQ_AUTHINFO, NOAUTH, 0, get_auth_info }, |
---|
143 | { REQ_TRAPS, NOAUTH, 0, req_get_traps }, |
---|
144 | { REQ_ADD_TRAP, AUTH, sizeof(struct conf_trap), req_set_trap }, |
---|
145 | { REQ_CLR_TRAP, AUTH, sizeof(struct conf_trap), req_clr_trap }, |
---|
146 | { REQ_REQUEST_KEY, AUTH, sizeof(u_int32), set_request_keyid }, |
---|
147 | { REQ_CONTROL_KEY, AUTH, sizeof(u_int32), set_control_keyid }, |
---|
148 | { REQ_GET_CTLSTATS, NOAUTH, 0, get_ctl_stats }, |
---|
149 | { REQ_GET_LEAPINFO, NOAUTH, 0, get_leap_info }, |
---|
150 | #ifdef KERNEL_PLL |
---|
151 | { REQ_GET_KERNEL, NOAUTH, 0, get_kernel_info }, |
---|
152 | #endif |
---|
153 | #ifdef REFCLOCK |
---|
154 | { REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32), get_clock_info }, |
---|
155 | { REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge), set_clock_fudge }, |
---|
156 | { REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), get_clkbug_info }, |
---|
157 | #endif |
---|
158 | { NO_REQUEST, NOAUTH, 0, 0 } |
---|
159 | }; |
---|
160 | |
---|
161 | |
---|
162 | /* |
---|
163 | * Authentication keyid used to authenticate requests. Zero means we |
---|
164 | * don't allow writing anything. |
---|
165 | */ |
---|
166 | u_int32 info_auth_keyid; |
---|
167 | |
---|
168 | |
---|
169 | /* |
---|
170 | * Statistic counters to keep track of requests and responses. |
---|
171 | */ |
---|
172 | u_long numrequests; /* number of requests we've received */ |
---|
173 | u_long numresppkts; /* number of resp packets sent with data */ |
---|
174 | |
---|
175 | u_long errorcounter[INFO_ERR_AUTH+1]; /* lazy way to count errors, indexed */ |
---|
176 | /* by the error code */ |
---|
177 | |
---|
178 | /* |
---|
179 | * Imported from the I/O module |
---|
180 | */ |
---|
181 | extern struct interface *any_interface; |
---|
182 | |
---|
183 | /* |
---|
184 | * Imported from the main routines |
---|
185 | */ |
---|
186 | extern int debug; |
---|
187 | |
---|
188 | /* |
---|
189 | * Imported from the timer module |
---|
190 | */ |
---|
191 | extern u_long current_time; |
---|
192 | |
---|
193 | /* |
---|
194 | * Imported from ntp_loopfilter.c |
---|
195 | */ |
---|
196 | extern int pll_control; |
---|
197 | extern int pll_enable; |
---|
198 | extern int pps_control; |
---|
199 | extern int pps_enable; |
---|
200 | |
---|
201 | /* |
---|
202 | * Imported from ntp_monitor.c |
---|
203 | */ |
---|
204 | extern int mon_enabled; |
---|
205 | |
---|
206 | /* |
---|
207 | * Imported from ntp_util.c |
---|
208 | */ |
---|
209 | extern int stats_control; |
---|
210 | |
---|
211 | extern struct peer *peer_hash[]; |
---|
212 | extern struct peer *sys_peer; |
---|
213 | |
---|
214 | #ifdef NTP_SYSCALLS_STD |
---|
215 | # ifdef DECL_SYSCALL |
---|
216 | extern int syscall P((int, void *, ...)); |
---|
217 | # endif /* DECL_SYSCALL */ |
---|
218 | #endif /* NTP_SYSCALLS_STD */ |
---|
219 | |
---|
220 | /* |
---|
221 | * A hack. To keep the authentication module clear of xntp-ism's, we |
---|
222 | * include a time reset variable for its stats here. |
---|
223 | */ |
---|
224 | static u_long auth_timereset; |
---|
225 | |
---|
226 | /* |
---|
227 | * Response packet used by these routines. Also some state information |
---|
228 | * so that we can handle packet formatting within a common set of |
---|
229 | * subroutines. Note we try to enter data in place whenever possible, |
---|
230 | * but the need to set the more bit correctly means we occasionally |
---|
231 | * use the extra buffer and copy. |
---|
232 | */ |
---|
233 | static struct resp_pkt rpkt; |
---|
234 | static int seqno; |
---|
235 | static int nitems; |
---|
236 | static int itemsize; |
---|
237 | static int databytes; |
---|
238 | static char exbuf[RESP_DATA_SIZE]; |
---|
239 | static int usingexbuf; |
---|
240 | static struct sockaddr_in *toaddr; |
---|
241 | static struct interface *frominter; |
---|
242 | |
---|
243 | /* |
---|
244 | * init_request - initialize request data |
---|
245 | */ |
---|
246 | void |
---|
247 | init_request() |
---|
248 | { |
---|
249 | int i; |
---|
250 | |
---|
251 | numrequests = 0; |
---|
252 | numresppkts = 0; |
---|
253 | auth_timereset = 0; |
---|
254 | info_auth_keyid = 0; /* by default, can't do this */ |
---|
255 | |
---|
256 | for (i = 0; i < sizeof(errorcounter)/sizeof(errorcounter[0]); i++) |
---|
257 | errorcounter[i] = 0; |
---|
258 | } |
---|
259 | |
---|
260 | |
---|
261 | /* |
---|
262 | * req_ack - acknowledge request with no data |
---|
263 | */ |
---|
264 | static void |
---|
265 | req_ack(srcadr, inter, inpkt, errcode) |
---|
266 | struct sockaddr_in *srcadr; |
---|
267 | struct interface *inter; |
---|
268 | struct req_pkt *inpkt; |
---|
269 | int errcode; |
---|
270 | { |
---|
271 | /* |
---|
272 | * fill in the fields |
---|
273 | */ |
---|
274 | rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0); |
---|
275 | rpkt.auth_seq = AUTH_SEQ(0, 0); |
---|
276 | rpkt.implementation = inpkt->implementation; |
---|
277 | rpkt.request = inpkt->request; |
---|
278 | rpkt.err_nitems = ERR_NITEMS(errcode, 0); |
---|
279 | rpkt.mbz_itemsize = MBZ_ITEMSIZE(0); |
---|
280 | |
---|
281 | /* |
---|
282 | * send packet and bump counters |
---|
283 | */ |
---|
284 | sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE); |
---|
285 | errorcounter[errcode]++; |
---|
286 | } |
---|
287 | |
---|
288 | |
---|
289 | /* |
---|
290 | * prepare_pkt - prepare response packet for transmission, return pointer |
---|
291 | * to storage for data item. |
---|
292 | */ |
---|
293 | static char * |
---|
294 | prepare_pkt(srcadr, inter, pkt, structsize) |
---|
295 | struct sockaddr_in *srcadr; |
---|
296 | struct interface *inter; |
---|
297 | struct req_pkt *pkt; |
---|
298 | u_int structsize; |
---|
299 | { |
---|
300 | #ifdef DEBUG |
---|
301 | if (debug > 3) |
---|
302 | printf("request: preparing pkt\n"); |
---|
303 | #endif |
---|
304 | |
---|
305 | /* |
---|
306 | * Fill in the implementation, reqest and itemsize fields |
---|
307 | * since these won't change. |
---|
308 | */ |
---|
309 | rpkt.implementation = pkt->implementation; |
---|
310 | rpkt.request = pkt->request; |
---|
311 | rpkt.mbz_itemsize = MBZ_ITEMSIZE(structsize); |
---|
312 | |
---|
313 | /* |
---|
314 | * Compute the static data needed to carry on. |
---|
315 | */ |
---|
316 | toaddr = srcadr; |
---|
317 | frominter = inter; |
---|
318 | seqno = 0; |
---|
319 | nitems = 0; |
---|
320 | itemsize = structsize; |
---|
321 | databytes = 0; |
---|
322 | usingexbuf = 0; |
---|
323 | |
---|
324 | /* |
---|
325 | * return the beginning of the packet buffer. |
---|
326 | */ |
---|
327 | return &rpkt.data[0]; |
---|
328 | } |
---|
329 | |
---|
330 | |
---|
331 | /* |
---|
332 | * more_pkt - return a data pointer for a new item. |
---|
333 | */ |
---|
334 | static char * |
---|
335 | more_pkt() |
---|
336 | { |
---|
337 | /* |
---|
338 | * If we were using the extra buffer, send the packet. |
---|
339 | */ |
---|
340 | if (usingexbuf) { |
---|
341 | #ifdef DEBUG |
---|
342 | if (debug > 2) |
---|
343 | printf("request: sending pkt\n"); |
---|
344 | #endif |
---|
345 | rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT); |
---|
346 | rpkt.auth_seq = AUTH_SEQ(0, seqno); |
---|
347 | rpkt.err_nitems = htons((u_short)nitems); |
---|
348 | sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt, |
---|
349 | RESP_HEADER_SIZE+databytes); |
---|
350 | numresppkts++; |
---|
351 | |
---|
352 | /* |
---|
353 | * Copy data out of exbuf into the packet. |
---|
354 | */ |
---|
355 | memmove(&rpkt.data[0], exbuf, itemsize); |
---|
356 | seqno++; |
---|
357 | databytes = 0; |
---|
358 | nitems = 0; |
---|
359 | usingexbuf = 0; |
---|
360 | } |
---|
361 | |
---|
362 | databytes += itemsize; |
---|
363 | nitems++; |
---|
364 | if (databytes + itemsize <= RESP_DATA_SIZE) { |
---|
365 | #ifdef DEBUG |
---|
366 | if (debug > 3) |
---|
367 | printf("request: giving him more data\n"); |
---|
368 | #endif |
---|
369 | /* |
---|
370 | * More room in packet. Give him the |
---|
371 | * next address. |
---|
372 | */ |
---|
373 | return &rpkt.data[databytes]; |
---|
374 | } else { |
---|
375 | /* |
---|
376 | * No room in packet. Give him the extra |
---|
377 | * buffer unless this was the last in the sequence. |
---|
378 | */ |
---|
379 | #ifdef DEBUG |
---|
380 | if (debug > 3) |
---|
381 | printf("request: into extra buffer\n"); |
---|
382 | #endif |
---|
383 | if (seqno == MAXSEQ) |
---|
384 | return (char *)0; |
---|
385 | else { |
---|
386 | usingexbuf = 1; |
---|
387 | return exbuf; |
---|
388 | } |
---|
389 | } |
---|
390 | } |
---|
391 | |
---|
392 | |
---|
393 | /* |
---|
394 | * flush_pkt - we're done, return remaining information. |
---|
395 | */ |
---|
396 | static void |
---|
397 | flush_pkt() |
---|
398 | { |
---|
399 | #ifdef DEBUG |
---|
400 | if (debug > 2) |
---|
401 | printf("request: flushing packet, %d items\n", nitems); |
---|
402 | #endif |
---|
403 | /* |
---|
404 | * Must send the last packet. If nothing in here and nothing |
---|
405 | * has been sent, send an error saying no data to be found. |
---|
406 | */ |
---|
407 | if (seqno == 0 && nitems == 0) |
---|
408 | req_ack(toaddr, frominter, (struct req_pkt *)&rpkt, |
---|
409 | INFO_ERR_NODATA); |
---|
410 | else { |
---|
411 | rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0); |
---|
412 | rpkt.auth_seq = AUTH_SEQ(0, seqno); |
---|
413 | rpkt.err_nitems = htons((u_short)nitems); |
---|
414 | sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt, |
---|
415 | RESP_HEADER_SIZE+databytes); |
---|
416 | numresppkts++; |
---|
417 | } |
---|
418 | } |
---|
419 | |
---|
420 | |
---|
421 | |
---|
422 | /* |
---|
423 | * process_private - process private mode (7) packets |
---|
424 | */ |
---|
425 | void |
---|
426 | process_private(rbufp, mod_okay) |
---|
427 | struct recvbuf *rbufp; |
---|
428 | int mod_okay; |
---|
429 | { |
---|
430 | struct req_pkt *inpkt; |
---|
431 | struct sockaddr_in *srcadr; |
---|
432 | struct interface *inter; |
---|
433 | struct req_proc *proc; |
---|
434 | |
---|
435 | /* |
---|
436 | * Initialize pointers, for convenience |
---|
437 | */ |
---|
438 | inpkt = (struct req_pkt *)&rbufp->recv_pkt; |
---|
439 | srcadr = &rbufp->recv_srcadr; |
---|
440 | inter = rbufp->dstadr; |
---|
441 | |
---|
442 | #ifdef DEBUG |
---|
443 | if (debug > 2) |
---|
444 | printf("prepare_pkt: impl %d req %d\n", |
---|
445 | inpkt->implementation, inpkt->request); |
---|
446 | #endif |
---|
447 | |
---|
448 | /* |
---|
449 | * Do some sanity checks on the packet. Return a format |
---|
450 | * error if it fails. |
---|
451 | */ |
---|
452 | if (ISRESPONSE(inpkt->rm_vn_mode) |
---|
453 | || ISMORE(inpkt->rm_vn_mode) |
---|
454 | || INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION |
---|
455 | || INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION |
---|
456 | || INFO_SEQ(inpkt->auth_seq) != 0 |
---|
457 | || INFO_ERR(inpkt->err_nitems) != 0 |
---|
458 | || INFO_MBZ(inpkt->mbz_itemsize) != 0 |
---|
459 | || rbufp->recv_length > REQ_LEN_MAC |
---|
460 | || rbufp->recv_length < REQ_LEN_NOMAC) { |
---|
461 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
462 | return; |
---|
463 | } |
---|
464 | |
---|
465 | |
---|
466 | /* |
---|
467 | * Get the appropriate procedure list to search. |
---|
468 | */ |
---|
469 | if (inpkt->implementation == IMPL_UNIV) |
---|
470 | proc = univ_codes; |
---|
471 | else if (inpkt->implementation == IMPL_XNTPD) |
---|
472 | proc = xntp_codes; |
---|
473 | else { |
---|
474 | req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL); |
---|
475 | return; |
---|
476 | } |
---|
477 | |
---|
478 | |
---|
479 | /* |
---|
480 | * Search the list for the request codes. If it isn't one |
---|
481 | * we know, return an error. |
---|
482 | */ |
---|
483 | while (proc->request_code != NO_REQUEST) { |
---|
484 | if (proc->request_code == (short) inpkt->request) |
---|
485 | break; |
---|
486 | proc++; |
---|
487 | } |
---|
488 | if (proc->request_code == NO_REQUEST) { |
---|
489 | req_ack(srcadr, inter, inpkt, INFO_ERR_REQ); |
---|
490 | return; |
---|
491 | } |
---|
492 | |
---|
493 | #ifdef DEBUG |
---|
494 | if (debug > 3) |
---|
495 | printf("found request in tables\n"); |
---|
496 | #endif |
---|
497 | |
---|
498 | /* |
---|
499 | * If we need to authenticate, do so. Note that an |
---|
500 | * authenticatable packet must include a mac field, must |
---|
501 | * have used key info_auth_keyid and must have included |
---|
502 | * a time stamp in the appropriate field. The time stamp |
---|
503 | * must be within INFO_TS_MAXSKEW of the receive |
---|
504 | * time stamp. |
---|
505 | */ |
---|
506 | if (proc->needs_auth) { |
---|
507 | l_fp ftmp; |
---|
508 | |
---|
509 | /* |
---|
510 | * If this guy is restricted from doing this, don't let him |
---|
511 | * If wrong key was used, or packet doesn't have mac, return. |
---|
512 | */ |
---|
513 | if (!INFO_IS_AUTH(inpkt->auth_seq) || info_auth_keyid == 0 |
---|
514 | || ntohl(inpkt->keyid) != info_auth_keyid) { |
---|
515 | #ifdef DEBUG |
---|
516 | if (debug > 4) |
---|
517 | printf("failed auth %d info_auth_keyid %lu pkt keyid %lu\n", |
---|
518 | INFO_IS_AUTH(inpkt->auth_seq), |
---|
519 | (u_long)info_auth_keyid, |
---|
520 | (u_long)ntohl(inpkt->keyid)); |
---|
521 | #endif |
---|
522 | req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); |
---|
523 | return; |
---|
524 | } |
---|
525 | if (rbufp->recv_length > REQ_LEN_MAC) { |
---|
526 | #ifdef DEBUG |
---|
527 | if (debug > 4) |
---|
528 | printf("bad pkt length %d\n", |
---|
529 | rbufp->recv_length); |
---|
530 | #endif |
---|
531 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
532 | return; |
---|
533 | } |
---|
534 | if (!mod_okay || !authhavekey(info_auth_keyid)) { |
---|
535 | #ifdef DEBUG |
---|
536 | if (debug > 4) |
---|
537 | printf("failed auth mod_okay %d\n", mod_okay); |
---|
538 | #endif |
---|
539 | req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); |
---|
540 | return; |
---|
541 | } |
---|
542 | |
---|
543 | /* |
---|
544 | * calculate absolute time difference between xmit time stamp |
---|
545 | * and receive time stamp. If too large, too bad. |
---|
546 | */ |
---|
547 | NTOHL_FP(&inpkt->tstamp, &ftmp); |
---|
548 | L_SUB(&ftmp, &rbufp->recv_time); |
---|
549 | if (L_ISNEG(&ftmp)) |
---|
550 | L_NEG(&ftmp); |
---|
551 | |
---|
552 | if (ftmp.l_ui >= INFO_TS_MAXSKEW_UI) { |
---|
553 | /* |
---|
554 | * He's a loser. Tell him. |
---|
555 | */ |
---|
556 | req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); |
---|
557 | return; |
---|
558 | } |
---|
559 | |
---|
560 | /* |
---|
561 | * So far so good. See if decryption works out okay. |
---|
562 | */ |
---|
563 | if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt, |
---|
564 | REQ_LEN_NOMAC)) { |
---|
565 | req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); |
---|
566 | return; |
---|
567 | } |
---|
568 | } |
---|
569 | |
---|
570 | /* |
---|
571 | * If we need data, check to see if we have some. If we |
---|
572 | * don't, check to see that there is none (picky, picky). |
---|
573 | */ |
---|
574 | if (INFO_ITEMSIZE(inpkt->mbz_itemsize) != proc->sizeofitem) { |
---|
575 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
576 | return; |
---|
577 | } |
---|
578 | if (proc->sizeofitem != 0) |
---|
579 | if (proc->sizeofitem*INFO_NITEMS(inpkt->err_nitems) |
---|
580 | > sizeof(inpkt->data)) { |
---|
581 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
582 | return; |
---|
583 | } |
---|
584 | |
---|
585 | #ifdef DEBUG |
---|
586 | if (debug > 3) |
---|
587 | printf("process_private: all okay, into handler\n"); |
---|
588 | #endif |
---|
589 | |
---|
590 | /* |
---|
591 | * Packet is okay. Call the handler to send him data. |
---|
592 | */ |
---|
593 | (proc->handler)(srcadr, inter, inpkt); |
---|
594 | } |
---|
595 | |
---|
596 | |
---|
597 | /* |
---|
598 | * peer_list - send a list of the peers |
---|
599 | */ |
---|
600 | static void |
---|
601 | peer_list(srcadr, inter, inpkt) |
---|
602 | struct sockaddr_in *srcadr; |
---|
603 | struct interface *inter; |
---|
604 | struct req_pkt *inpkt; |
---|
605 | { |
---|
606 | register struct info_peer_list *ip; |
---|
607 | register struct peer *pp; |
---|
608 | register int i; |
---|
609 | |
---|
610 | ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt, |
---|
611 | sizeof(struct info_peer_list)); |
---|
612 | for (i = 0; i < HASH_SIZE && ip != 0; i++) { |
---|
613 | pp = peer_hash[i]; |
---|
614 | while (pp != 0 && ip != 0) { |
---|
615 | ip->address = pp->srcadr.sin_addr.s_addr; |
---|
616 | ip->port = pp->srcadr.sin_port; |
---|
617 | ip->hmode = pp->hmode; |
---|
618 | ip->flags = 0; |
---|
619 | if (pp->flags & FLAG_CONFIG) |
---|
620 | ip->flags |= INFO_FLAG_CONFIG; |
---|
621 | if (pp == sys_peer) |
---|
622 | ip->flags |= INFO_FLAG_SYSPEER; |
---|
623 | if (pp->candidate != 0) |
---|
624 | ip->flags |= INFO_FLAG_SEL_CANDIDATE; |
---|
625 | if (pp->select != 0) |
---|
626 | ip->flags |= INFO_FLAG_SHORTLIST; |
---|
627 | ip = (struct info_peer_list *)more_pkt(); |
---|
628 | pp = pp->next; |
---|
629 | } |
---|
630 | } |
---|
631 | flush_pkt(); |
---|
632 | } |
---|
633 | |
---|
634 | |
---|
635 | /* |
---|
636 | * peer_list_sum - return extended peer list |
---|
637 | */ |
---|
638 | static void |
---|
639 | peer_list_sum(srcadr, inter, inpkt) |
---|
640 | struct sockaddr_in *srcadr; |
---|
641 | struct interface *inter; |
---|
642 | struct req_pkt *inpkt; |
---|
643 | { |
---|
644 | register struct info_peer_summary *ips; |
---|
645 | register struct peer *pp; |
---|
646 | register int i; |
---|
647 | |
---|
648 | #ifdef DEBUG |
---|
649 | if (debug > 2) |
---|
650 | printf("wants peer list summary\n"); |
---|
651 | #endif |
---|
652 | |
---|
653 | ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt, |
---|
654 | sizeof(struct info_peer_summary)); |
---|
655 | for (i = 0; i < HASH_SIZE && ips != 0; i++) { |
---|
656 | pp = peer_hash[i]; |
---|
657 | while (pp != 0 && ips != 0) { |
---|
658 | #ifdef DEBUG |
---|
659 | if (debug > 3) |
---|
660 | printf("sum: got one\n"); |
---|
661 | #endif |
---|
662 | ips->dstadr = (pp->processed) ? |
---|
663 | pp->cast_flags == MDF_BCAST ? |
---|
664 | pp->dstadr->bcast.sin_addr.s_addr: |
---|
665 | pp->cast_flags ? |
---|
666 | pp->dstadr->sin.sin_addr.s_addr ? |
---|
667 | pp->dstadr->sin.sin_addr.s_addr: |
---|
668 | pp->dstadr->bcast.sin_addr.s_addr: |
---|
669 | 1 : 5; |
---|
670 | ips->srcadr = pp->srcadr.sin_addr.s_addr; |
---|
671 | ips->srcport = pp->srcadr.sin_port; |
---|
672 | ips->stratum = pp->stratum; |
---|
673 | ips->hpoll = pp->hpoll; |
---|
674 | ips->ppoll = pp->ppoll; |
---|
675 | ips->reach = pp->reach; |
---|
676 | ips->flags = 0; |
---|
677 | if (pp == sys_peer) |
---|
678 | ips->flags |= INFO_FLAG_SYSPEER; |
---|
679 | if (pp->flags & FLAG_CONFIG) |
---|
680 | ips->flags |= INFO_FLAG_CONFIG; |
---|
681 | if (pp->flags & FLAG_REFCLOCK) |
---|
682 | ips->flags |= INFO_FLAG_REFCLOCK; |
---|
683 | if (pp->flags & FLAG_AUTHENABLE) |
---|
684 | ips->flags |= INFO_FLAG_AUTHENABLE; |
---|
685 | if (pp->flags & FLAG_PREFER) |
---|
686 | ips->flags |= INFO_FLAG_PREFER; |
---|
687 | if (pp->candidate != 0) |
---|
688 | ips->flags |= INFO_FLAG_SEL_CANDIDATE; |
---|
689 | if (pp->select != 0) |
---|
690 | ips->flags |= INFO_FLAG_SHORTLIST; |
---|
691 | ips->hmode = pp->hmode; |
---|
692 | ips->delay = HTONS_FP(pp->delay); |
---|
693 | HTONL_FP(&pp->offset, &ips->offset); |
---|
694 | ips->dispersion = HTONS_FP(pp->dispersion); |
---|
695 | |
---|
696 | pp = pp->next; |
---|
697 | ips = (struct info_peer_summary *)more_pkt(); |
---|
698 | } |
---|
699 | } |
---|
700 | flush_pkt(); |
---|
701 | } |
---|
702 | |
---|
703 | |
---|
704 | /* |
---|
705 | * peer_info - send information for one or more peers |
---|
706 | */ |
---|
707 | static void |
---|
708 | peer_info (srcadr, inter, inpkt) |
---|
709 | struct sockaddr_in *srcadr; |
---|
710 | struct interface *inter; |
---|
711 | struct req_pkt *inpkt; |
---|
712 | { |
---|
713 | register struct info_peer_list *ipl; |
---|
714 | register struct peer *pp; |
---|
715 | register struct info_peer *ip; |
---|
716 | register int items; |
---|
717 | register int i, j; |
---|
718 | struct sockaddr_in addr; |
---|
719 | extern struct peer *sys_peer; |
---|
720 | |
---|
721 | memset((char *)&addr, 0, sizeof addr); |
---|
722 | addr.sin_family = AF_INET; |
---|
723 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
724 | ipl = (struct info_peer_list *) inpkt->data; |
---|
725 | ip = (struct info_peer *)prepare_pkt(srcadr, inter, inpkt, |
---|
726 | sizeof(struct info_peer)); |
---|
727 | while (items-- > 0 && ip != 0) { |
---|
728 | addr.sin_port = ipl->port; |
---|
729 | addr.sin_addr.s_addr = ipl->address; |
---|
730 | ipl++; |
---|
731 | if ((pp = findexistingpeer(&addr, (struct peer *)0)) == 0) |
---|
732 | continue; |
---|
733 | ip->dstadr = (pp->processed) ? |
---|
734 | pp->cast_flags == MDF_BCAST ? |
---|
735 | pp->dstadr->bcast.sin_addr.s_addr: |
---|
736 | pp->cast_flags ? |
---|
737 | pp->dstadr->sin.sin_addr.s_addr ? |
---|
738 | pp->dstadr->sin.sin_addr.s_addr: |
---|
739 | pp->dstadr->bcast.sin_addr.s_addr: |
---|
740 | 2 : 6; |
---|
741 | ip->srcadr = NSRCADR(&pp->srcadr); |
---|
742 | ip->srcport = NSRCPORT(&pp->srcadr); |
---|
743 | ip->flags = 0; |
---|
744 | if (pp == sys_peer) |
---|
745 | ip->flags |= INFO_FLAG_SYSPEER; |
---|
746 | if (pp->flags & FLAG_CONFIG) |
---|
747 | ip->flags |= INFO_FLAG_CONFIG; |
---|
748 | if (pp->flags & FLAG_REFCLOCK) |
---|
749 | ip->flags |= INFO_FLAG_REFCLOCK; |
---|
750 | if (pp->flags & FLAG_AUTHENABLE) |
---|
751 | ip->flags |= INFO_FLAG_AUTHENABLE; |
---|
752 | if (pp->flags & FLAG_PREFER) |
---|
753 | ip->flags |= INFO_FLAG_PREFER; |
---|
754 | if (pp->candidate != 0) |
---|
755 | ip->flags |= INFO_FLAG_SEL_CANDIDATE; |
---|
756 | if (pp->select != 0) |
---|
757 | ip->flags |= INFO_FLAG_SHORTLIST; |
---|
758 | ip->leap = pp->leap; |
---|
759 | ip->hmode = pp->hmode; |
---|
760 | ip->keyid = pp->keyid; |
---|
761 | ip->pkeyid = pp->pkeyid; |
---|
762 | ip->stratum = pp->stratum; |
---|
763 | ip->ppoll = pp->ppoll; |
---|
764 | ip->hpoll = pp->hpoll; |
---|
765 | ip->precision = pp->precision; |
---|
766 | ip->version = pp->version; |
---|
767 | ip->valid = pp->valid; |
---|
768 | ip->reach = pp->reach; |
---|
769 | ip->unreach = pp->unreach; |
---|
770 | ip->flash = pp->flash; |
---|
771 | ip->estbdelay = HTONS_FP(pp->estbdelay); |
---|
772 | ip->ttl = pp->ttl; |
---|
773 | ip->associd = htons(pp->associd); |
---|
774 | ip->rootdelay = HTONS_FP(pp->rootdelay); |
---|
775 | ip->rootdispersion = HTONS_FP(pp->rootdispersion); |
---|
776 | ip->refid = pp->refid; |
---|
777 | ip->timer = htonl((u_int32)(pp->event_timer.event_time - current_time)); |
---|
778 | HTONL_FP(&pp->reftime, &ip->reftime); |
---|
779 | HTONL_FP(&pp->org, &ip->org); |
---|
780 | HTONL_FP(&pp->rec, &ip->rec); |
---|
781 | HTONL_FP(&pp->xmt, &ip->xmt); |
---|
782 | j = pp->filter_nextpt - 1; |
---|
783 | for (i = 0; i < NTP_SHIFT; i++, j--) { |
---|
784 | if (j < 0) |
---|
785 | j = NTP_SHIFT-1; |
---|
786 | ip->filtdelay[i] = HTONS_FP(pp->filter_delay[j]); |
---|
787 | HTONL_FP(&pp->filter_offset[j], &ip->filtoffset[i]); |
---|
788 | ip->order[i] = (pp->filter_nextpt+NTP_SHIFT-1) |
---|
789 | - pp->filter_order[i]; |
---|
790 | if (ip->order[i] >= NTP_SHIFT) |
---|
791 | ip->order[i] -= NTP_SHIFT; |
---|
792 | } |
---|
793 | HTONL_FP(&pp->offset, &ip->offset); |
---|
794 | ip->delay = HTONS_FP(pp->delay); |
---|
795 | ip->dispersion = HTONS_FP(pp->dispersion); |
---|
796 | ip->selectdisp = HTONS_FP(pp->selectdisp); |
---|
797 | ip = (struct info_peer *)more_pkt(); |
---|
798 | } |
---|
799 | flush_pkt(); |
---|
800 | } |
---|
801 | |
---|
802 | |
---|
803 | /* |
---|
804 | * peer_stats - send statistics for one or more peers |
---|
805 | */ |
---|
806 | static void |
---|
807 | peer_stats (srcadr, inter, inpkt) |
---|
808 | struct sockaddr_in *srcadr; |
---|
809 | struct interface *inter; |
---|
810 | struct req_pkt *inpkt; |
---|
811 | { |
---|
812 | register struct info_peer_list *ipl; |
---|
813 | register struct peer *pp; |
---|
814 | register struct info_peer_stats *ip; |
---|
815 | register int items; |
---|
816 | struct sockaddr_in addr; |
---|
817 | extern struct peer *sys_peer; |
---|
818 | |
---|
819 | memset((char *)&addr, 0, sizeof addr); |
---|
820 | addr.sin_family = AF_INET; |
---|
821 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
822 | ipl = (struct info_peer_list *) inpkt->data; |
---|
823 | ip = (struct info_peer_stats *)prepare_pkt(srcadr, inter, inpkt, |
---|
824 | sizeof(struct info_peer_stats)); |
---|
825 | while (items-- > 0 && ip != 0) { |
---|
826 | addr.sin_port = ipl->port; |
---|
827 | addr.sin_addr.s_addr = ipl->address; |
---|
828 | ipl++; |
---|
829 | if ((pp = findexistingpeer(&addr, (struct peer *)0)) == 0) |
---|
830 | continue; |
---|
831 | ip->dstadr = (pp->processed) ? |
---|
832 | pp->cast_flags == MDF_BCAST ? |
---|
833 | pp->dstadr->bcast.sin_addr.s_addr: |
---|
834 | pp->cast_flags ? |
---|
835 | pp->dstadr->sin.sin_addr.s_addr ? |
---|
836 | pp->dstadr->sin.sin_addr.s_addr: |
---|
837 | pp->dstadr->bcast.sin_addr.s_addr: |
---|
838 | 3 : 7; |
---|
839 | ip->srcadr = NSRCADR(&pp->srcadr); |
---|
840 | ip->srcport = NSRCPORT(&pp->srcadr); |
---|
841 | ip->flags = 0; |
---|
842 | if (pp == sys_peer) |
---|
843 | ip->flags |= INFO_FLAG_SYSPEER; |
---|
844 | if (pp->flags & FLAG_CONFIG) |
---|
845 | ip->flags |= INFO_FLAG_CONFIG; |
---|
846 | if (pp->flags & FLAG_REFCLOCK) |
---|
847 | ip->flags |= INFO_FLAG_REFCLOCK; |
---|
848 | if (pp->flags & FLAG_AUTHENABLE) |
---|
849 | ip->flags |= INFO_FLAG_AUTHENABLE; |
---|
850 | if (pp->flags & FLAG_PREFER) |
---|
851 | ip->flags |= INFO_FLAG_PREFER; |
---|
852 | if (pp->candidate != 0) |
---|
853 | ip->flags |= INFO_FLAG_SEL_CANDIDATE; |
---|
854 | if (pp->select != 0) |
---|
855 | ip->flags |= INFO_FLAG_SHORTLIST; |
---|
856 | ip->timereceived = htonl((u_int32)(current_time - pp->timereceived)); |
---|
857 | ip->timetosend |
---|
858 | = htonl((u_int32)(pp->event_timer.event_time - current_time)); |
---|
859 | ip->timereachable = htonl((u_int32)(current_time - pp->timereachable)); |
---|
860 | ip->sent = htonl((u_int32)pp->sent); |
---|
861 | ip->processed = htonl((u_int32)pp->processed); |
---|
862 | ip->badauth = htonl((u_int32)pp->badauth); |
---|
863 | ip->bogusorg = htonl((u_int32)pp->bogusorg); |
---|
864 | ip->oldpkt = htonl((u_int32)pp->oldpkt); |
---|
865 | ip->seldisp = htonl((u_int32)pp->seldisptoolarge); |
---|
866 | ip->selbroken = htonl((u_int32)pp->selbroken); |
---|
867 | ip->candidate = pp->candidate; |
---|
868 | ip = (struct info_peer_stats *)more_pkt(); |
---|
869 | } |
---|
870 | flush_pkt(); |
---|
871 | } |
---|
872 | |
---|
873 | |
---|
874 | /* |
---|
875 | * sys_info - return system info |
---|
876 | */ |
---|
877 | static void |
---|
878 | sys_info(srcadr, inter, inpkt) |
---|
879 | struct sockaddr_in *srcadr; |
---|
880 | struct interface *inter; |
---|
881 | struct req_pkt *inpkt; |
---|
882 | { |
---|
883 | register struct info_sys *is; |
---|
884 | |
---|
885 | /* |
---|
886 | * Importations from the protocol module |
---|
887 | */ |
---|
888 | extern u_char sys_leap; |
---|
889 | extern u_char sys_stratum; |
---|
890 | extern s_char sys_precision; |
---|
891 | extern s_fp sys_rootdelay; |
---|
892 | extern u_fp sys_rootdispersion; |
---|
893 | extern u_int32 sys_refid; |
---|
894 | extern l_fp sys_reftime; |
---|
895 | extern u_char sys_poll; |
---|
896 | extern struct peer *sys_peer; |
---|
897 | extern int sys_bclient; |
---|
898 | extern s_fp sys_bdelay; |
---|
899 | extern int sys_authenticate; |
---|
900 | extern l_fp sys_authdelay; |
---|
901 | extern u_fp clock_stability; |
---|
902 | extern s_fp clock_frequency; |
---|
903 | |
---|
904 | is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt, |
---|
905 | sizeof(struct info_sys)); |
---|
906 | |
---|
907 | if (sys_peer != 0) { |
---|
908 | is->peer = NSRCADR(&sys_peer->srcadr); |
---|
909 | is->peer_mode = sys_peer->hmode; |
---|
910 | } else { |
---|
911 | is->peer = 0; |
---|
912 | is->peer_mode = 0; |
---|
913 | } |
---|
914 | is->leap = sys_leap; |
---|
915 | is->stratum = sys_stratum; |
---|
916 | is->precision = sys_precision; |
---|
917 | is->rootdelay = htonl(sys_rootdelay); |
---|
918 | is->rootdispersion = htonl(sys_rootdispersion); |
---|
919 | is->frequency = htonl(clock_frequency); |
---|
920 | is->stability = htonl(clock_stability); |
---|
921 | is->refid = sys_refid; |
---|
922 | HTONL_FP(&sys_reftime, &is->reftime); |
---|
923 | |
---|
924 | is->poll = sys_poll; |
---|
925 | |
---|
926 | is->flags = 0; |
---|
927 | if (sys_bclient) |
---|
928 | is->flags |= INFO_FLAG_BCLIENT; |
---|
929 | if (sys_authenticate) |
---|
930 | is->flags |= INFO_FLAG_AUTHENTICATE; |
---|
931 | if (pll_enable) |
---|
932 | is->flags |= INFO_FLAG_PLL; |
---|
933 | if (pps_enable) |
---|
934 | is->flags |= INFO_FLAG_PPS; |
---|
935 | if (pll_control) |
---|
936 | is->flags |= INFO_FLAG_PLL_SYNC; |
---|
937 | if (pps_control) |
---|
938 | is->flags |= INFO_FLAG_PPS_SYNC; |
---|
939 | if (mon_enabled != MON_OFF) |
---|
940 | is->flags |= INFO_FLAG_MONITOR; |
---|
941 | if (stats_control) |
---|
942 | is->flags |= INFO_FLAG_FILEGEN; |
---|
943 | is->bdelay = HTONS_FP(sys_bdelay); |
---|
944 | HTONL_UF(sys_authdelay.l_f, &is->authdelay); |
---|
945 | |
---|
946 | (void) more_pkt(); |
---|
947 | flush_pkt(); |
---|
948 | } |
---|
949 | |
---|
950 | |
---|
951 | /* |
---|
952 | * sys_stats - return system statistics |
---|
953 | */ |
---|
954 | static void |
---|
955 | sys_stats(srcadr, inter, inpkt) |
---|
956 | struct sockaddr_in *srcadr; |
---|
957 | struct interface *inter; |
---|
958 | struct req_pkt *inpkt; |
---|
959 | { |
---|
960 | register struct info_sys_stats *ss; |
---|
961 | |
---|
962 | /* |
---|
963 | * Importations from the protocol module |
---|
964 | */ |
---|
965 | extern u_long sys_stattime; |
---|
966 | extern u_long sys_badstratum; |
---|
967 | extern u_long sys_oldversionpkt; |
---|
968 | extern u_long sys_newversionpkt; |
---|
969 | extern u_long sys_unknownversion; |
---|
970 | extern u_long sys_badlength; |
---|
971 | extern u_long sys_processed; |
---|
972 | extern u_long sys_badauth; |
---|
973 | extern u_long sys_limitrejected; |
---|
974 | |
---|
975 | ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt, |
---|
976 | sizeof(struct info_sys_stats)); |
---|
977 | |
---|
978 | ss->timeup = htonl((u_int32)current_time); |
---|
979 | ss->timereset = htonl((u_int32)(current_time - sys_stattime)); |
---|
980 | ss->badstratum = htonl((u_int32)sys_badstratum); |
---|
981 | ss->oldversionpkt = htonl((u_int32)sys_oldversionpkt); |
---|
982 | ss->newversionpkt = htonl((u_int32)sys_newversionpkt); |
---|
983 | ss->unknownversion = htonl((u_int32)sys_unknownversion); |
---|
984 | ss->badlength = htonl((u_int32)sys_badlength); |
---|
985 | ss->processed = htonl((u_int32)sys_processed); |
---|
986 | ss->badauth = htonl((u_int32)sys_badauth); |
---|
987 | ss->limitrejected = htonl((u_int32)sys_limitrejected); |
---|
988 | (void) more_pkt(); |
---|
989 | flush_pkt(); |
---|
990 | } |
---|
991 | |
---|
992 | |
---|
993 | /* |
---|
994 | * mem_stats - return memory statistics |
---|
995 | */ |
---|
996 | static void |
---|
997 | mem_stats(srcadr, inter, inpkt) |
---|
998 | struct sockaddr_in *srcadr; |
---|
999 | struct interface *inter; |
---|
1000 | struct req_pkt *inpkt; |
---|
1001 | { |
---|
1002 | register struct info_mem_stats *ms; |
---|
1003 | register int i; |
---|
1004 | |
---|
1005 | /* |
---|
1006 | * Importations from the peer module |
---|
1007 | */ |
---|
1008 | extern int peer_hash_count[HASH_SIZE]; |
---|
1009 | extern int peer_free_count; |
---|
1010 | extern u_long peer_timereset; |
---|
1011 | extern u_long findpeer_calls; |
---|
1012 | extern u_long peer_allocations; |
---|
1013 | extern u_long peer_demobilizations; |
---|
1014 | extern int total_peer_structs; |
---|
1015 | |
---|
1016 | ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt, |
---|
1017 | sizeof(struct info_mem_stats)); |
---|
1018 | |
---|
1019 | ms->timereset = htonl((u_int32)(current_time - peer_timereset)); |
---|
1020 | ms->totalpeermem = htons((u_short)total_peer_structs); |
---|
1021 | ms->freepeermem = htons((u_short)peer_free_count); |
---|
1022 | ms->findpeer_calls = htonl((u_int32)findpeer_calls); |
---|
1023 | ms->allocations = htonl((u_int32)peer_allocations); |
---|
1024 | ms->demobilizations = htonl((u_int32)peer_demobilizations); |
---|
1025 | |
---|
1026 | for (i = 0; i < HASH_SIZE; i++) { |
---|
1027 | if (peer_hash_count[i] > 255) |
---|
1028 | ms->hashcount[i] = 255; |
---|
1029 | else |
---|
1030 | ms->hashcount[i] = (u_char)peer_hash_count[i]; |
---|
1031 | } |
---|
1032 | |
---|
1033 | (void) more_pkt(); |
---|
1034 | flush_pkt(); |
---|
1035 | } |
---|
1036 | |
---|
1037 | |
---|
1038 | /* |
---|
1039 | * io_stats - return io statistics |
---|
1040 | */ |
---|
1041 | static void |
---|
1042 | io_stats(srcadr, inter, inpkt) |
---|
1043 | struct sockaddr_in *srcadr; |
---|
1044 | struct interface *inter; |
---|
1045 | struct req_pkt *inpkt; |
---|
1046 | { |
---|
1047 | register struct info_io_stats *io; |
---|
1048 | |
---|
1049 | /* |
---|
1050 | * Importations from the io module |
---|
1051 | */ |
---|
1052 | extern u_long io_timereset; |
---|
1053 | volatile extern u_long full_recvbufs; |
---|
1054 | volatile extern u_long free_recvbufs; |
---|
1055 | extern u_long total_recvbufs; |
---|
1056 | extern u_long lowater_additions; |
---|
1057 | volatile extern u_long packets_dropped; |
---|
1058 | volatile extern u_long packets_ignored; |
---|
1059 | volatile extern u_long packets_received; |
---|
1060 | extern u_long packets_sent; |
---|
1061 | extern u_long packets_notsent; |
---|
1062 | volatile extern u_long handler_calls; |
---|
1063 | volatile extern u_long handler_pkts; |
---|
1064 | |
---|
1065 | io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt, |
---|
1066 | sizeof(struct info_io_stats)); |
---|
1067 | |
---|
1068 | io->timereset = htonl((u_int32)(current_time - io_timereset)); |
---|
1069 | io->totalrecvbufs = htons((u_short) total_recvbufs); |
---|
1070 | io->freerecvbufs = htons((u_short) free_recvbufs); |
---|
1071 | io->fullrecvbufs = htons((u_short) full_recvbufs); |
---|
1072 | io->lowwater = htons((u_short) lowater_additions); |
---|
1073 | io->dropped = htonl((u_int32)packets_dropped); |
---|
1074 | io->ignored = htonl((u_int32)packets_ignored); |
---|
1075 | io->received = htonl((u_int32)packets_received); |
---|
1076 | io->sent = htonl((u_int32)packets_sent); |
---|
1077 | io->notsent = htonl((u_int32)packets_notsent); |
---|
1078 | io->interrupts = htonl((u_int32)handler_calls); |
---|
1079 | io->int_received = htonl((u_int32)handler_pkts); |
---|
1080 | |
---|
1081 | (void) more_pkt(); |
---|
1082 | flush_pkt(); |
---|
1083 | } |
---|
1084 | |
---|
1085 | |
---|
1086 | /* |
---|
1087 | * timer_stats - return timer statistics |
---|
1088 | */ |
---|
1089 | static void |
---|
1090 | timer_stats(srcadr, inter, inpkt) |
---|
1091 | struct sockaddr_in *srcadr; |
---|
1092 | struct interface *inter; |
---|
1093 | struct req_pkt *inpkt; |
---|
1094 | { |
---|
1095 | register struct info_timer_stats *ts; |
---|
1096 | |
---|
1097 | /* |
---|
1098 | * Importations from the timer module |
---|
1099 | */ |
---|
1100 | extern u_long alarm_overflow; |
---|
1101 | extern u_long timer_timereset; |
---|
1102 | extern u_long timer_overflows; |
---|
1103 | extern u_long timer_xmtcalls; |
---|
1104 | |
---|
1105 | ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, inpkt, |
---|
1106 | sizeof(struct info_timer_stats)); |
---|
1107 | |
---|
1108 | ts->timereset = htonl((u_int32)(current_time - timer_timereset)); |
---|
1109 | ts->alarms = htonl((u_int32)alarm_overflow); |
---|
1110 | ts->overflows = htonl((u_int32)timer_overflows); |
---|
1111 | ts->xmtcalls = htonl((u_int32)timer_xmtcalls); |
---|
1112 | |
---|
1113 | (void) more_pkt(); |
---|
1114 | flush_pkt(); |
---|
1115 | } |
---|
1116 | |
---|
1117 | |
---|
1118 | /* |
---|
1119 | * loop_info - return the current state of the loop filter |
---|
1120 | */ |
---|
1121 | static void |
---|
1122 | loop_info(srcadr, inter, inpkt) |
---|
1123 | struct sockaddr_in *srcadr; |
---|
1124 | struct interface *inter; |
---|
1125 | struct req_pkt *inpkt; |
---|
1126 | { |
---|
1127 | register struct info_loop *li; |
---|
1128 | l_fp tmp; |
---|
1129 | |
---|
1130 | /* |
---|
1131 | * Importations from the loop filter module |
---|
1132 | */ |
---|
1133 | extern l_fp last_offset; |
---|
1134 | extern s_fp drift_comp; |
---|
1135 | extern int tc_counter; |
---|
1136 | extern u_long last_time; |
---|
1137 | |
---|
1138 | li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt, |
---|
1139 | sizeof(struct info_loop)); |
---|
1140 | |
---|
1141 | HTONL_FP(&last_offset, &li->last_offset); |
---|
1142 | FPTOLFP(drift_comp, &tmp); |
---|
1143 | HTONL_FP(&tmp, &li->drift_comp); |
---|
1144 | li->compliance = htonl((u_int32)tc_counter); |
---|
1145 | li->watchdog_timer = htonl((u_int32)(current_time - last_time)); |
---|
1146 | |
---|
1147 | (void) more_pkt(); |
---|
1148 | flush_pkt(); |
---|
1149 | } |
---|
1150 | |
---|
1151 | |
---|
1152 | /* |
---|
1153 | * do_conf - add a peer to the configuration list |
---|
1154 | */ |
---|
1155 | static void |
---|
1156 | do_conf(srcadr, inter, inpkt) |
---|
1157 | struct sockaddr_in *srcadr; |
---|
1158 | struct interface *inter; |
---|
1159 | struct req_pkt *inpkt; |
---|
1160 | { |
---|
1161 | register struct conf_peer *cp; |
---|
1162 | register int items; |
---|
1163 | struct sockaddr_in peeraddr; |
---|
1164 | int fl; |
---|
1165 | |
---|
1166 | /* |
---|
1167 | * Do a check of everything to see that it looks |
---|
1168 | * okay. If not, complain about it. Note we are |
---|
1169 | * very picky here. |
---|
1170 | */ |
---|
1171 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
1172 | cp = (struct conf_peer *)inpkt->data; |
---|
1173 | |
---|
1174 | fl = 0; |
---|
1175 | while (items-- > 0 && !fl) { |
---|
1176 | if (cp->version > NTP_VERSION |
---|
1177 | || cp->version < NTP_OLDVERSION) |
---|
1178 | fl = 1; |
---|
1179 | if (cp->hmode != MODE_ACTIVE |
---|
1180 | && cp->hmode != MODE_CLIENT |
---|
1181 | && cp->hmode != MODE_BROADCAST) |
---|
1182 | fl = 1; |
---|
1183 | if (cp->flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER)) |
---|
1184 | fl = 1; |
---|
1185 | cp++; |
---|
1186 | } |
---|
1187 | |
---|
1188 | if (fl) { |
---|
1189 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
1190 | return; |
---|
1191 | } |
---|
1192 | |
---|
1193 | /* |
---|
1194 | * Looks okay, try it out |
---|
1195 | */ |
---|
1196 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
1197 | cp = (struct conf_peer *)inpkt->data; |
---|
1198 | memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in)); |
---|
1199 | peeraddr.sin_family = AF_INET; |
---|
1200 | peeraddr.sin_port = htons(NTP_PORT); |
---|
1201 | |
---|
1202 | /* |
---|
1203 | * Make sure the address is valid |
---|
1204 | */ |
---|
1205 | #ifdef REFCLOCK |
---|
1206 | if (!ISREFCLOCKADR(&peeraddr) && ISBADADR(&peeraddr)) { |
---|
1207 | #else |
---|
1208 | if (ISBADADR(&peeraddr)) { |
---|
1209 | #endif |
---|
1210 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
1211 | return; |
---|
1212 | } |
---|
1213 | |
---|
1214 | while (items-- > 0) { |
---|
1215 | fl = 0; |
---|
1216 | if (cp->flags & CONF_FLAG_AUTHENABLE) |
---|
1217 | fl |= FLAG_AUTHENABLE; |
---|
1218 | if (cp->flags & CONF_FLAG_PREFER) |
---|
1219 | fl |= FLAG_PREFER; |
---|
1220 | peeraddr.sin_addr.s_addr = cp->peeraddr; |
---|
1221 | /* XXX W2DO? minpoll/maxpoll arguments ??? */ |
---|
1222 | if (peer_config(&peeraddr, (struct interface *)0, |
---|
1223 | cp->hmode, cp->version, cp->minpoll, cp->maxpoll, |
---|
1224 | fl, cp->ttl, cp->keyid) == 0) { |
---|
1225 | req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); |
---|
1226 | return; |
---|
1227 | } |
---|
1228 | cp++; |
---|
1229 | } |
---|
1230 | |
---|
1231 | req_ack(srcadr, inter, inpkt, INFO_OKAY); |
---|
1232 | } |
---|
1233 | |
---|
1234 | |
---|
1235 | /* |
---|
1236 | * do_unconf - remove a peer from the configuration list |
---|
1237 | */ |
---|
1238 | static void |
---|
1239 | do_unconf(srcadr, inter, inpkt) |
---|
1240 | struct sockaddr_in *srcadr; |
---|
1241 | struct interface *inter; |
---|
1242 | struct req_pkt *inpkt; |
---|
1243 | { |
---|
1244 | register struct conf_unpeer *cp; |
---|
1245 | register int items; |
---|
1246 | register struct peer *peer; |
---|
1247 | struct sockaddr_in peeraddr; |
---|
1248 | int bad, found; |
---|
1249 | |
---|
1250 | /* |
---|
1251 | * This is a bit unstructured, but I like to be careful. |
---|
1252 | * We check to see that every peer exists and is actually |
---|
1253 | * configured. If so, we remove them. If not, we return |
---|
1254 | * an error. |
---|
1255 | */ |
---|
1256 | peeraddr.sin_family = AF_INET; |
---|
1257 | peeraddr.sin_port = htons(NTP_PORT); |
---|
1258 | |
---|
1259 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
1260 | cp = (struct conf_unpeer *)inpkt->data; |
---|
1261 | |
---|
1262 | bad = 0; |
---|
1263 | while (items-- > 0 && !bad) { |
---|
1264 | peeraddr.sin_addr.s_addr = cp->peeraddr; |
---|
1265 | found = 0; |
---|
1266 | peer = (struct peer *)0; |
---|
1267 | while (!found) { |
---|
1268 | peer = findexistingpeer(&peeraddr, peer); |
---|
1269 | if (peer == (struct peer *)0) |
---|
1270 | break; |
---|
1271 | if (peer->flags & FLAG_CONFIG) |
---|
1272 | found = 1; |
---|
1273 | } |
---|
1274 | if (!found) |
---|
1275 | bad = 1; |
---|
1276 | cp++; |
---|
1277 | } |
---|
1278 | |
---|
1279 | if (bad) { |
---|
1280 | req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); |
---|
1281 | return; |
---|
1282 | } |
---|
1283 | |
---|
1284 | /* |
---|
1285 | * Now do it in earnest. |
---|
1286 | */ |
---|
1287 | |
---|
1288 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
1289 | cp = (struct conf_unpeer *)inpkt->data; |
---|
1290 | while (items-- > 0) { |
---|
1291 | peeraddr.sin_addr.s_addr = cp->peeraddr; |
---|
1292 | peer_unconfig(&peeraddr, (struct interface *)0); |
---|
1293 | cp++; |
---|
1294 | } |
---|
1295 | |
---|
1296 | req_ack(srcadr, inter, inpkt, INFO_OKAY); |
---|
1297 | } |
---|
1298 | |
---|
1299 | |
---|
1300 | /* |
---|
1301 | * set_sys_flag - set system flags |
---|
1302 | */ |
---|
1303 | static void |
---|
1304 | set_sys_flag(srcadr, inter, inpkt) |
---|
1305 | struct sockaddr_in *srcadr; |
---|
1306 | struct interface *inter; |
---|
1307 | struct req_pkt *inpkt; |
---|
1308 | { |
---|
1309 | setclr_flags(srcadr, inter, inpkt, 1); |
---|
1310 | } |
---|
1311 | |
---|
1312 | |
---|
1313 | /* |
---|
1314 | * clr_sys_flag - clear system flags |
---|
1315 | */ |
---|
1316 | static void |
---|
1317 | clr_sys_flag(srcadr, inter, inpkt) |
---|
1318 | struct sockaddr_in *srcadr; |
---|
1319 | struct interface *inter; |
---|
1320 | struct req_pkt *inpkt; |
---|
1321 | { |
---|
1322 | setclr_flags(srcadr, inter, inpkt, 0); |
---|
1323 | } |
---|
1324 | |
---|
1325 | |
---|
1326 | /* |
---|
1327 | * setclr_flags - do the grunge work of flag setting/clearing |
---|
1328 | */ |
---|
1329 | static void |
---|
1330 | setclr_flags(srcadr, inter, inpkt, set) |
---|
1331 | struct sockaddr_in *srcadr; |
---|
1332 | struct interface *inter; |
---|
1333 | struct req_pkt *inpkt; |
---|
1334 | u_long set; |
---|
1335 | { |
---|
1336 | register u_long flags; |
---|
1337 | |
---|
1338 | if (INFO_NITEMS(inpkt->err_nitems) > 1) { |
---|
1339 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
1340 | return; |
---|
1341 | } |
---|
1342 | |
---|
1343 | flags = ((struct conf_sys_flags *)inpkt->data)->flags; |
---|
1344 | |
---|
1345 | if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_AUTHENTICATE | |
---|
1346 | SYS_FLAG_PLL | SYS_FLAG_PPS | SYS_FLAG_MONITOR | |
---|
1347 | SYS_FLAG_FILEGEN)) { |
---|
1348 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
1349 | return; |
---|
1350 | } |
---|
1351 | |
---|
1352 | if (flags & SYS_FLAG_BCLIENT) |
---|
1353 | proto_config(PROTO_BROADCLIENT, set); |
---|
1354 | if (flags & SYS_FLAG_AUTHENTICATE) |
---|
1355 | proto_config(PROTO_AUTHENTICATE, set); |
---|
1356 | if (flags & SYS_FLAG_PLL) |
---|
1357 | proto_config(PROTO_PLL, set); |
---|
1358 | if (flags & SYS_FLAG_PPS) |
---|
1359 | proto_config(PROTO_PPS, set); |
---|
1360 | if (flags & SYS_FLAG_MONITOR) |
---|
1361 | proto_config(PROTO_MONITOR, set); |
---|
1362 | if (flags & SYS_FLAG_FILEGEN) |
---|
1363 | proto_config(PROTO_FILEGEN, set); |
---|
1364 | req_ack(srcadr, inter, inpkt, INFO_OKAY); |
---|
1365 | } |
---|
1366 | |
---|
1367 | |
---|
1368 | /* |
---|
1369 | * list_restrict - return the restrict list |
---|
1370 | */ |
---|
1371 | static void |
---|
1372 | list_restrict(srcadr, inter, inpkt) |
---|
1373 | struct sockaddr_in *srcadr; |
---|
1374 | struct interface *inter; |
---|
1375 | struct req_pkt *inpkt; |
---|
1376 | { |
---|
1377 | register struct info_restrict *ir; |
---|
1378 | register struct restrictlist *rl; |
---|
1379 | extern struct restrictlist *restrictlist; |
---|
1380 | |
---|
1381 | #ifdef DEBUG |
---|
1382 | if (debug > 2) |
---|
1383 | printf("wants peer list summary\n"); |
---|
1384 | #endif |
---|
1385 | |
---|
1386 | ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt, |
---|
1387 | sizeof(struct info_restrict)); |
---|
1388 | for (rl = restrictlist; rl != 0 && ir != 0; rl = rl->next) { |
---|
1389 | ir->addr = htonl(rl->addr); |
---|
1390 | ir->mask = htonl(rl->mask); |
---|
1391 | ir->count = htonl((u_int32)rl->count); |
---|
1392 | ir->flags = htons(rl->flags); |
---|
1393 | ir->mflags = htons(rl->mflags); |
---|
1394 | ir = (struct info_restrict *)more_pkt(); |
---|
1395 | } |
---|
1396 | flush_pkt(); |
---|
1397 | } |
---|
1398 | |
---|
1399 | |
---|
1400 | |
---|
1401 | /* |
---|
1402 | * do_resaddflags - add flags to a restrict entry (or create one) |
---|
1403 | */ |
---|
1404 | static void |
---|
1405 | do_resaddflags(srcadr, inter, inpkt) |
---|
1406 | struct sockaddr_in *srcadr; |
---|
1407 | struct interface *inter; |
---|
1408 | struct req_pkt *inpkt; |
---|
1409 | { |
---|
1410 | do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS); |
---|
1411 | } |
---|
1412 | |
---|
1413 | |
---|
1414 | |
---|
1415 | /* |
---|
1416 | * do_ressubflags - remove flags from a restrict entry |
---|
1417 | */ |
---|
1418 | static void |
---|
1419 | do_ressubflags(srcadr, inter, inpkt) |
---|
1420 | struct sockaddr_in *srcadr; |
---|
1421 | struct interface *inter; |
---|
1422 | struct req_pkt *inpkt; |
---|
1423 | { |
---|
1424 | do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG); |
---|
1425 | } |
---|
1426 | |
---|
1427 | |
---|
1428 | /* |
---|
1429 | * do_unrestrict - remove a restrict entry from the list |
---|
1430 | */ |
---|
1431 | static void |
---|
1432 | do_unrestrict(srcadr, inter, inpkt) |
---|
1433 | struct sockaddr_in *srcadr; |
---|
1434 | struct interface *inter; |
---|
1435 | struct req_pkt *inpkt; |
---|
1436 | { |
---|
1437 | do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE); |
---|
1438 | } |
---|
1439 | |
---|
1440 | |
---|
1441 | |
---|
1442 | |
---|
1443 | |
---|
1444 | /* |
---|
1445 | * do_restrict - do the dirty stuff of dealing with restrictions |
---|
1446 | */ |
---|
1447 | static void |
---|
1448 | do_restrict(srcadr, inter, inpkt, op) |
---|
1449 | struct sockaddr_in *srcadr; |
---|
1450 | struct interface *inter; |
---|
1451 | struct req_pkt *inpkt; |
---|
1452 | int op; |
---|
1453 | { |
---|
1454 | register struct conf_restrict *cr; |
---|
1455 | register int items; |
---|
1456 | struct sockaddr_in matchaddr; |
---|
1457 | struct sockaddr_in matchmask; |
---|
1458 | int bad; |
---|
1459 | |
---|
1460 | /* |
---|
1461 | * Do a check of the flags to make sure that only |
---|
1462 | * the NTPPORT flag is set, if any. If not, complain |
---|
1463 | * about it. Note we are very picky here. |
---|
1464 | */ |
---|
1465 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
1466 | cr = (struct conf_restrict *)inpkt->data; |
---|
1467 | |
---|
1468 | bad = 0; |
---|
1469 | while (items-- > 0 && !bad) { |
---|
1470 | if (cr->mflags & ~(RESM_NTPONLY)) |
---|
1471 | bad = 1; |
---|
1472 | if (cr->flags & ~(RES_ALLFLAGS)) |
---|
1473 | bad = 1; |
---|
1474 | if (cr->addr == htonl(INADDR_ANY) && cr->mask != htonl(INADDR_ANY)) |
---|
1475 | bad = 1; |
---|
1476 | cr++; |
---|
1477 | } |
---|
1478 | |
---|
1479 | if (bad) { |
---|
1480 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
1481 | return; |
---|
1482 | } |
---|
1483 | |
---|
1484 | /* |
---|
1485 | * Looks okay, try it out |
---|
1486 | */ |
---|
1487 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
1488 | cr = (struct conf_restrict *)inpkt->data; |
---|
1489 | memset((char *)&matchaddr, 0, sizeof(struct sockaddr_in)); |
---|
1490 | memset((char *)&matchmask, 0, sizeof(struct sockaddr_in)); |
---|
1491 | matchaddr.sin_family = AF_INET; |
---|
1492 | matchmask.sin_family = AF_INET; |
---|
1493 | |
---|
1494 | while (items-- > 0) { |
---|
1495 | matchaddr.sin_addr.s_addr = cr->addr; |
---|
1496 | matchmask.sin_addr.s_addr = cr->mask; |
---|
1497 | restrict(op, &matchaddr, &matchmask, cr->mflags, |
---|
1498 | cr->flags); |
---|
1499 | cr++; |
---|
1500 | } |
---|
1501 | |
---|
1502 | req_ack(srcadr, inter, inpkt, INFO_OKAY); |
---|
1503 | } |
---|
1504 | |
---|
1505 | |
---|
1506 | /* |
---|
1507 | * mon_getlist - return monitor data |
---|
1508 | */ |
---|
1509 | static void |
---|
1510 | mon_getlist_0(srcadr, inter, inpkt) |
---|
1511 | struct sockaddr_in *srcadr; |
---|
1512 | struct interface *inter; |
---|
1513 | struct req_pkt *inpkt; |
---|
1514 | { |
---|
1515 | register struct info_monitor *im; |
---|
1516 | register struct mon_data *md; |
---|
1517 | extern struct mon_data mon_mru_list; |
---|
1518 | extern int mon_enabled; |
---|
1519 | |
---|
1520 | #ifdef DEBUG |
---|
1521 | if (debug > 2) |
---|
1522 | printf("wants monitor 0 list\n"); |
---|
1523 | #endif |
---|
1524 | if (!mon_enabled) { |
---|
1525 | req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); |
---|
1526 | return; |
---|
1527 | } |
---|
1528 | |
---|
1529 | im = (struct info_monitor *)prepare_pkt(srcadr, inter, inpkt, |
---|
1530 | sizeof(struct info_monitor)); |
---|
1531 | for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0; |
---|
1532 | md = md->mru_next) { |
---|
1533 | im->lasttime = htonl((u_int32)(current_time - md->lasttime)); |
---|
1534 | im->firsttime = htonl((u_int32)(current_time - md->firsttime)); |
---|
1535 | if (md->lastdrop) |
---|
1536 | im->lastdrop = htonl((u_int32)(current_time - md->lastdrop)); |
---|
1537 | else |
---|
1538 | im->lastdrop = 0; |
---|
1539 | im->count = htonl((u_int32)md->count); |
---|
1540 | im->addr = md->rmtadr; |
---|
1541 | im->port = md->rmtport; |
---|
1542 | im->mode = md->mode; |
---|
1543 | im->version = md->version; |
---|
1544 | im = (struct info_monitor *)more_pkt(); |
---|
1545 | } |
---|
1546 | flush_pkt(); |
---|
1547 | } |
---|
1548 | |
---|
1549 | /* |
---|
1550 | * mon_getlist - return monitor data |
---|
1551 | */ |
---|
1552 | static void |
---|
1553 | mon_getlist_1(srcadr, inter, inpkt) |
---|
1554 | struct sockaddr_in *srcadr; |
---|
1555 | struct interface *inter; |
---|
1556 | struct req_pkt *inpkt; |
---|
1557 | { |
---|
1558 | register struct info_monitor_1 *im; |
---|
1559 | register struct mon_data *md; |
---|
1560 | extern struct mon_data mon_mru_list; |
---|
1561 | extern int mon_enabled; |
---|
1562 | |
---|
1563 | #ifdef DEBUG |
---|
1564 | if (debug > 2) |
---|
1565 | printf("wants monitor 1 list\n"); |
---|
1566 | #endif |
---|
1567 | if (!mon_enabled) { |
---|
1568 | req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); |
---|
1569 | return; |
---|
1570 | } |
---|
1571 | |
---|
1572 | im = (struct info_monitor_1 *)prepare_pkt(srcadr, inter, inpkt, |
---|
1573 | sizeof(struct info_monitor_1)); |
---|
1574 | for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0; |
---|
1575 | md = md->mru_next) { |
---|
1576 | im->lasttime = htonl((u_int32)(current_time - md->lasttime)); |
---|
1577 | im->firsttime = htonl((u_int32)(current_time - md->firsttime)); |
---|
1578 | if (md->lastdrop) |
---|
1579 | im->lastdrop = htonl((u_int32)(current_time - md->lastdrop)); |
---|
1580 | else |
---|
1581 | im->lastdrop = 0; |
---|
1582 | im->count = htonl((u_int32)md->count); |
---|
1583 | im->addr = md->rmtadr; |
---|
1584 | im->daddr = |
---|
1585 | (md->cast_flags == MDF_BCAST) |
---|
1586 | ? md->interface->bcast.sin_addr.s_addr |
---|
1587 | : (md->cast_flags |
---|
1588 | ? (md->interface->sin.sin_addr.s_addr |
---|
1589 | ? md->interface->sin.sin_addr.s_addr |
---|
1590 | : md->interface->bcast.sin_addr.s_addr |
---|
1591 | ) |
---|
1592 | : 4); |
---|
1593 | im->flags = md->cast_flags; |
---|
1594 | im->port = md->rmtport; |
---|
1595 | im->mode = md->mode; |
---|
1596 | im->version = md->version; |
---|
1597 | im = (struct info_monitor_1 *)more_pkt(); |
---|
1598 | } |
---|
1599 | flush_pkt(); |
---|
1600 | } |
---|
1601 | |
---|
1602 | /* |
---|
1603 | * Module entry points and the flags they correspond with |
---|
1604 | */ |
---|
1605 | struct reset_entry { |
---|
1606 | int flag; /* flag this corresponds to */ |
---|
1607 | void (*handler) P((void)); /* routine to handle request */ |
---|
1608 | }; |
---|
1609 | |
---|
1610 | struct reset_entry reset_entries[] = { |
---|
1611 | { RESET_FLAG_ALLPEERS, peer_all_reset }, |
---|
1612 | { RESET_FLAG_IO, io_clr_stats }, |
---|
1613 | { RESET_FLAG_SYS, proto_clr_stats }, |
---|
1614 | { RESET_FLAG_MEM, peer_clr_stats }, |
---|
1615 | { RESET_FLAG_TIMER, timer_clr_stats }, |
---|
1616 | { RESET_FLAG_AUTH, reset_auth_stats }, |
---|
1617 | { RESET_FLAG_CTL, ctl_clr_stats }, |
---|
1618 | { 0, 0 } |
---|
1619 | }; |
---|
1620 | |
---|
1621 | /* |
---|
1622 | * reset_stats - reset statistic counters here and there |
---|
1623 | */ |
---|
1624 | static void |
---|
1625 | reset_stats(srcadr, inter, inpkt) |
---|
1626 | struct sockaddr_in *srcadr; |
---|
1627 | struct interface *inter; |
---|
1628 | struct req_pkt *inpkt; |
---|
1629 | { |
---|
1630 | u_long flags; |
---|
1631 | struct reset_entry *rent; |
---|
1632 | |
---|
1633 | if (INFO_NITEMS(inpkt->err_nitems) > 1) { |
---|
1634 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
1635 | return; |
---|
1636 | } |
---|
1637 | |
---|
1638 | flags = ((struct reset_flags *)inpkt->data)->flags; |
---|
1639 | |
---|
1640 | if (flags & ~RESET_ALLFLAGS) { |
---|
1641 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
1642 | return; |
---|
1643 | } |
---|
1644 | |
---|
1645 | for (rent = reset_entries; rent->flag != 0; rent++) { |
---|
1646 | if (flags & rent->flag) |
---|
1647 | (rent->handler)(); |
---|
1648 | } |
---|
1649 | req_ack(srcadr, inter, inpkt, INFO_OKAY); |
---|
1650 | } |
---|
1651 | |
---|
1652 | |
---|
1653 | /* |
---|
1654 | * reset_peer - clear a peer's statistics |
---|
1655 | */ |
---|
1656 | static void |
---|
1657 | reset_peer(srcadr, inter, inpkt) |
---|
1658 | struct sockaddr_in *srcadr; |
---|
1659 | struct interface *inter; |
---|
1660 | struct req_pkt *inpkt; |
---|
1661 | { |
---|
1662 | register struct conf_unpeer *cp; |
---|
1663 | register int items; |
---|
1664 | register struct peer *peer; |
---|
1665 | struct sockaddr_in peeraddr; |
---|
1666 | int bad; |
---|
1667 | |
---|
1668 | /* |
---|
1669 | * We check first to see that every peer exists. If not, |
---|
1670 | * we return an error. |
---|
1671 | */ |
---|
1672 | peeraddr.sin_family = AF_INET; |
---|
1673 | peeraddr.sin_port = htons(NTP_PORT); |
---|
1674 | |
---|
1675 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
1676 | cp = (struct conf_unpeer *)inpkt->data; |
---|
1677 | |
---|
1678 | bad = 0; |
---|
1679 | while (items-- > 0 && !bad) { |
---|
1680 | peeraddr.sin_addr.s_addr = cp->peeraddr; |
---|
1681 | peer = findexistingpeer(&peeraddr, (struct peer *)0); |
---|
1682 | if (peer == (struct peer *)0) |
---|
1683 | bad++; |
---|
1684 | cp++; |
---|
1685 | } |
---|
1686 | |
---|
1687 | if (bad) { |
---|
1688 | req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); |
---|
1689 | return; |
---|
1690 | } |
---|
1691 | |
---|
1692 | /* |
---|
1693 | * Now do it in earnest. |
---|
1694 | */ |
---|
1695 | |
---|
1696 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
1697 | cp = (struct conf_unpeer *)inpkt->data; |
---|
1698 | while (items-- > 0) { |
---|
1699 | peeraddr.sin_addr.s_addr = cp->peeraddr; |
---|
1700 | peer = findexistingpeer(&peeraddr, (struct peer *)0); |
---|
1701 | peer_reset(peer); |
---|
1702 | cp++; |
---|
1703 | } |
---|
1704 | |
---|
1705 | req_ack(srcadr, inter, inpkt, INFO_OKAY); |
---|
1706 | } |
---|
1707 | |
---|
1708 | |
---|
1709 | /* |
---|
1710 | * do_key_reread - reread the encryption key file |
---|
1711 | */ |
---|
1712 | static void |
---|
1713 | do_key_reread(srcadr, inter, inpkt) |
---|
1714 | struct sockaddr_in *srcadr; |
---|
1715 | struct interface *inter; |
---|
1716 | struct req_pkt *inpkt; |
---|
1717 | { |
---|
1718 | rereadkeys(); |
---|
1719 | req_ack(srcadr, inter, inpkt, INFO_OKAY); |
---|
1720 | } |
---|
1721 | |
---|
1722 | |
---|
1723 | /* |
---|
1724 | * trust_key - make one or more keys trusted |
---|
1725 | */ |
---|
1726 | static void |
---|
1727 | trust_key(srcadr, inter, inpkt) |
---|
1728 | struct sockaddr_in *srcadr; |
---|
1729 | struct interface *inter; |
---|
1730 | struct req_pkt *inpkt; |
---|
1731 | { |
---|
1732 | do_trustkey(srcadr, inter, inpkt, 1); |
---|
1733 | } |
---|
1734 | |
---|
1735 | |
---|
1736 | /* |
---|
1737 | * untrust_key - make one or more keys untrusted |
---|
1738 | */ |
---|
1739 | static void |
---|
1740 | untrust_key(srcadr, inter, inpkt) |
---|
1741 | struct sockaddr_in *srcadr; |
---|
1742 | struct interface *inter; |
---|
1743 | struct req_pkt *inpkt; |
---|
1744 | { |
---|
1745 | do_trustkey(srcadr, inter, inpkt, 0); |
---|
1746 | } |
---|
1747 | |
---|
1748 | |
---|
1749 | /* |
---|
1750 | * do_trustkey - make keys either trustable or untrustable |
---|
1751 | */ |
---|
1752 | static void |
---|
1753 | do_trustkey(srcadr, inter, inpkt, trust) |
---|
1754 | struct sockaddr_in *srcadr; |
---|
1755 | struct interface *inter; |
---|
1756 | struct req_pkt *inpkt; |
---|
1757 | int trust; |
---|
1758 | { |
---|
1759 | register u_int32 *kp; |
---|
1760 | register int items; |
---|
1761 | |
---|
1762 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
1763 | kp = (u_int32 *)inpkt->data; |
---|
1764 | while (items-- > 0) { |
---|
1765 | authtrust(*kp, trust); |
---|
1766 | kp++; |
---|
1767 | } |
---|
1768 | |
---|
1769 | req_ack(srcadr, inter, inpkt, INFO_OKAY); |
---|
1770 | } |
---|
1771 | |
---|
1772 | |
---|
1773 | /* |
---|
1774 | * get_auth_info - return some stats concerning the authentication module |
---|
1775 | */ |
---|
1776 | static void |
---|
1777 | get_auth_info(srcadr, inter, inpkt) |
---|
1778 | struct sockaddr_in *srcadr; |
---|
1779 | struct interface *inter; |
---|
1780 | struct req_pkt *inpkt; |
---|
1781 | { |
---|
1782 | register struct info_auth *ia; |
---|
1783 | |
---|
1784 | /* |
---|
1785 | * Importations from the authentication module |
---|
1786 | */ |
---|
1787 | extern u_long authnumkeys; |
---|
1788 | extern u_long authnumfreekeys; |
---|
1789 | extern u_long authkeylookups; |
---|
1790 | extern u_long authkeynotfound; |
---|
1791 | extern u_long authencryptions; |
---|
1792 | extern u_long authdecryptions; |
---|
1793 | extern u_long authkeyuncached; |
---|
1794 | |
---|
1795 | ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt, |
---|
1796 | sizeof(struct info_auth)); |
---|
1797 | |
---|
1798 | ia->numkeys = htonl((u_int32)authnumkeys); |
---|
1799 | ia->numfreekeys = htonl((u_int32)authnumfreekeys); |
---|
1800 | ia->keylookups = htonl((u_int32)authkeylookups); |
---|
1801 | ia->keynotfound = htonl((u_int32)authkeynotfound); |
---|
1802 | ia->encryptions = htonl((u_int32)authencryptions); |
---|
1803 | ia->decryptions = htonl((u_int32)authdecryptions); |
---|
1804 | ia->keyuncached = htonl((u_int32)authkeyuncached); |
---|
1805 | ia->timereset = htonl((u_int32)(current_time - auth_timereset)); |
---|
1806 | |
---|
1807 | (void) more_pkt(); |
---|
1808 | flush_pkt(); |
---|
1809 | } |
---|
1810 | |
---|
1811 | |
---|
1812 | |
---|
1813 | /* |
---|
1814 | * reset_auth_stats - reset the authentication stat counters. Done here |
---|
1815 | * to keep xntp-isms out of the authentication module |
---|
1816 | */ |
---|
1817 | static void |
---|
1818 | reset_auth_stats() |
---|
1819 | { |
---|
1820 | /* |
---|
1821 | * Importations from the authentication module |
---|
1822 | */ |
---|
1823 | extern u_long authkeylookups; |
---|
1824 | extern u_long authkeynotfound; |
---|
1825 | extern u_long authencryptions; |
---|
1826 | extern u_long authdecryptions; |
---|
1827 | extern u_long authkeyuncached; |
---|
1828 | |
---|
1829 | authkeylookups = 0; |
---|
1830 | authkeynotfound = 0; |
---|
1831 | authencryptions = 0; |
---|
1832 | authdecryptions = 0; |
---|
1833 | authkeyuncached = 0; |
---|
1834 | auth_timereset = current_time; |
---|
1835 | } |
---|
1836 | |
---|
1837 | |
---|
1838 | /* |
---|
1839 | * req_get_traps - return information about current trap holders |
---|
1840 | */ |
---|
1841 | static void |
---|
1842 | req_get_traps(srcadr, inter, inpkt) |
---|
1843 | struct sockaddr_in *srcadr; |
---|
1844 | struct interface *inter; |
---|
1845 | struct req_pkt *inpkt; |
---|
1846 | { |
---|
1847 | register struct info_trap *it; |
---|
1848 | register struct ctl_trap *tr; |
---|
1849 | register int i; |
---|
1850 | |
---|
1851 | /* |
---|
1852 | * Imported from the control module |
---|
1853 | */ |
---|
1854 | extern struct ctl_trap ctl_trap[]; |
---|
1855 | extern int num_ctl_traps; |
---|
1856 | |
---|
1857 | if (num_ctl_traps == 0) { |
---|
1858 | req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); |
---|
1859 | return; |
---|
1860 | } |
---|
1861 | |
---|
1862 | it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt, |
---|
1863 | sizeof(struct info_trap)); |
---|
1864 | |
---|
1865 | for (i = 0, tr = ctl_trap; i < CTL_MAXTRAPS; i++, tr++) { |
---|
1866 | if (tr->tr_flags & TRAP_INUSE) { |
---|
1867 | if (tr->tr_localaddr == any_interface) |
---|
1868 | it->local_address = 0; |
---|
1869 | else |
---|
1870 | it->local_address |
---|
1871 | = NSRCADR(&tr->tr_localaddr->sin); |
---|
1872 | it->trap_address = NSRCADR(&tr->tr_addr); |
---|
1873 | it->trap_port = NSRCPORT(&tr->tr_addr); |
---|
1874 | it->sequence = htons(tr->tr_sequence); |
---|
1875 | it->settime = htonl((u_int32)(current_time - tr->tr_settime)); |
---|
1876 | it->origtime = htonl((u_int32)(current_time - tr->tr_origtime)); |
---|
1877 | it->resets = htonl((u_int32)tr->tr_resets); |
---|
1878 | it->flags = htonl((u_int32)tr->tr_flags); |
---|
1879 | it = (struct info_trap *)more_pkt(); |
---|
1880 | } |
---|
1881 | } |
---|
1882 | flush_pkt(); |
---|
1883 | } |
---|
1884 | |
---|
1885 | |
---|
1886 | /* |
---|
1887 | * req_set_trap - configure a trap |
---|
1888 | */ |
---|
1889 | static void |
---|
1890 | req_set_trap(srcadr, inter, inpkt) |
---|
1891 | struct sockaddr_in *srcadr; |
---|
1892 | struct interface *inter; |
---|
1893 | struct req_pkt *inpkt; |
---|
1894 | { |
---|
1895 | do_setclr_trap(srcadr, inter, inpkt, 1); |
---|
1896 | } |
---|
1897 | |
---|
1898 | |
---|
1899 | |
---|
1900 | /* |
---|
1901 | * req_clr_trap - unconfigure a trap |
---|
1902 | */ |
---|
1903 | static void |
---|
1904 | req_clr_trap(srcadr, inter, inpkt) |
---|
1905 | struct sockaddr_in *srcadr; |
---|
1906 | struct interface *inter; |
---|
1907 | struct req_pkt *inpkt; |
---|
1908 | { |
---|
1909 | do_setclr_trap(srcadr, inter, inpkt, 0); |
---|
1910 | } |
---|
1911 | |
---|
1912 | |
---|
1913 | |
---|
1914 | /* |
---|
1915 | * do_setclr_trap - do the grunge work of (un)configuring a trap |
---|
1916 | */ |
---|
1917 | static void |
---|
1918 | do_setclr_trap(srcadr, inter, inpkt, set) |
---|
1919 | struct sockaddr_in *srcadr; |
---|
1920 | struct interface *inter; |
---|
1921 | struct req_pkt *inpkt; |
---|
1922 | int set; |
---|
1923 | { |
---|
1924 | register struct conf_trap *ct; |
---|
1925 | register struct interface *linter; |
---|
1926 | int res; |
---|
1927 | struct sockaddr_in laddr; |
---|
1928 | |
---|
1929 | /* |
---|
1930 | * Prepare sockaddr_in structure |
---|
1931 | */ |
---|
1932 | memset((char *)&laddr, 0, sizeof laddr); |
---|
1933 | laddr.sin_family = AF_INET; |
---|
1934 | laddr.sin_port = ntohs(NTP_PORT); |
---|
1935 | |
---|
1936 | /* |
---|
1937 | * Restrict ourselves to one item only. This eliminates |
---|
1938 | * the error reporting problem. |
---|
1939 | */ |
---|
1940 | if (INFO_NITEMS(inpkt->err_nitems) > 1) { |
---|
1941 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
1942 | return; |
---|
1943 | } |
---|
1944 | ct = (struct conf_trap *)inpkt->data; |
---|
1945 | |
---|
1946 | /* |
---|
1947 | * Look for the local interface. If none, use the default. |
---|
1948 | */ |
---|
1949 | if (ct->local_address == 0) { |
---|
1950 | linter = any_interface; |
---|
1951 | } else { |
---|
1952 | laddr.sin_addr.s_addr = ct->local_address; |
---|
1953 | linter = findinterface(&laddr); |
---|
1954 | if (linter == NULL) { |
---|
1955 | req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); |
---|
1956 | return; |
---|
1957 | } |
---|
1958 | } |
---|
1959 | |
---|
1960 | laddr.sin_addr.s_addr = ct->trap_address; |
---|
1961 | if (ct->trap_port != 0) |
---|
1962 | laddr.sin_port = ct->trap_port; |
---|
1963 | else |
---|
1964 | laddr.sin_port = htons(TRAPPORT); |
---|
1965 | |
---|
1966 | if (set) { |
---|
1967 | res = ctlsettrap(&laddr, linter, 0, |
---|
1968 | INFO_VERSION(inpkt->rm_vn_mode)); |
---|
1969 | } else { |
---|
1970 | res = ctlclrtrap(&laddr, linter, 0); |
---|
1971 | } |
---|
1972 | |
---|
1973 | if (!res) { |
---|
1974 | req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); |
---|
1975 | } else { |
---|
1976 | req_ack(srcadr, inter, inpkt, INFO_OKAY); |
---|
1977 | } |
---|
1978 | return; |
---|
1979 | } |
---|
1980 | |
---|
1981 | |
---|
1982 | |
---|
1983 | /* |
---|
1984 | * set_request_keyid - set the keyid used to authenticate requests |
---|
1985 | */ |
---|
1986 | static void |
---|
1987 | set_request_keyid(srcadr, inter, inpkt) |
---|
1988 | struct sockaddr_in *srcadr; |
---|
1989 | struct interface *inter; |
---|
1990 | struct req_pkt *inpkt; |
---|
1991 | { |
---|
1992 | u_int32 keyid; |
---|
1993 | |
---|
1994 | /* |
---|
1995 | * Restrict ourselves to one item only. |
---|
1996 | */ |
---|
1997 | if (INFO_NITEMS(inpkt->err_nitems) > 1) { |
---|
1998 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
1999 | return; |
---|
2000 | } |
---|
2001 | |
---|
2002 | keyid = ntohl(*((u_int32 *)(inpkt->data))); |
---|
2003 | info_auth_keyid = keyid; |
---|
2004 | req_ack(srcadr, inter, inpkt, INFO_OKAY); |
---|
2005 | } |
---|
2006 | |
---|
2007 | |
---|
2008 | |
---|
2009 | /* |
---|
2010 | * set_control_keyid - set the keyid used to authenticate requests |
---|
2011 | */ |
---|
2012 | static void |
---|
2013 | set_control_keyid(srcadr, inter, inpkt) |
---|
2014 | struct sockaddr_in *srcadr; |
---|
2015 | struct interface *inter; |
---|
2016 | struct req_pkt *inpkt; |
---|
2017 | { |
---|
2018 | u_int32 keyid; |
---|
2019 | extern u_int32 ctl_auth_keyid; |
---|
2020 | |
---|
2021 | /* |
---|
2022 | * Restrict ourselves to one item only. |
---|
2023 | */ |
---|
2024 | if (INFO_NITEMS(inpkt->err_nitems) > 1) { |
---|
2025 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
2026 | return; |
---|
2027 | } |
---|
2028 | |
---|
2029 | keyid = ntohl(*((u_int32 *)(inpkt->data))); |
---|
2030 | ctl_auth_keyid = keyid; |
---|
2031 | req_ack(srcadr, inter, inpkt, INFO_OKAY); |
---|
2032 | } |
---|
2033 | |
---|
2034 | |
---|
2035 | |
---|
2036 | /* |
---|
2037 | * get_ctl_stats - return some stats concerning the control message module |
---|
2038 | */ |
---|
2039 | static void |
---|
2040 | get_ctl_stats(srcadr, inter, inpkt) |
---|
2041 | struct sockaddr_in *srcadr; |
---|
2042 | struct interface *inter; |
---|
2043 | struct req_pkt *inpkt; |
---|
2044 | { |
---|
2045 | register struct info_control *ic; |
---|
2046 | |
---|
2047 | /* |
---|
2048 | * Importations from the control module |
---|
2049 | */ |
---|
2050 | extern u_long ctltimereset; |
---|
2051 | extern u_long numctlreq; |
---|
2052 | extern u_long numctlbadpkts; |
---|
2053 | extern u_long numctlresponses; |
---|
2054 | extern u_long numctlfrags; |
---|
2055 | extern u_long numctlerrors; |
---|
2056 | extern u_long numctltooshort; |
---|
2057 | extern u_long numctlinputresp; |
---|
2058 | extern u_long numctlinputfrag; |
---|
2059 | extern u_long numctlinputerr; |
---|
2060 | extern u_long numctlbadoffset; |
---|
2061 | extern u_long numctlbadversion; |
---|
2062 | extern u_long numctldatatooshort; |
---|
2063 | extern u_long numctlbadop; |
---|
2064 | extern u_long numasyncmsgs; |
---|
2065 | |
---|
2066 | ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt, |
---|
2067 | sizeof(struct info_control)); |
---|
2068 | |
---|
2069 | ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset)); |
---|
2070 | ic->numctlreq = htonl((u_int32)numctlreq); |
---|
2071 | ic->numctlbadpkts = htonl((u_int32)numctlbadpkts); |
---|
2072 | ic->numctlresponses = htonl((u_int32)numctlresponses); |
---|
2073 | ic->numctlfrags = htonl((u_int32)numctlfrags); |
---|
2074 | ic->numctlerrors = htonl((u_int32)numctlerrors); |
---|
2075 | ic->numctltooshort = htonl((u_int32)numctltooshort); |
---|
2076 | ic->numctlinputresp = htonl((u_int32)numctlinputresp); |
---|
2077 | ic->numctlinputfrag = htonl((u_int32)numctlinputfrag); |
---|
2078 | ic->numctlinputerr = htonl((u_int32)numctlinputerr); |
---|
2079 | ic->numctlbadoffset = htonl((u_int32)numctlbadoffset); |
---|
2080 | ic->numctlbadversion = htonl((u_int32)numctlbadversion); |
---|
2081 | ic->numctldatatooshort = htonl((u_int32)numctldatatooshort); |
---|
2082 | ic->numctlbadop = htonl((u_int32)numctlbadop); |
---|
2083 | ic->numasyncmsgs = htonl((u_int32)numasyncmsgs); |
---|
2084 | |
---|
2085 | (void) more_pkt(); |
---|
2086 | flush_pkt(); |
---|
2087 | } |
---|
2088 | |
---|
2089 | |
---|
2090 | |
---|
2091 | /* |
---|
2092 | * get_leap_info - return some stats concerning the control message module |
---|
2093 | */ |
---|
2094 | static void |
---|
2095 | get_leap_info(srcadr, inter, inpkt) |
---|
2096 | struct sockaddr_in *srcadr; |
---|
2097 | struct interface *inter; |
---|
2098 | struct req_pkt *inpkt; |
---|
2099 | { |
---|
2100 | register struct info_leap *il; |
---|
2101 | |
---|
2102 | /* |
---|
2103 | * Imported from the protocol module |
---|
2104 | */ |
---|
2105 | extern u_char sys_leap; |
---|
2106 | |
---|
2107 | /* |
---|
2108 | * Importations from the leap module |
---|
2109 | */ |
---|
2110 | extern u_char leap_indicator; |
---|
2111 | extern u_char leap_warning; |
---|
2112 | extern u_char leapbits; |
---|
2113 | extern u_long leap_timer; |
---|
2114 | extern u_long leap_processcalls; |
---|
2115 | extern u_long leap_notclose; |
---|
2116 | extern u_long leap_monthofleap; |
---|
2117 | extern u_long leap_dayofleap; |
---|
2118 | extern u_long leap_hoursfromleap; |
---|
2119 | extern u_long leap_happened; |
---|
2120 | |
---|
2121 | il = (struct info_leap *)prepare_pkt(srcadr, inter, inpkt, |
---|
2122 | sizeof(struct info_leap)); |
---|
2123 | |
---|
2124 | il->sys_leap = sys_leap; |
---|
2125 | il->leap_indicator = leap_indicator; |
---|
2126 | il->leap_warning = leap_warning; |
---|
2127 | il->leap_bits = (leapbits & INFO_LEAP_MASK) |
---|
2128 | | ((leap_indicator != LEAP_NOWARNING) ? INFO_LEAP_OVERRIDE : 0); |
---|
2129 | il->leap_timer = htonl((u_int32)(leap_timer - current_time)); |
---|
2130 | il->leap_processcalls = htonl((u_int32)leap_processcalls); |
---|
2131 | il->leap_notclose = htonl((u_int32)leap_notclose); |
---|
2132 | il->leap_monthofleap = htonl((u_int32)leap_monthofleap); |
---|
2133 | il->leap_dayofleap = htonl((u_int32)leap_dayofleap); |
---|
2134 | il->leap_hoursfromleap = htonl((u_int32)leap_hoursfromleap); |
---|
2135 | il->leap_happened = htonl((u_int32)leap_happened); |
---|
2136 | |
---|
2137 | (void) more_pkt(); |
---|
2138 | flush_pkt(); |
---|
2139 | } |
---|
2140 | |
---|
2141 | |
---|
2142 | #ifdef KERNEL_PLL |
---|
2143 | /* |
---|
2144 | * get_kernel_info - get kernel pll/pps information |
---|
2145 | */ |
---|
2146 | static void |
---|
2147 | get_kernel_info(srcadr, inter, inpkt) |
---|
2148 | struct sockaddr_in *srcadr; |
---|
2149 | struct interface *inter; |
---|
2150 | struct req_pkt *inpkt; |
---|
2151 | { |
---|
2152 | register struct info_kernel *ik; |
---|
2153 | struct timex ntx; |
---|
2154 | |
---|
2155 | if (!pll_control) { |
---|
2156 | req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); |
---|
2157 | return; |
---|
2158 | } |
---|
2159 | |
---|
2160 | memset((char *)&ntx, 0, sizeof(ntx)); |
---|
2161 | if (ntp_adjtime(&ntx) < 0) |
---|
2162 | { |
---|
2163 | msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m"); |
---|
2164 | } |
---|
2165 | ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt, |
---|
2166 | sizeof(struct info_kernel)); |
---|
2167 | |
---|
2168 | /* |
---|
2169 | * pll variables |
---|
2170 | */ |
---|
2171 | ik->offset = htonl((u_int32)ntx.offset); |
---|
2172 | ik->freq = htonl((u_int32)ntx.freq); |
---|
2173 | ik->maxerror = htonl((u_int32)ntx.maxerror); |
---|
2174 | ik->esterror = htonl((u_int32)ntx.esterror); |
---|
2175 | ik->status = htons(ntx.status); |
---|
2176 | ik->constant = htonl((u_int32)ntx.constant); |
---|
2177 | ik->precision = htonl((u_int32)ntx.precision); |
---|
2178 | ik->tolerance = htonl((u_int32)ntx.tolerance); |
---|
2179 | |
---|
2180 | /* |
---|
2181 | * pps variables |
---|
2182 | */ |
---|
2183 | ik->ppsfreq = htonl((u_int32)ntx.ppsfreq); |
---|
2184 | ik->jitter = htonl((u_int32)ntx.jitter); |
---|
2185 | ik->shift = htons(ntx.shift); |
---|
2186 | ik->stabil = htonl((u_int32)ntx.stabil); |
---|
2187 | ik->jitcnt = htonl((u_int32)ntx.jitcnt); |
---|
2188 | ik->calcnt = htonl((u_int32)ntx.calcnt); |
---|
2189 | ik->errcnt = htonl((u_int32)ntx.errcnt); |
---|
2190 | ik->stbcnt = htonl((u_int32)ntx.stbcnt); |
---|
2191 | |
---|
2192 | (void) more_pkt(); |
---|
2193 | flush_pkt(); |
---|
2194 | } |
---|
2195 | #endif /* KERNEL_PLL */ |
---|
2196 | |
---|
2197 | |
---|
2198 | #ifdef REFCLOCK |
---|
2199 | /* |
---|
2200 | * get_clock_info - get info about a clock |
---|
2201 | */ |
---|
2202 | static void |
---|
2203 | get_clock_info(srcadr, inter, inpkt) |
---|
2204 | struct sockaddr_in *srcadr; |
---|
2205 | struct interface *inter; |
---|
2206 | struct req_pkt *inpkt; |
---|
2207 | { |
---|
2208 | register struct info_clock *ic; |
---|
2209 | register u_int32 *clkaddr; |
---|
2210 | register int items; |
---|
2211 | struct refclockstat clock; |
---|
2212 | struct sockaddr_in addr; |
---|
2213 | |
---|
2214 | memset((char *)&addr, 0, sizeof addr); |
---|
2215 | addr.sin_family = AF_INET; |
---|
2216 | addr.sin_port = htons(NTP_PORT); |
---|
2217 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
2218 | clkaddr = (u_int32 *) inpkt->data; |
---|
2219 | |
---|
2220 | ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt, |
---|
2221 | sizeof(struct info_clock)); |
---|
2222 | |
---|
2223 | while (items-- > 0) { |
---|
2224 | addr.sin_addr.s_addr = *clkaddr++; |
---|
2225 | if (!ISREFCLOCKADR(&addr) || |
---|
2226 | findexistingpeer(&addr, (struct peer *)0) == 0) { |
---|
2227 | req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); |
---|
2228 | return; |
---|
2229 | } |
---|
2230 | |
---|
2231 | clock.kv_list = (struct ctl_var *)0; |
---|
2232 | |
---|
2233 | refclock_control(&addr, (struct refclockstat *)0, &clock); |
---|
2234 | |
---|
2235 | ic->clockadr = addr.sin_addr.s_addr; |
---|
2236 | ic->type = clock.type; |
---|
2237 | ic->flags = clock.flags; |
---|
2238 | ic->lastevent = clock.lastevent; |
---|
2239 | ic->currentstatus = clock.currentstatus; |
---|
2240 | ic->polls = htonl((u_int32)clock.polls); |
---|
2241 | ic->noresponse = htonl((u_int32)clock.noresponse); |
---|
2242 | ic->badformat = htonl((u_int32)clock.badformat); |
---|
2243 | ic->baddata = htonl((u_int32)clock.baddata); |
---|
2244 | ic->timestarted = htonl((u_int32)clock.timereset); |
---|
2245 | HTONL_FP(&clock.fudgetime1, &ic->fudgetime1); |
---|
2246 | HTONL_FP(&clock.fudgetime2, &ic->fudgetime2); |
---|
2247 | ic->fudgeval1 = htonl((u_int32)clock.fudgeval1); |
---|
2248 | ic->fudgeval2 = htonl((u_int32)clock.fudgeval2); |
---|
2249 | |
---|
2250 | free_varlist(clock.kv_list); |
---|
2251 | |
---|
2252 | ic = (struct info_clock *)more_pkt(); |
---|
2253 | } |
---|
2254 | flush_pkt(); |
---|
2255 | } |
---|
2256 | |
---|
2257 | |
---|
2258 | |
---|
2259 | /* |
---|
2260 | * set_clock_fudge - get a clock's fudge factors |
---|
2261 | */ |
---|
2262 | static void |
---|
2263 | set_clock_fudge(srcadr, inter, inpkt) |
---|
2264 | struct sockaddr_in *srcadr; |
---|
2265 | struct interface *inter; |
---|
2266 | struct req_pkt *inpkt; |
---|
2267 | { |
---|
2268 | register struct conf_fudge *cf; |
---|
2269 | register int items; |
---|
2270 | struct refclockstat clock; |
---|
2271 | struct sockaddr_in addr; |
---|
2272 | |
---|
2273 | memset((char *)&addr, 0, sizeof addr); |
---|
2274 | memset((char *)&clock, 0, sizeof clock); |
---|
2275 | addr.sin_family = AF_INET; |
---|
2276 | addr.sin_port = htons(NTP_PORT); |
---|
2277 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
2278 | cf = (struct conf_fudge *) inpkt->data; |
---|
2279 | |
---|
2280 | while (items-- > 0) { |
---|
2281 | addr.sin_addr.s_addr = cf->clockadr; |
---|
2282 | if (!ISREFCLOCKADR(&addr) || |
---|
2283 | findexistingpeer(&addr, (struct peer *)0) == 0) { |
---|
2284 | req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); |
---|
2285 | return; |
---|
2286 | } |
---|
2287 | |
---|
2288 | switch(ntohl(cf->which)) { |
---|
2289 | case FUDGE_TIME1: |
---|
2290 | NTOHL_FP(&cf->fudgetime, &clock.fudgetime1); |
---|
2291 | clock.haveflags = CLK_HAVETIME1; |
---|
2292 | break; |
---|
2293 | case FUDGE_TIME2: |
---|
2294 | NTOHL_FP(&cf->fudgetime, &clock.fudgetime2); |
---|
2295 | clock.haveflags = CLK_HAVETIME2; |
---|
2296 | break; |
---|
2297 | case FUDGE_VAL1: |
---|
2298 | clock.fudgeval1 = ntohl(cf->fudgeval_flags); |
---|
2299 | clock.haveflags = CLK_HAVEVAL1; |
---|
2300 | break; |
---|
2301 | case FUDGE_VAL2: |
---|
2302 | clock.fudgeval2 = ntohl(cf->fudgeval_flags); |
---|
2303 | clock.haveflags = CLK_HAVEVAL2; |
---|
2304 | break; |
---|
2305 | case FUDGE_FLAGS: |
---|
2306 | clock.flags = (u_char) ntohl(cf->fudgeval_flags) & 0xf; |
---|
2307 | clock.haveflags = |
---|
2308 | (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4); |
---|
2309 | break; |
---|
2310 | default: |
---|
2311 | req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); |
---|
2312 | return; |
---|
2313 | } |
---|
2314 | |
---|
2315 | refclock_control(&addr, &clock, (struct refclockstat *)0); |
---|
2316 | } |
---|
2317 | |
---|
2318 | req_ack(srcadr, inter, inpkt, INFO_OKAY); |
---|
2319 | } |
---|
2320 | #endif |
---|
2321 | |
---|
2322 | #ifdef REFCLOCK |
---|
2323 | /* |
---|
2324 | * get_clkbug_info - get debugging info about a clock |
---|
2325 | */ |
---|
2326 | static void |
---|
2327 | get_clkbug_info(srcadr, inter, inpkt) |
---|
2328 | struct sockaddr_in *srcadr; |
---|
2329 | struct interface *inter; |
---|
2330 | struct req_pkt *inpkt; |
---|
2331 | { |
---|
2332 | register int i; |
---|
2333 | register struct info_clkbug *ic; |
---|
2334 | register u_int32 *clkaddr; |
---|
2335 | register int items; |
---|
2336 | struct refclockbug bug; |
---|
2337 | struct sockaddr_in addr; |
---|
2338 | |
---|
2339 | memset((char *)&addr, 0, sizeof addr); |
---|
2340 | addr.sin_family = AF_INET; |
---|
2341 | addr.sin_port = htons(NTP_PORT); |
---|
2342 | items = INFO_NITEMS(inpkt->err_nitems); |
---|
2343 | clkaddr = (u_int32 *) inpkt->data; |
---|
2344 | |
---|
2345 | ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt, |
---|
2346 | sizeof(struct info_clkbug)); |
---|
2347 | |
---|
2348 | while (items-- > 0) { |
---|
2349 | addr.sin_addr.s_addr = *clkaddr++; |
---|
2350 | if (!ISREFCLOCKADR(&addr) || |
---|
2351 | findexistingpeer(&addr, (struct peer *)0) == 0) { |
---|
2352 | req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); |
---|
2353 | return; |
---|
2354 | } |
---|
2355 | |
---|
2356 | memset((char *)&bug, 0, sizeof bug); |
---|
2357 | refclock_buginfo(&addr, &bug); |
---|
2358 | if (bug.nvalues == 0 && bug.ntimes == 0) { |
---|
2359 | req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); |
---|
2360 | return; |
---|
2361 | } |
---|
2362 | |
---|
2363 | ic->clockadr = addr.sin_addr.s_addr; |
---|
2364 | i = bug.nvalues; |
---|
2365 | if (i > NUMCBUGVALUES) |
---|
2366 | i = NUMCBUGVALUES; |
---|
2367 | ic->nvalues = (u_char)i; |
---|
2368 | ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1))); |
---|
2369 | while (--i >= 0) |
---|
2370 | ic->values[i] = htonl(bug.values[i]); |
---|
2371 | |
---|
2372 | i = bug.ntimes; |
---|
2373 | if (i > NUMCBUGTIMES) |
---|
2374 | i = NUMCBUGTIMES; |
---|
2375 | ic->ntimes = (u_char)i; |
---|
2376 | ic->stimes = htonl(bug.stimes); |
---|
2377 | while (--i >= 0) { |
---|
2378 | HTONL_FP(&bug.times[i], &ic->times[i]); |
---|
2379 | } |
---|
2380 | |
---|
2381 | ic = (struct info_clkbug *)more_pkt(); |
---|
2382 | } |
---|
2383 | flush_pkt(); |
---|
2384 | } |
---|
2385 | #endif |
---|