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