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