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