source: trunk/third/xntp/xntpd/ntp_request.c @ 10832

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