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