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