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