home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xntp3.zip / xntpd / ntp_request.c < prev    next >
C/C++ Source or Header  |  1992-08-04  |  57KB  |  2,420 lines

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