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