]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ntp/ntpd/ntp_request.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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         static u_long soonest_ifrescan_time = 0;
1330         int items;
1331         u_int fl;
1332         struct conf_peer *cp; 
1333         struct conf_peer temp_cp;
1334         struct sockaddr_storage peeraddr;
1335         struct sockaddr_in tmp_clock;
1336
1337         /*
1338          * Do a check of everything to see that it looks
1339          * okay.  If not, complain about it.  Note we are
1340          * very picky here.
1341          */
1342         items = INFO_NITEMS(inpkt->err_nitems);
1343         cp = (struct conf_peer *)inpkt->data;
1344         memset(&temp_cp, 0, sizeof(struct conf_peer));
1345         memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
1346         fl = 0;
1347         while (items-- > 0 && !fl) {
1348                 if (((temp_cp.version) > NTP_VERSION)
1349                     || ((temp_cp.version) < NTP_OLDVERSION))
1350                     fl = 1;
1351                 if (temp_cp.hmode != MODE_ACTIVE
1352                     && temp_cp.hmode != MODE_CLIENT
1353                     && temp_cp.hmode != MODE_BROADCAST)
1354                     fl = 1;
1355                 if (temp_cp.flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER
1356                                   | CONF_FLAG_BURST | CONF_FLAG_IBURST | CONF_FLAG_SKEY))
1357                     fl = 1;
1358                 cp = (struct conf_peer *)
1359                     ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
1360         }
1361
1362         if (fl) {
1363                 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1364                 return;
1365         }
1366
1367         /*
1368          * Looks okay, try it out
1369          */
1370         items = INFO_NITEMS(inpkt->err_nitems);
1371         cp = (struct conf_peer *)inpkt->data;  
1372
1373         while (items-- > 0) {
1374                 memset(&temp_cp, 0, sizeof(struct conf_peer));
1375                 memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
1376                 memset((char *)&peeraddr, 0, sizeof(struct sockaddr_storage));
1377
1378                 fl = 0;
1379                 if (temp_cp.flags & CONF_FLAG_AUTHENABLE)
1380                         fl |= FLAG_AUTHENABLE;
1381                 if (temp_cp.flags & CONF_FLAG_PREFER)
1382                         fl |= FLAG_PREFER;
1383                 if (temp_cp.flags & CONF_FLAG_BURST)
1384                     fl |= FLAG_BURST;
1385                 if (temp_cp.flags & CONF_FLAG_IBURST)
1386                     fl |= FLAG_IBURST;
1387                 if (temp_cp.flags & CONF_FLAG_SKEY)
1388                         fl |= FLAG_SKEY;
1389                 
1390                 if (client_v6_capable && temp_cp.v6_flag != 0) {
1391                         peeraddr.ss_family = AF_INET6;
1392                         GET_INADDR6(peeraddr) = temp_cp.peeraddr6; 
1393                 } else {
1394                         peeraddr.ss_family = AF_INET;
1395                         GET_INADDR(peeraddr) = temp_cp.peeraddr;
1396                         /*
1397                          * Make sure the address is valid
1398                          */
1399                         tmp_clock = *CAST_V4(peeraddr);
1400                         if (
1401 #ifdef REFCLOCK
1402                                 !ISREFCLOCKADR(&tmp_clock) &&
1403 #endif
1404                                 ISBADADR(&tmp_clock)) {
1405                                 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1406                                 return;
1407                         }
1408
1409                 }
1410                 NSRCPORT(&peeraddr) = htons(NTP_PORT);
1411 #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
1412                 peeraddr.ss_len = SOCKLEN(&peeraddr);
1413 #endif
1414
1415                 /* XXX W2DO? minpoll/maxpoll arguments ??? */
1416                 if (peer_config(&peeraddr, (struct interface *)0,
1417                     temp_cp.hmode, temp_cp.version, temp_cp.minpoll, 
1418                     temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid,
1419                     NULL) == 0) {
1420                         req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1421                         return;
1422                 }
1423
1424                 /*
1425                  * ntp_intres.c uses REQ_CONFIG/doconf() to add each
1426                  * server after its name is resolved.  If we have been
1427                  * disconnected from the network, it may notice the
1428                  * network has returned and add the first server while
1429                  * the relevant interface is still disabled, awaiting
1430                  * the next interface rescan.  To get things moving
1431                  * more quickly, trigger an interface scan now, except
1432                  * if we have done so in the last half minute.
1433                  */
1434                 if (soonest_ifrescan_time < current_time) {
1435                         soonest_ifrescan_time = current_time + 30;
1436                         timer_interfacetimeout(current_time);
1437                         DPRINTF(1, ("do_conf triggering interface rescan\n"));
1438                 }
1439
1440                 cp = (struct conf_peer *)
1441                     ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
1442         }
1443
1444         req_ack(srcadr, inter, inpkt, INFO_OKAY);
1445 }
1446
1447 #if 0
1448 /* XXX */
1449 /*
1450  * dns_a - Snarf DNS info for an association ID
1451  */
1452 static void
1453 dns_a(
1454         struct sockaddr_storage *srcadr,
1455         struct interface *inter,
1456         struct req_pkt *inpkt
1457         )
1458 {
1459         register struct info_dns_assoc *dp;
1460         register int items;
1461         struct sockaddr_in peeraddr;
1462
1463         /*
1464          * Do a check of everything to see that it looks
1465          * okay.  If not, complain about it.  Note we are
1466          * very picky here.
1467          */
1468         items = INFO_NITEMS(inpkt->err_nitems);
1469         dp = (struct info_dns_assoc *)inpkt->data;
1470
1471         /*
1472          * Looks okay, try it out
1473          */
1474         items = INFO_NITEMS(inpkt->err_nitems);
1475         dp = (struct info_dns_assoc *)inpkt->data;
1476         memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in));
1477         peeraddr.sin_family = AF_INET;
1478         peeraddr.sin_port = htons(NTP_PORT);
1479
1480         /*
1481          * Make sure the address is valid
1482          */
1483         if (
1484 #ifdef REFCLOCK
1485                 !ISREFCLOCKADR(&peeraddr) &&
1486 #endif
1487                 ISBADADR(&peeraddr)) {
1488 #ifdef REFCLOCK
1489                 msyslog(LOG_ERR, "dns_a: !ISREFCLOCK && ISBADADR");
1490 #else
1491                 msyslog(LOG_ERR, "dns_a: ISBADADR");
1492 #endif
1493                 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1494                 return;
1495         }
1496
1497         while (items-- > 0) {
1498                 associd_t associd;
1499                 size_t hnl;
1500                 struct peer *peer;
1501                 int bogon = 0;
1502
1503                 associd = dp->associd;
1504                 peer = findpeerbyassoc(associd);
1505                 if (peer == 0 || peer->flags & FLAG_REFCLOCK) {
1506                         msyslog(LOG_ERR, "dns_a: %s",
1507                                 (peer == 0)
1508                                 ? "peer == 0"
1509                                 : "peer->flags & FLAG_REFCLOCK");
1510                         ++bogon;
1511                 }
1512                 peeraddr.sin_addr.s_addr = dp->peeraddr;
1513                 for (hnl = 0; dp->hostname[hnl] && hnl < sizeof dp->hostname; ++hnl) ;
1514                 if (hnl >= sizeof dp->hostname) {
1515                         msyslog(LOG_ERR, "dns_a: hnl (%ld) >= %ld",
1516                                 (long)hnl, (long)sizeof dp->hostname);
1517                         ++bogon;
1518                 }
1519
1520                 msyslog(LOG_INFO, "dns_a: <%s> for %s, AssocID %d, bogon %d",
1521                         dp->hostname,
1522                         stoa((struct sockaddr_storage *)&peeraddr), associd,
1523                         bogon);
1524
1525                 if (bogon) {
1526                         /* If it didn't work */
1527                         req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1528                         return;
1529                 } else {
1530 #if 0
1531 #ifdef PUBKEY
1532                         crypto_public(peer, dp->hostname);
1533 #endif /* PUBKEY */
1534 #endif
1535                 }
1536
1537                 dp++;
1538         }
1539
1540         req_ack(srcadr, inter, inpkt, INFO_OKAY);
1541 }
1542 #endif /* 0 */
1543
1544 /*
1545  * do_unconf - remove a peer from the configuration list
1546  */
1547 static void
1548 do_unconf(
1549         struct sockaddr_storage *srcadr,
1550         struct interface *inter,
1551         struct req_pkt *inpkt
1552         )
1553 {
1554         register struct conf_unpeer *cp;
1555         struct conf_unpeer temp_cp;
1556         register int items;
1557         register struct peer *peer;
1558         struct sockaddr_storage peeraddr;
1559         int bad, found;
1560
1561         /*
1562          * This is a bit unstructured, but I like to be careful.
1563          * We check to see that every peer exists and is actually
1564          * configured.  If so, we remove them.  If not, we return
1565          * an error.
1566          */
1567         items = INFO_NITEMS(inpkt->err_nitems);
1568         cp = (struct conf_unpeer *)inpkt->data;
1569
1570         bad = 0;
1571         while (items-- > 0 && !bad) {
1572                 memset(&temp_cp, 0, sizeof(temp_cp));
1573                 memset(&peeraddr, 0, sizeof(peeraddr));
1574                 memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
1575                 if (client_v6_capable && temp_cp.v6_flag != 0) {
1576                         peeraddr.ss_family = AF_INET6;
1577                         GET_INADDR6(peeraddr) = temp_cp.peeraddr6;
1578                 } else {
1579                         peeraddr.ss_family = AF_INET;
1580                         GET_INADDR(peeraddr) = temp_cp.peeraddr;
1581                 }
1582                 NSRCPORT(&peeraddr) = htons(NTP_PORT);
1583 #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
1584                 peeraddr.ss_len = SOCKLEN(&peeraddr);
1585 #endif
1586                 found = 0;
1587                 peer = (struct peer *)0;
1588 #ifdef DEBUG
1589                 if (debug)
1590                      printf("searching for %s\n", stoa(&peeraddr));
1591 #endif
1592                 while (!found) {
1593                         peer = findexistingpeer(&peeraddr, peer, -1);
1594                         if (peer == (struct peer *)0)
1595                             break;
1596                         if (peer->flags & FLAG_CONFIG)
1597                             found = 1;
1598                 }
1599                 if (!found)
1600                     bad = 1;
1601                 cp = (struct conf_unpeer *)
1602                     ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
1603         }
1604
1605         if (bad) {
1606                 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1607                 return;
1608         }
1609
1610         /*
1611          * Now do it in earnest.
1612          */
1613
1614         items = INFO_NITEMS(inpkt->err_nitems);
1615         cp = (struct conf_unpeer *)inpkt->data;
1616         while (items-- > 0) {
1617                 memset(&temp_cp, 0, sizeof(temp_cp));
1618                 memset(&peeraddr, 0, sizeof(peeraddr));
1619                 memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
1620                 if (client_v6_capable && temp_cp.v6_flag != 0) {
1621                         peeraddr.ss_family = AF_INET6;
1622                         GET_INADDR6(peeraddr) = temp_cp.peeraddr6;
1623                 } else {
1624                         peeraddr.ss_family = AF_INET;
1625                         GET_INADDR(peeraddr) = temp_cp.peeraddr;
1626                 }
1627                 NSRCPORT(&peeraddr) = htons(NTP_PORT);
1628 #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
1629                 peeraddr.ss_len = SOCKLEN(&peeraddr);
1630 #endif
1631                 peer_unconfig(&peeraddr, (struct interface *)0, -1);
1632                 cp = (struct conf_unpeer *)
1633                     ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
1634         }
1635
1636         req_ack(srcadr, inter, inpkt, INFO_OKAY);
1637 }
1638
1639
1640 /*
1641  * set_sys_flag - set system flags
1642  */
1643 static void
1644 set_sys_flag(
1645         struct sockaddr_storage *srcadr,
1646         struct interface *inter,
1647         struct req_pkt *inpkt
1648         )
1649 {
1650         setclr_flags(srcadr, inter, inpkt, 1);
1651 }
1652
1653
1654 /*
1655  * clr_sys_flag - clear system flags
1656  */
1657 static void
1658 clr_sys_flag(
1659         struct sockaddr_storage *srcadr,
1660         struct interface *inter,
1661         struct req_pkt *inpkt
1662         )
1663 {
1664         setclr_flags(srcadr, inter, inpkt, 0);
1665 }
1666
1667
1668 /*
1669  * setclr_flags - do the grunge work of flag setting/clearing
1670  */
1671 static void
1672 setclr_flags(
1673         struct sockaddr_storage *srcadr,
1674         struct interface *inter,
1675         struct req_pkt *inpkt,
1676         u_long set
1677         )
1678 {
1679         register u_int flags;
1680         int prev_kern_enable;
1681
1682         prev_kern_enable = kern_enable;
1683         if (INFO_NITEMS(inpkt->err_nitems) > 1) {
1684                 msyslog(LOG_ERR, "setclr_flags: err_nitems > 1");
1685                 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1686                 return;
1687         }
1688
1689         flags = ((struct conf_sys_flags *)inpkt->data)->flags;
1690         flags = ntohl(flags);
1691         
1692         if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
1693                       SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR |
1694                       SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) {
1695                 msyslog(LOG_ERR, "setclr_flags: extra flags: %#x",
1696                         flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
1697                                   SYS_FLAG_NTP | SYS_FLAG_KERNEL |
1698                                   SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN |
1699                                   SYS_FLAG_AUTH | SYS_FLAG_CAL));
1700                 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1701                 return;
1702         }
1703
1704         if (flags & SYS_FLAG_BCLIENT)
1705                 proto_config(PROTO_BROADCLIENT, set, 0., NULL);
1706         if (flags & SYS_FLAG_PPS)
1707                 proto_config(PROTO_PPS, set, 0., NULL);
1708         if (flags & SYS_FLAG_NTP)
1709                 proto_config(PROTO_NTP, set, 0., NULL);
1710         if (flags & SYS_FLAG_KERNEL)
1711                 proto_config(PROTO_KERNEL, set, 0., NULL);
1712         if (flags & SYS_FLAG_MONITOR)
1713                 proto_config(PROTO_MONITOR, set, 0., NULL);
1714         if (flags & SYS_FLAG_FILEGEN)
1715                 proto_config(PROTO_FILEGEN, set, 0., NULL);
1716         if (flags & SYS_FLAG_AUTH)
1717                 proto_config(PROTO_AUTHENTICATE, set, 0., NULL);
1718         if (flags & SYS_FLAG_CAL)
1719                 proto_config(PROTO_CAL, set, 0., NULL);
1720         req_ack(srcadr, inter, inpkt, INFO_OKAY);
1721
1722         /* Reset the kernel ntp parameters if the kernel flag changed. */
1723         if (prev_kern_enable && !kern_enable)
1724                 loop_config(LOOP_KERN_CLEAR, 0.0);
1725         if (!prev_kern_enable && kern_enable)
1726                 loop_config(LOOP_DRIFTCOMP, drift_comp);
1727 }
1728
1729
1730 /*
1731  * list_restrict - return the restrict list
1732  */
1733 static void
1734 list_restrict(
1735         struct sockaddr_storage *srcadr,
1736         struct interface *inter,
1737         struct req_pkt *inpkt
1738         )
1739 {
1740         register struct info_restrict *ir;
1741         register struct restrictlist *rl;
1742         register struct restrictlist6 *rl6;
1743
1744 #ifdef DEBUG
1745         if (debug > 2)
1746             printf("wants restrict list summary\n");
1747 #endif
1748
1749         ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt,
1750             v6sizeof(struct info_restrict));
1751         
1752         for (rl = restrictlist; rl != 0 && ir != 0; rl = rl->next) {
1753                 ir->addr = htonl(rl->addr);
1754                 if (client_v6_capable) 
1755                         ir->v6_flag = 0;
1756                 ir->mask = htonl(rl->mask);
1757                 ir->count = htonl((u_int32)rl->count);
1758                 ir->flags = htons(rl->flags);
1759                 ir->mflags = htons(rl->mflags);
1760                 ir = (struct info_restrict *)more_pkt();
1761         }
1762         if (client_v6_capable)
1763                 for (rl6 = restrictlist6; rl6 != 0 && ir != 0; rl6 = rl6->next) {
1764                         ir->addr6 = rl6->addr6;
1765                         ir->mask6 = rl6->mask6;
1766                         ir->v6_flag = 1;
1767                         ir->count = htonl((u_int32)rl6->count);
1768                         ir->flags = htons(rl6->flags);
1769                         ir->mflags = htons(rl6->mflags);
1770                         ir = (struct info_restrict *)more_pkt();
1771                 }
1772         flush_pkt();
1773 }
1774
1775
1776
1777 /*
1778  * do_resaddflags - add flags to a restrict entry (or create one)
1779  */
1780 static void
1781 do_resaddflags(
1782         struct sockaddr_storage *srcadr,
1783         struct interface *inter,
1784         struct req_pkt *inpkt
1785         )
1786 {
1787         do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS);
1788 }
1789
1790
1791
1792 /*
1793  * do_ressubflags - remove flags from a restrict entry
1794  */
1795 static void
1796 do_ressubflags(
1797         struct sockaddr_storage *srcadr,
1798         struct interface *inter,
1799         struct req_pkt *inpkt
1800         )
1801 {
1802         do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG);
1803 }
1804
1805
1806 /*
1807  * do_unrestrict - remove a restrict entry from the list
1808  */
1809 static void
1810 do_unrestrict(
1811         struct sockaddr_storage *srcadr,
1812         struct interface *inter,
1813         struct req_pkt *inpkt
1814         )
1815 {
1816         do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE);
1817 }
1818
1819
1820
1821
1822
1823 /*
1824  * do_restrict - do the dirty stuff of dealing with restrictions
1825  */
1826 static void
1827 do_restrict(
1828         struct sockaddr_storage *srcadr,
1829         struct interface *inter,
1830         struct req_pkt *inpkt,
1831         int op
1832         )
1833 {
1834         register struct conf_restrict *cr;
1835         register int items;
1836         struct sockaddr_storage matchaddr;
1837         struct sockaddr_storage matchmask;
1838         int bad;
1839
1840         /*
1841          * Do a check of the flags to make sure that only
1842          * the NTPPORT flag is set, if any.  If not, complain
1843          * about it.  Note we are very picky here.
1844          */
1845         items = INFO_NITEMS(inpkt->err_nitems);
1846         cr = (struct conf_restrict *)inpkt->data;
1847
1848         bad = 0;
1849         cr->flags = ntohs(cr->flags);
1850         cr->mflags = ntohs(cr->mflags);
1851         while (items-- > 0 && !bad) {
1852                 if (cr->mflags & ~(RESM_NTPONLY))
1853                     bad |= 1;
1854                 if (cr->flags & ~(RES_ALLFLAGS))
1855                     bad |= 2;
1856                 if (cr->mask != htonl(INADDR_ANY)) {
1857                         if (client_v6_capable && cr->v6_flag != 0) {
1858                                 if (IN6_IS_ADDR_UNSPECIFIED(&cr->addr6))
1859                                         bad |= 4;
1860                         } else
1861                                 if (cr->addr == htonl(INADDR_ANY))
1862                                         bad |= 8;
1863                 }
1864                 cr = (struct conf_restrict *)((char *)cr +
1865                     INFO_ITEMSIZE(inpkt->mbz_itemsize));
1866         }
1867
1868         if (bad) {
1869                 msyslog(LOG_ERR, "do_restrict: bad = %#x", bad);
1870                 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
1871                 return;
1872         }
1873
1874         /*
1875          * Looks okay, try it out
1876          */
1877         items = INFO_NITEMS(inpkt->err_nitems);
1878         cr = (struct conf_restrict *)inpkt->data;
1879         memset((char *)&matchaddr, 0, sizeof(struct sockaddr_storage));
1880         memset((char *)&matchmask, 0, sizeof(struct sockaddr_storage));
1881
1882         while (items-- > 0) {
1883                 if (client_v6_capable && cr->v6_flag != 0) {
1884                         GET_INADDR6(matchaddr) = cr->addr6;
1885                         GET_INADDR6(matchmask) = cr->mask6;
1886                         matchaddr.ss_family = AF_INET6;
1887                         matchmask.ss_family = AF_INET6;
1888                 } else {
1889                         GET_INADDR(matchaddr) = cr->addr;
1890                         GET_INADDR(matchmask) = cr->mask;
1891                         matchaddr.ss_family = AF_INET;
1892                         matchmask.ss_family = AF_INET;
1893                 }
1894                 hack_restrict(op, &matchaddr, &matchmask, cr->mflags,
1895                          cr->flags);
1896                 cr++;
1897         }
1898
1899         req_ack(srcadr, inter, inpkt, INFO_OKAY);
1900 }
1901
1902
1903 /*
1904  * mon_getlist - return monitor data
1905  */
1906 static void
1907 mon_getlist_0(
1908         struct sockaddr_storage *srcadr,
1909         struct interface *inter,
1910         struct req_pkt *inpkt
1911         )
1912 {
1913         register struct info_monitor *im;
1914         register struct mon_data *md;
1915         extern struct mon_data mon_mru_list;
1916         extern int mon_enabled;
1917
1918 #ifdef DEBUG
1919         if (debug > 2)
1920             printf("wants monitor 0 list\n");
1921 #endif
1922         if (!mon_enabled) {
1923                 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1924                 return;
1925         }
1926         im = (struct info_monitor *)prepare_pkt(srcadr, inter, inpkt,
1927             v6sizeof(struct info_monitor));
1928         for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0;
1929              md = md->mru_next) {
1930                 im->lasttime = htonl((u_int32)md->avg_interval);
1931                 im->firsttime = htonl((u_int32)(current_time - md->lasttime));
1932                 im->lastdrop = htonl((u_int32)md->drop_count);
1933                 im->count = htonl((u_int32)(md->count));
1934                 if (md->rmtadr.ss_family == AF_INET6) {
1935                         if (!client_v6_capable)
1936                                 continue;
1937                         im->addr6 = GET_INADDR6(md->rmtadr);
1938                         im->v6_flag = 1;
1939                 } else {
1940                         im->addr = GET_INADDR(md->rmtadr);
1941                         if (client_v6_capable)
1942                                 im->v6_flag = 0;
1943                 }
1944                 im->port = md->rmtport;
1945                 im->mode = md->mode;
1946                 im->version = md->version;
1947                 im = (struct info_monitor *)more_pkt();
1948         }
1949         flush_pkt();
1950 }
1951
1952 /*
1953  * mon_getlist - return monitor data
1954  */
1955 static void
1956 mon_getlist_1(
1957         struct sockaddr_storage *srcadr,
1958         struct interface *inter,
1959         struct req_pkt *inpkt
1960         )
1961 {
1962         register struct info_monitor_1 *im;
1963         register struct mon_data *md;
1964         extern struct mon_data mon_mru_list;
1965         extern int mon_enabled;
1966
1967         if (!mon_enabled) {
1968                 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
1969                 return;
1970         }
1971         im = (struct info_monitor_1 *)prepare_pkt(srcadr, inter, inpkt,
1972             v6sizeof(struct info_monitor_1));
1973         for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0;
1974              md = md->mru_next) {
1975                 im->lasttime = htonl((u_int32)md->avg_interval);
1976                 im->firsttime = htonl((u_int32)(current_time - md->lasttime));
1977                 im->lastdrop = htonl((u_int32)md->drop_count);
1978                 im->count = htonl((u_int32)md->count);
1979                 if (md->rmtadr.ss_family == AF_INET6) {
1980                         if (!client_v6_capable)
1981                                 continue;
1982                         im->addr6 = GET_INADDR6(md->rmtadr);
1983                         im->v6_flag = 1;
1984                         im->daddr6 = GET_INADDR6(md->interface->sin);
1985                 } else {
1986                         im->addr = GET_INADDR(md->rmtadr);
1987                         if (client_v6_capable)
1988                                 im->v6_flag = 0;
1989                         im->daddr = (md->cast_flags == MDF_BCAST)  
1990                                 ? GET_INADDR(md->interface->bcast) 
1991                                 : (md->cast_flags 
1992                                 ? (GET_INADDR(md->interface->sin)
1993                                 ? GET_INADDR(md->interface->sin)
1994                                 : GET_INADDR(md->interface->bcast))
1995                                 : 4);
1996                 }
1997                 im->flags = htonl(md->cast_flags);
1998                 im->port = md->rmtport;
1999                 im->mode = md->mode;
2000                 im->version = md->version;
2001                 im = (struct info_monitor_1 *)more_pkt();
2002         }
2003         flush_pkt();
2004 }
2005
2006 /*
2007  * Module entry points and the flags they correspond with
2008  */
2009 struct reset_entry {
2010         int flag;               /* flag this corresponds to */
2011         void (*handler) P((void)); /* routine to handle request */
2012 };
2013
2014 struct reset_entry reset_entries[] = {
2015         { RESET_FLAG_ALLPEERS,  peer_all_reset },
2016         { RESET_FLAG_IO,        io_clr_stats },
2017         { RESET_FLAG_SYS,       proto_clr_stats },
2018         { RESET_FLAG_MEM,       peer_clr_stats },
2019         { RESET_FLAG_TIMER,     timer_clr_stats },
2020         { RESET_FLAG_AUTH,      reset_auth_stats },
2021         { RESET_FLAG_CTL,       ctl_clr_stats },
2022         { 0,                    0 }
2023 };
2024
2025 /*
2026  * reset_stats - reset statistic counters here and there
2027  */
2028 static void
2029 reset_stats(
2030         struct sockaddr_storage *srcadr,
2031         struct interface *inter,
2032         struct req_pkt *inpkt
2033         )
2034 {
2035         u_long flags;
2036         struct reset_entry *rent;
2037
2038         if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2039                 msyslog(LOG_ERR, "reset_stats: err_nitems > 1");
2040                 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2041                 return;
2042         }
2043
2044         flags = ((struct reset_flags *)inpkt->data)->flags;
2045         flags = ntohl(flags);
2046      
2047         if (flags & ~RESET_ALLFLAGS) {
2048                 msyslog(LOG_ERR, "reset_stats: reset leaves %#lx",
2049                         flags & ~RESET_ALLFLAGS);
2050                 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2051                 return;
2052         }
2053
2054         for (rent = reset_entries; rent->flag != 0; rent++) {
2055                 if (flags & rent->flag)
2056                     (rent->handler)();
2057         }
2058         req_ack(srcadr, inter, inpkt, INFO_OKAY);
2059 }
2060
2061
2062 /*
2063  * reset_peer - clear a peer's statistics
2064  */
2065 static void
2066 reset_peer(
2067         struct sockaddr_storage *srcadr,
2068         struct interface *inter,
2069         struct req_pkt *inpkt
2070         )
2071 {
2072         register struct conf_unpeer *cp;
2073         register int items;
2074         register struct peer *peer;
2075         struct sockaddr_storage peeraddr;
2076         int bad;
2077
2078         /*
2079          * We check first to see that every peer exists.  If not,
2080          * we return an error.
2081          */
2082
2083         items = INFO_NITEMS(inpkt->err_nitems);
2084         cp = (struct conf_unpeer *)inpkt->data;
2085
2086         bad = 0;
2087         while (items-- > 0 && !bad) {
2088                 memset((char *)&peeraddr, 0, sizeof(peeraddr));
2089                 if (client_v6_capable && cp->v6_flag != 0) {
2090                         GET_INADDR6(peeraddr) = cp->peeraddr6;
2091                         peeraddr.ss_family = AF_INET6;
2092                 } else {
2093                         GET_INADDR(peeraddr) = cp->peeraddr;
2094                         peeraddr.ss_family = AF_INET;
2095                 }
2096                 NSRCPORT(&peeraddr) = htons(NTP_PORT);
2097 #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
2098                 peeraddr.ss_len = SOCKLEN(&peeraddr);
2099 #endif
2100                 peer = findexistingpeer(&peeraddr, (struct peer *)0, -1);
2101                 if (peer == (struct peer *)0)
2102                     bad++;
2103                 cp = (struct conf_unpeer *)((char *)cp +
2104                     INFO_ITEMSIZE(inpkt->mbz_itemsize));
2105         }
2106
2107         if (bad) {
2108                 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2109                 return;
2110         }
2111
2112         /*
2113          * Now do it in earnest.
2114          */
2115
2116         items = INFO_NITEMS(inpkt->err_nitems);
2117         cp = (struct conf_unpeer *)inpkt->data;
2118         while (items-- > 0) {
2119                 memset((char *)&peeraddr, 0, sizeof(peeraddr));
2120                 if (client_v6_capable && cp->v6_flag != 0) {
2121                         GET_INADDR6(peeraddr) = cp->peeraddr6;
2122                         peeraddr.ss_family = AF_INET6;
2123                 } else {
2124                         GET_INADDR(peeraddr) = cp->peeraddr;
2125                         peeraddr.ss_family = AF_INET;
2126                 }
2127 #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
2128                 peeraddr.ss_len = SOCKLEN(&peeraddr);
2129 #endif
2130                 peer = findexistingpeer(&peeraddr, (struct peer *)0, -1);
2131                 while (peer != 0) {
2132                         peer_reset(peer);
2133                         peer = findexistingpeer(&peeraddr, (struct peer *)peer, -1);
2134                 }
2135                 cp = (struct conf_unpeer *)((char *)cp +
2136                     INFO_ITEMSIZE(inpkt->mbz_itemsize));
2137         }
2138
2139         req_ack(srcadr, inter, inpkt, INFO_OKAY);
2140 }
2141
2142
2143 /*
2144  * do_key_reread - reread the encryption key file
2145  */
2146 static void
2147 do_key_reread(
2148         struct sockaddr_storage *srcadr,
2149         struct interface *inter,
2150         struct req_pkt *inpkt
2151         )
2152 {
2153         rereadkeys();
2154         req_ack(srcadr, inter, inpkt, INFO_OKAY);
2155 }
2156
2157
2158 /*
2159  * trust_key - make one or more keys trusted
2160  */
2161 static void
2162 trust_key(
2163         struct sockaddr_storage *srcadr,
2164         struct interface *inter,
2165         struct req_pkt *inpkt
2166         )
2167 {
2168         do_trustkey(srcadr, inter, inpkt, 1);
2169 }
2170
2171
2172 /*
2173  * untrust_key - make one or more keys untrusted
2174  */
2175 static void
2176 untrust_key(
2177         struct sockaddr_storage *srcadr,
2178         struct interface *inter,
2179         struct req_pkt *inpkt
2180         )
2181 {
2182         do_trustkey(srcadr, inter, inpkt, 0);
2183 }
2184
2185
2186 /*
2187  * do_trustkey - make keys either trustable or untrustable
2188  */
2189 static void
2190 do_trustkey(
2191         struct sockaddr_storage *srcadr,
2192         struct interface *inter,
2193         struct req_pkt *inpkt,
2194         u_long trust
2195         )
2196 {
2197         register u_long *kp;
2198         register int items;
2199
2200         items = INFO_NITEMS(inpkt->err_nitems);
2201         kp = (u_long *)inpkt->data;
2202         while (items-- > 0) {
2203                 authtrust(*kp, trust);
2204                 kp++;
2205         }
2206
2207         req_ack(srcadr, inter, inpkt, INFO_OKAY);
2208 }
2209
2210
2211 /*
2212  * get_auth_info - return some stats concerning the authentication module
2213  */
2214 static void
2215 get_auth_info(
2216         struct sockaddr_storage *srcadr,
2217         struct interface *inter,
2218         struct req_pkt *inpkt
2219         )
2220 {
2221         register struct info_auth *ia;
2222
2223         /*
2224          * Importations from the authentication module
2225          */
2226         extern u_long authnumkeys;
2227         extern int authnumfreekeys;
2228         extern u_long authkeylookups;
2229         extern u_long authkeynotfound;
2230         extern u_long authencryptions;
2231         extern u_long authdecryptions;
2232         extern u_long authkeyuncached;
2233         extern u_long authkeyexpired;
2234
2235         ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt,
2236                                              sizeof(struct info_auth));
2237
2238         ia->numkeys = htonl((u_int32)authnumkeys);
2239         ia->numfreekeys = htonl((u_int32)authnumfreekeys);
2240         ia->keylookups = htonl((u_int32)authkeylookups);
2241         ia->keynotfound = htonl((u_int32)authkeynotfound);
2242         ia->encryptions = htonl((u_int32)authencryptions);
2243         ia->decryptions = htonl((u_int32)authdecryptions);
2244         ia->keyuncached = htonl((u_int32)authkeyuncached);
2245         ia->expired = htonl((u_int32)authkeyexpired);
2246         ia->timereset = htonl((u_int32)(current_time - auth_timereset));
2247         
2248         (void) more_pkt();
2249         flush_pkt();
2250 }
2251
2252
2253
2254 /*
2255  * reset_auth_stats - reset the authentication stat counters.  Done here
2256  *                    to keep ntp-isms out of the authentication module
2257  */
2258 static void
2259 reset_auth_stats(void)
2260 {
2261         /*
2262          * Importations from the authentication module
2263          */
2264         extern u_long authkeylookups;
2265         extern u_long authkeynotfound;
2266         extern u_long authencryptions;
2267         extern u_long authdecryptions;
2268         extern u_long authkeyuncached;
2269
2270         authkeylookups = 0;
2271         authkeynotfound = 0;
2272         authencryptions = 0;
2273         authdecryptions = 0;
2274         authkeyuncached = 0;
2275         auth_timereset = current_time;
2276 }
2277
2278
2279 /*
2280  * req_get_traps - return information about current trap holders
2281  */
2282 static void
2283 req_get_traps(
2284         struct sockaddr_storage *srcadr,
2285         struct interface *inter,
2286         struct req_pkt *inpkt
2287         )
2288 {
2289         register struct info_trap *it;
2290         register struct ctl_trap *tr;
2291         register int i;
2292
2293         /*
2294          * Imported from the control module
2295          */
2296         extern struct ctl_trap ctl_trap[];
2297         extern int num_ctl_traps;
2298
2299         if (num_ctl_traps == 0) {
2300                 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2301                 return;
2302         }
2303
2304         it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt,
2305             v6sizeof(struct info_trap));
2306
2307         for (i = 0, tr = ctl_trap; i < CTL_MAXTRAPS; i++, tr++) {
2308                 if (tr->tr_flags & TRAP_INUSE) {
2309                         if (tr->tr_addr.ss_family == AF_INET) {
2310                                 if (tr->tr_localaddr == any_interface)
2311                                         it->local_address = 0;
2312                                 else
2313                                         it->local_address
2314                                             = GET_INADDR(tr->tr_localaddr->sin);
2315                                 it->trap_address = GET_INADDR(tr->tr_addr);
2316                                 if (client_v6_capable)
2317                                         it->v6_flag = 0;
2318                         } else {
2319                                 if (!client_v6_capable)
2320                                         continue;
2321                                 it->local_address6 
2322                                     = GET_INADDR6(tr->tr_localaddr->sin);
2323                                 it->trap_address6 = GET_INADDR6(tr->tr_addr);
2324                                 it->v6_flag = 1;
2325                         }
2326                         it->trap_port = NSRCPORT(&tr->tr_addr);
2327                         it->sequence = htons(tr->tr_sequence);
2328                         it->settime = htonl((u_int32)(current_time - tr->tr_settime));
2329                         it->origtime = htonl((u_int32)(current_time - tr->tr_origtime));
2330                         it->resets = htonl((u_int32)tr->tr_resets);
2331                         it->flags = htonl((u_int32)tr->tr_flags);
2332                         it = (struct info_trap *)more_pkt();
2333                 }
2334         }
2335         flush_pkt();
2336 }
2337
2338
2339 /*
2340  * req_set_trap - configure a trap
2341  */
2342 static void
2343 req_set_trap(
2344         struct sockaddr_storage *srcadr,
2345         struct interface *inter,
2346         struct req_pkt *inpkt
2347         )
2348 {
2349         do_setclr_trap(srcadr, inter, inpkt, 1);
2350 }
2351
2352
2353
2354 /*
2355  * req_clr_trap - unconfigure a trap
2356  */
2357 static void
2358 req_clr_trap(
2359         struct sockaddr_storage *srcadr,
2360         struct interface *inter,
2361         struct req_pkt *inpkt
2362         )
2363 {
2364         do_setclr_trap(srcadr, inter, inpkt, 0);
2365 }
2366
2367
2368
2369 /*
2370  * do_setclr_trap - do the grunge work of (un)configuring a trap
2371  */
2372 static void
2373 do_setclr_trap(
2374         struct sockaddr_storage *srcadr,
2375         struct interface *inter,
2376         struct req_pkt *inpkt,
2377         int set
2378         )
2379 {
2380         register struct conf_trap *ct;
2381         register struct interface *linter;
2382         int res;
2383         struct sockaddr_storage laddr;
2384
2385         /*
2386          * Prepare sockaddr_storage structure
2387          */
2388         memset((char *)&laddr, 0, sizeof laddr);
2389         laddr.ss_family = srcadr->ss_family;
2390         NSRCPORT(&laddr) = ntohs(NTP_PORT);
2391
2392         /*
2393          * Restrict ourselves to one item only.  This eliminates
2394          * the error reporting problem.
2395          */
2396         if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2397                 msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1");
2398                 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2399                 return;
2400         }
2401         ct = (struct conf_trap *)inpkt->data;
2402
2403         /*
2404          * Look for the local interface.  If none, use the default.
2405          */
2406         if (ct->local_address == 0) {
2407                 linter = any_interface;
2408         } else {
2409                 if (laddr.ss_family == AF_INET)
2410                         GET_INADDR(laddr) = ct->local_address;
2411                 else
2412                         GET_INADDR6(laddr) = ct->local_address6;
2413                 linter = findinterface(&laddr);
2414                 if (linter == NULL) {
2415                         req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2416                         return;
2417                 }
2418         }
2419
2420         if (laddr.ss_family == AF_INET)
2421                 GET_INADDR(laddr) = ct->trap_address;
2422         else
2423                 GET_INADDR6(laddr) = ct->trap_address6;
2424         if (ct->trap_port != 0)
2425             NSRCPORT(&laddr) = ct->trap_port;
2426         else
2427             NSRCPORT(&laddr) = htons(TRAPPORT);
2428
2429         if (set) {
2430                 res = ctlsettrap(&laddr, linter, 0,
2431                                  INFO_VERSION(inpkt->rm_vn_mode));
2432         } else {
2433                 res = ctlclrtrap(&laddr, linter, 0);
2434         }
2435
2436         if (!res) {
2437                 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2438         } else {
2439                 req_ack(srcadr, inter, inpkt, INFO_OKAY);
2440         }
2441         return;
2442 }
2443
2444
2445
2446 /*
2447  * set_request_keyid - set the keyid used to authenticate requests
2448  */
2449 static void
2450 set_request_keyid(
2451         struct sockaddr_storage *srcadr,
2452         struct interface *inter,
2453         struct req_pkt *inpkt
2454         )
2455 {
2456         keyid_t keyid;
2457
2458         /*
2459          * Restrict ourselves to one item only.
2460          */
2461         if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2462                 msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1");
2463                 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2464                 return;
2465         }
2466
2467         keyid = ntohl(*((u_int32 *)(inpkt->data)));
2468         info_auth_keyid = keyid;
2469         req_ack(srcadr, inter, inpkt, INFO_OKAY);
2470 }
2471
2472
2473
2474 /*
2475  * set_control_keyid - set the keyid used to authenticate requests
2476  */
2477 static void
2478 set_control_keyid(
2479         struct sockaddr_storage *srcadr,
2480         struct interface *inter,
2481         struct req_pkt *inpkt
2482         )
2483 {
2484         keyid_t keyid;
2485         extern keyid_t ctl_auth_keyid;
2486
2487         /*
2488          * Restrict ourselves to one item only.
2489          */
2490         if (INFO_NITEMS(inpkt->err_nitems) > 1) {
2491                 msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1");
2492                 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2493                 return;
2494         }
2495
2496         keyid = ntohl(*((u_int32 *)(inpkt->data)));
2497         ctl_auth_keyid = keyid;
2498         req_ack(srcadr, inter, inpkt, INFO_OKAY);
2499 }
2500
2501
2502
2503 /*
2504  * get_ctl_stats - return some stats concerning the control message module
2505  */
2506 static void
2507 get_ctl_stats(
2508         struct sockaddr_storage *srcadr,
2509         struct interface *inter,
2510         struct req_pkt *inpkt
2511         )
2512 {
2513         register struct info_control *ic;
2514
2515         /*
2516          * Importations from the control module
2517          */
2518         extern u_long ctltimereset;
2519         extern u_long numctlreq;
2520         extern u_long numctlbadpkts;
2521         extern u_long numctlresponses;
2522         extern u_long numctlfrags;
2523         extern u_long numctlerrors;
2524         extern u_long numctltooshort;
2525         extern u_long numctlinputresp;
2526         extern u_long numctlinputfrag;
2527         extern u_long numctlinputerr;
2528         extern u_long numctlbadoffset;
2529         extern u_long numctlbadversion;
2530         extern u_long numctldatatooshort;
2531         extern u_long numctlbadop;
2532         extern u_long numasyncmsgs;
2533
2534         ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt,
2535                                                 sizeof(struct info_control));
2536
2537         ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset));
2538         ic->numctlreq = htonl((u_int32)numctlreq);
2539         ic->numctlbadpkts = htonl((u_int32)numctlbadpkts);
2540         ic->numctlresponses = htonl((u_int32)numctlresponses);
2541         ic->numctlfrags = htonl((u_int32)numctlfrags);
2542         ic->numctlerrors = htonl((u_int32)numctlerrors);
2543         ic->numctltooshort = htonl((u_int32)numctltooshort);
2544         ic->numctlinputresp = htonl((u_int32)numctlinputresp);
2545         ic->numctlinputfrag = htonl((u_int32)numctlinputfrag);
2546         ic->numctlinputerr = htonl((u_int32)numctlinputerr);
2547         ic->numctlbadoffset = htonl((u_int32)numctlbadoffset);
2548         ic->numctlbadversion = htonl((u_int32)numctlbadversion);
2549         ic->numctldatatooshort = htonl((u_int32)numctldatatooshort);
2550         ic->numctlbadop = htonl((u_int32)numctlbadop);
2551         ic->numasyncmsgs = htonl((u_int32)numasyncmsgs);
2552
2553         (void) more_pkt();
2554         flush_pkt();
2555 }
2556
2557
2558 #ifdef KERNEL_PLL
2559 /*
2560  * get_kernel_info - get kernel pll/pps information
2561  */
2562 static void
2563 get_kernel_info(
2564         struct sockaddr_storage *srcadr,
2565         struct interface *inter,
2566         struct req_pkt *inpkt
2567         )
2568 {
2569         register struct info_kernel *ik;
2570         struct timex ntx;
2571
2572         if (!pll_control) {
2573                 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2574                 return;
2575         }
2576
2577         memset((char *)&ntx, 0, sizeof(ntx));
2578         if (ntp_adjtime(&ntx) < 0)
2579                 msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m");
2580         ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt,
2581             sizeof(struct info_kernel));
2582
2583         /*
2584          * pll variables
2585          */
2586         ik->offset = htonl((u_int32)ntx.offset);
2587         ik->freq = htonl((u_int32)ntx.freq);
2588         ik->maxerror = htonl((u_int32)ntx.maxerror);
2589         ik->esterror = htonl((u_int32)ntx.esterror);
2590         ik->status = htons(ntx.status);
2591         ik->constant = htonl((u_int32)ntx.constant);
2592         ik->precision = htonl((u_int32)ntx.precision);
2593         ik->tolerance = htonl((u_int32)ntx.tolerance);
2594
2595         /*
2596          * pps variables
2597          */
2598         ik->ppsfreq = htonl((u_int32)ntx.ppsfreq);
2599         ik->jitter = htonl((u_int32)ntx.jitter);
2600         ik->shift = htons(ntx.shift);
2601         ik->stabil = htonl((u_int32)ntx.stabil);
2602         ik->jitcnt = htonl((u_int32)ntx.jitcnt);
2603         ik->calcnt = htonl((u_int32)ntx.calcnt);
2604         ik->errcnt = htonl((u_int32)ntx.errcnt);
2605         ik->stbcnt = htonl((u_int32)ntx.stbcnt);
2606         
2607         (void) more_pkt();
2608         flush_pkt();
2609 }
2610 #endif /* KERNEL_PLL */
2611
2612
2613 #ifdef REFCLOCK
2614 /*
2615  * get_clock_info - get info about a clock
2616  */
2617 static void
2618 get_clock_info(
2619         struct sockaddr_storage *srcadr,
2620         struct interface *inter,
2621         struct req_pkt *inpkt
2622         )
2623 {
2624         register struct info_clock *ic;
2625         register u_int32 *clkaddr;
2626         register int items;
2627         struct refclockstat clock_stat;
2628         struct sockaddr_storage addr;
2629         struct sockaddr_in tmp_clock;
2630         l_fp ltmp;
2631
2632         memset((char *)&addr, 0, sizeof addr);
2633         addr.ss_family = AF_INET;
2634 #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
2635         addr.ss_len = SOCKLEN(&addr);
2636 #endif
2637         NSRCPORT(&addr) = htons(NTP_PORT);
2638         items = INFO_NITEMS(inpkt->err_nitems);
2639         clkaddr = (u_int32 *) inpkt->data;
2640
2641         ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt,
2642                                               sizeof(struct info_clock));
2643
2644         while (items-- > 0) {
2645                 tmp_clock.sin_addr.s_addr = *clkaddr++;
2646                 CAST_V4(addr)->sin_addr = tmp_clock.sin_addr;
2647                 if (!ISREFCLOCKADR(&tmp_clock) ||
2648                     findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
2649                         req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2650                         return;
2651                 }
2652
2653                 clock_stat.kv_list = (struct ctl_var *)0;
2654
2655                 refclock_control(&addr, (struct refclockstat *)0, &clock_stat);
2656
2657                 ic->clockadr = tmp_clock.sin_addr.s_addr;
2658                 ic->type = clock_stat.type;
2659                 ic->flags = clock_stat.flags;
2660                 ic->lastevent = clock_stat.lastevent;
2661                 ic->currentstatus = clock_stat.currentstatus;
2662                 ic->polls = htonl((u_int32)clock_stat.polls);
2663                 ic->noresponse = htonl((u_int32)clock_stat.noresponse);
2664                 ic->badformat = htonl((u_int32)clock_stat.badformat);
2665                 ic->baddata = htonl((u_int32)clock_stat.baddata);
2666                 ic->timestarted = htonl((u_int32)clock_stat.timereset);
2667                 DTOLFP(clock_stat.fudgetime1, &ltmp);
2668                 HTONL_FP(&ltmp, &ic->fudgetime1);
2669                 DTOLFP(clock_stat.fudgetime2, &ltmp);
2670                 HTONL_FP(&ltmp, &ic->fudgetime2);
2671                 ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1);
2672                 ic->fudgeval2 = htonl((u_int32)clock_stat.fudgeval2);
2673
2674                 free_varlist(clock_stat.kv_list);
2675
2676                 ic = (struct info_clock *)more_pkt();
2677         }
2678         flush_pkt();
2679 }
2680
2681
2682
2683 /*
2684  * set_clock_fudge - get a clock's fudge factors
2685  */
2686 static void
2687 set_clock_fudge(
2688         struct sockaddr_storage *srcadr,
2689         struct interface *inter,
2690         struct req_pkt *inpkt
2691         )
2692 {
2693         register struct conf_fudge *cf;
2694         register int items;
2695         struct refclockstat clock_stat;
2696         struct sockaddr_storage addr;
2697         struct sockaddr_in tmp_clock;
2698         l_fp ltmp;
2699
2700         memset((char *)&addr, 0, sizeof addr);
2701         memset((char *)&clock_stat, 0, sizeof clock_stat);
2702         items = INFO_NITEMS(inpkt->err_nitems);
2703         cf = (struct conf_fudge *) inpkt->data;
2704
2705         while (items-- > 0) {
2706                 tmp_clock.sin_addr.s_addr = cf->clockadr;
2707                 *CAST_V4(addr) = tmp_clock;
2708                 addr.ss_family = AF_INET;
2709 #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
2710                 addr.ss_len = SOCKLEN(&addr);
2711 #endif
2712                 NSRCPORT(&addr) = htons(NTP_PORT);
2713                 if (!ISREFCLOCKADR(&tmp_clock) ||
2714                     findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
2715                         req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2716                         return;
2717                 }
2718
2719                 switch(ntohl(cf->which)) {
2720                     case FUDGE_TIME1:
2721                         NTOHL_FP(&cf->fudgetime, &ltmp);
2722                         LFPTOD(&ltmp, clock_stat.fudgetime1);
2723                         clock_stat.haveflags = CLK_HAVETIME1;
2724                         break;
2725                     case FUDGE_TIME2:
2726                         NTOHL_FP(&cf->fudgetime, &ltmp);
2727                         LFPTOD(&ltmp, clock_stat.fudgetime2);
2728                         clock_stat.haveflags = CLK_HAVETIME2;
2729                         break;
2730                     case FUDGE_VAL1:
2731                         clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags);
2732                         clock_stat.haveflags = CLK_HAVEVAL1;
2733                         break;
2734                     case FUDGE_VAL2:
2735                         clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags);
2736                         clock_stat.haveflags = CLK_HAVEVAL2;
2737                         break;
2738                     case FUDGE_FLAGS:
2739                         clock_stat.flags = (u_char) (ntohl(cf->fudgeval_flags) & 0xf);
2740                         clock_stat.haveflags =
2741                                 (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4);
2742                         break;
2743                     default:
2744                         msyslog(LOG_ERR, "set_clock_fudge: default!");
2745                         req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
2746                         return;
2747                 }
2748
2749                 refclock_control(&addr, &clock_stat, (struct refclockstat *)0);
2750         }
2751
2752         req_ack(srcadr, inter, inpkt, INFO_OKAY);
2753 }
2754 #endif
2755
2756 #ifdef REFCLOCK
2757 /*
2758  * get_clkbug_info - get debugging info about a clock
2759  */
2760 static void
2761 get_clkbug_info(
2762         struct sockaddr_storage *srcadr,
2763         struct interface *inter,
2764         struct req_pkt *inpkt
2765         )
2766 {
2767         register int i;
2768         register struct info_clkbug *ic;
2769         register u_int32 *clkaddr;
2770         register int items;
2771         struct refclockbug bug;
2772         struct sockaddr_storage addr;
2773         struct sockaddr_in tmp_clock;
2774
2775         memset((char *)&addr, 0, sizeof addr);
2776         addr.ss_family = AF_INET;
2777 #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
2778         addr.ss_len = SOCKLEN(&addr);
2779 #endif
2780         NSRCPORT(&addr) = htons(NTP_PORT);
2781         items = INFO_NITEMS(inpkt->err_nitems);
2782         clkaddr = (u_int32 *) inpkt->data;
2783
2784         ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt,
2785                                                sizeof(struct info_clkbug));
2786
2787         while (items-- > 0) {
2788                 tmp_clock.sin_addr.s_addr = *clkaddr++;
2789                 GET_INADDR(addr) = tmp_clock.sin_addr.s_addr;
2790                 if (!ISREFCLOCKADR(&tmp_clock) ||
2791                     findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
2792                         req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2793                         return;
2794                 }
2795
2796                 memset((char *)&bug, 0, sizeof bug);
2797                 refclock_buginfo(&addr, &bug);
2798                 if (bug.nvalues == 0 && bug.ntimes == 0) {
2799                         req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
2800                         return;
2801                 }
2802
2803                 ic->clockadr = tmp_clock.sin_addr.s_addr;
2804                 i = bug.nvalues;
2805                 if (i > NUMCBUGVALUES)
2806                     i = NUMCBUGVALUES;
2807                 ic->nvalues = (u_char)i;
2808                 ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1)));
2809                 while (--i >= 0)
2810                     ic->values[i] = htonl(bug.values[i]);
2811
2812                 i = bug.ntimes;
2813                 if (i > NUMCBUGTIMES)
2814                     i = NUMCBUGTIMES;
2815                 ic->ntimes = (u_char)i;
2816                 ic->stimes = htonl(bug.stimes);
2817                 while (--i >= 0) {
2818                         HTONL_FP(&bug.times[i], &ic->times[i]);
2819                 }
2820
2821                 ic = (struct info_clkbug *)more_pkt();
2822         }
2823         flush_pkt();
2824 }
2825 #endif
2826
2827 /*
2828  * receiver of interface structures
2829  */
2830 static void
2831 fill_info_if_stats(void *data, interface_info_t *interface_info)
2832 {
2833         struct info_if_stats **ifsp = (struct info_if_stats **)data;
2834         struct info_if_stats *ifs = *ifsp;
2835         struct interface *interface = interface_info->interface;
2836         
2837         memset((char*)ifs, 0, sizeof(*ifs));
2838         
2839         if (interface->sin.ss_family == AF_INET6) {
2840                 if (!client_v6_capable) {
2841                         return;
2842                 }
2843                 ifs->v6_flag = 1;
2844                 memcpy((char *)&ifs->unaddr.addr6, (char *)&CAST_V6(interface->sin)->sin6_addr, sizeof(struct in6_addr));
2845                 memcpy((char *)&ifs->unbcast.addr6, (char *)&CAST_V6(interface->bcast)->sin6_addr, sizeof(struct in6_addr));
2846                 memcpy((char *)&ifs->unmask.addr6, (char *)&CAST_V6(interface->mask)->sin6_addr, sizeof(struct in6_addr));
2847         } else {
2848                 ifs->v6_flag = 0;
2849                 memcpy((char *)&ifs->unaddr.addr, (char *)&CAST_V4(interface->sin)->sin_addr, sizeof(struct in_addr));
2850                 memcpy((char *)&ifs->unbcast.addr, (char *)&CAST_V4(interface->bcast)->sin_addr, sizeof(struct in_addr));
2851                 memcpy((char *)&ifs->unmask.addr, (char *)&CAST_V4(interface->mask)->sin_addr, sizeof(struct in_addr));
2852         }
2853         ifs->v6_flag = htonl(ifs->v6_flag);
2854         strcpy(ifs->name, interface->name);
2855         ifs->family = htons(interface->family);
2856         ifs->flags = htonl(interface->flags);
2857         ifs->last_ttl = htonl(interface->last_ttl);
2858         ifs->num_mcast = htonl(interface->num_mcast);
2859         ifs->received = htonl(interface->received);
2860         ifs->sent = htonl(interface->sent);
2861         ifs->notsent = htonl(interface->notsent);
2862         ifs->scopeid = htonl(interface->scopeid);
2863         ifs->ifindex = htonl(interface->ifindex);
2864         ifs->ifnum = htonl(interface->ifnum);
2865         ifs->uptime = htonl(current_time - interface->starttime);
2866         ifs->ignore_packets = interface->ignore_packets;
2867         ifs->peercnt = htonl(interface->peercnt);
2868         ifs->action = interface_info->action;
2869         
2870         *ifsp = (struct info_if_stats *)more_pkt();
2871 }
2872
2873 /*
2874  * get_if_stats - get interface statistics
2875  */
2876 static void
2877 get_if_stats(
2878         struct sockaddr_storage *srcadr,
2879         struct interface *inter,
2880         struct req_pkt *inpkt
2881         )
2882 {
2883         struct info_if_stats *ifs;
2884
2885         DPRINTF(3, ("wants interface statistics\n"));
2886
2887         ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt,
2888             v6sizeof(struct info_if_stats));
2889
2890         interface_enumerate(fill_info_if_stats, &ifs);
2891         
2892         flush_pkt();
2893 }
2894
2895 static void
2896 do_if_reload(
2897         struct sockaddr_storage *srcadr,
2898         struct interface *inter,
2899         struct req_pkt *inpkt
2900         )
2901 {
2902         struct info_if_stats *ifs;
2903
2904         DPRINTF(3, ("wants interface reload\n"));
2905
2906         ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt,
2907             v6sizeof(struct info_if_stats));
2908
2909         interface_update(fill_info_if_stats, &ifs);
2910         
2911         flush_pkt();
2912 }
2913