home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xntp3.zip / gizmo / gizmo_config.c < prev    next >
C/C++ Source or Header  |  1989-09-19  |  13KB  |  683 lines

  1. /*
  2.  * gizmo_config.c - read and apply configuration information
  3.  */
  4. #include <stdio.h>
  5. #include "gizmo_syslog.h"
  6. #include <strings.h>
  7. #include <ctype.h>
  8. #include <sys/types.h>
  9. #include <sys/socket.h>
  10. #include <netinet/in.h>
  11.  
  12. #include "ntp_fp.h"
  13. #include "ntp.h"
  14. #include "ntp_refclock.h"
  15. #include "gizmo.h"
  16.  
  17. /*
  18.  * These routines are used decode and apply configuration information
  19.  * at run time.  The configuration is compiled in.
  20.  */
  21.  
  22. /*
  23.  * Definitions of things either imported from or exported to outside
  24.  */
  25. #ifdef DEBUG
  26. extern int debug;
  27. #endif
  28. extern u_long ctl_auth_keyid;
  29. extern u_long info_auth_keyid;
  30.  
  31. /*
  32.  * Configuration array.  This is initialized at compile time.
  33.  */
  34. extern u_char gizmo_config_data[];
  35.  
  36. /*
  37.  * Used by the configuration data reading routines
  38.  */
  39. static u_char *config_pt;
  40. static u_long config_csum;
  41.  
  42. /*
  43.  * getstartup - search through the options looking for a debug level
  44.  *        and host to log to.
  45.  */
  46. void
  47. getstartup(argc, argv)
  48.     int argc;
  49.     char *argv[];
  50. {
  51.     void doconfig();
  52.  
  53.     doconfig(0);
  54. }
  55.  
  56. /*
  57.  * getconfig - get command line options and read the configuration file
  58.  */
  59. void
  60. getconfig(argc, argv)
  61.     int argc;
  62.     char *argv[];
  63. {
  64.     void doconfig();
  65.  
  66.     doconfig(1);
  67. }
  68.  
  69.  
  70. /*
  71.  * doconfig - do the gross work of configuration
  72.  */
  73. void
  74. doconfig(applyit)
  75.     int applyit;
  76. {
  77.     register int i;
  78.     int errflg;
  79.     int peerversion;
  80.     u_long peerkey;
  81.     int peerflags;
  82.     int hmode;
  83.     struct sockaddr_in peeraddr;
  84.     struct sockaddr_in maskaddr;
  85.     l_fp ts;
  86.     int tok;
  87.     struct interface *localaddr;
  88.     struct refclockstat clock;
  89.     u_long data_csum;
  90.     int cgettoken();
  91.     int cgetuchar();
  92.     int cgetchar();
  93.     int cgetushort();
  94.     u_long cgetulong();
  95.     void cgetts();
  96.     void cgetnetnum();
  97.     void check_size();
  98.     extern void proto_config();
  99.     extern void authtrust();
  100.     extern struct peer *peer_config();
  101.     extern void stats_config();
  102.     extern void mon_start(), mon_stop();
  103.     extern void loop_config();
  104.     extern int atolfp();
  105.     extern int authreadkeys();
  106.     extern struct interface *findinterface();
  107.     extern char *ntoa();
  108.     extern void setauthkey();
  109.  
  110.     /*
  111.      * Initialize, initialize
  112.      */
  113. #ifdef DEBUG
  114.     debug = 0;
  115. #endif    /* DEBUG */
  116.     config_pt = gizmo_config_data;
  117.     config_csum = 0;
  118.  
  119.     while ((tok = cgettoken())
  120.         != CONFIG_UNKNOWN) {
  121.         switch(tok) {
  122.         case CONFIG_PEER:
  123.         case CONFIG_SERVER:
  124.         case CONFIG_BROADCAST:
  125.             if (tok == CONFIG_PEER)
  126.                 hmode = MODE_ACTIVE;
  127.             else if (tok == CONFIG_SERVER)
  128.                 hmode = MODE_CLIENT;
  129.             else
  130.                 hmode = MODE_BROADCAST;
  131.  
  132.             cgetnetnum(&peeraddr);
  133.  
  134. #ifdef REFCLOCK
  135.             if (!ISREFCLOCKADR(&peeraddr) && ISBADADR(&peeraddr)) {
  136. #else
  137.             if (ISBADADR(&peeraddr)) {
  138. #endif
  139.                 syslog(LOG_ERR,
  140.                     "attempt to configure invalid address %s",
  141.                     ntoa(&peeraddr));
  142.                 break;
  143.             }
  144.             
  145.             errflg = 0;
  146.             peerversion = NTP_VERSION;
  147.             peerkey = 0;
  148.             peerflags = 0;
  149.             while ((tok = cgettoken()) != CONFIG_END) {
  150.                 switch (tok) {
  151.                 case CONF_MOD_VERSION:
  152.                     peerversion = cgetuchar();
  153.                     if (peerversion != NTP_VERSION
  154.                         && peerversion != NTP_OLDVERSION) {
  155.                         syslog(LOG_ERR,
  156.                 "inappropriate version number %d, %s ignored",
  157.                     peerversion, ntoa(&peeraddr));
  158.                         errflg = 1;
  159.                     }
  160.                     break;
  161.  
  162.                 case CONF_MOD_KEY:
  163.                     peerkey = cgetulong();
  164.                     peerflags |= FLAG_AUTHENABLE;
  165.                     break;
  166.  
  167.                 case CONF_MOD_MINPOLL:
  168.                     peerflags |= FLAG_MINPOLL;
  169.                     break;
  170.  
  171.                 default:
  172.                     syslog(LOG_ERR,
  173.         "inappropriate code for peer configuration <%d>, %s ignored\n",
  174.                         tok, ntoa(&peeraddr));
  175.                     errflg++;
  176.                     break;
  177.                 }
  178.             }
  179.             if (!errflg && applyit) {
  180.                 if (peer_config(&peeraddr,
  181.                     (struct interface *)0,
  182.                     hmode, peerversion, peerkey,
  183.                     peerflags) == 0) {
  184.                     syslog(LOG_ERR,
  185.                         "configuration of %s failed",
  186.                         ntoa(&peeraddr));
  187.                 }
  188.             }
  189.             break;
  190.  
  191.         case CONFIG_PRECISION:
  192.             i = cgetchar();
  193.             if (i >= 0 || i < -25)
  194.                 syslog(LOG_ERR,
  195.                     "unlikely precision %d, line ignored", i);
  196.             else if (applyit)
  197.                 proto_config(PROTO_PRECISION, i);
  198.             break;
  199.  
  200.         case CONFIG_DRIFT:
  201.             cgetts(&ts);
  202.             if (applyit)
  203.                 loop_config(LOOP_DRIFTCOMP, &ts);
  204.             break;
  205.         
  206.         case CONFIG_BROADCASTCLIENT:
  207.             i = cgetuchar();
  208.             if (i == CONF_YORN_YES) {
  209.                 if (applyit)
  210.                     proto_config(PROTO_BROADCLIENT, 1);
  211.             } else if (i = CONF_YORN_NO) {
  212.                 if (applyit)
  213.                     proto_config(PROTO_BROADCLIENT, 0);
  214.             } else {
  215.                 syslog(LOG_ERR,
  216.             "Invalid argument for broadcastclient <%d>", i);
  217.             }
  218.             break;
  219.         
  220.         case CONFIG_AUTHENTICATE:
  221.             i = cgetuchar();
  222.             if (i == CONF_YORN_YES) {
  223.                 if (applyit)
  224.                     proto_config(PROTO_AUTHENTICATE, 1);
  225.             } else if (i = CONF_YORN_NO) {
  226.                 if (applyit)
  227.                     proto_config(PROTO_AUTHENTICATE, 0);
  228.             } else {
  229.                 syslog(LOG_ERR,
  230.             "Invalid argument for authenticate <%d>", i);
  231.             }
  232.             break;
  233.         
  234.         case CONFIG_KEYS:
  235.             i = cgetuchar();
  236.             while (i-- > 0) {
  237.                 u_long keys[2];
  238.  
  239.                 peerkey = cgetulong();
  240.                 keys[0] = cgetulong();
  241.                 keys[1] = cgetulong();
  242.                 if (applyit)
  243.                     setauthkey(peerkey, keys);
  244.             }
  245.             break;
  246.  
  247.         case CONFIG_MONITOR:
  248.             i = cgetuchar();
  249.             if (i == CONF_YORN_YES) {
  250.                 if (applyit)
  251.                     mon_start();
  252.             } else if (i = CONF_YORN_NO) {
  253.                 if (applyit)
  254.                     mon_stop();
  255.             } else {
  256.                 syslog(LOG_ERR,
  257.             "Invalid argument for monitor <%d>", i);
  258.             }
  259.             break;
  260.         
  261.         case CONFIG_AUTHDELAY:
  262.             peerkey = cgetulong();
  263.             if (applyit)
  264.                 proto_config(PROTO_AUTHDELAY, (long)peerkey);
  265.             break;
  266.         
  267.         case CONFIG_RESTRICT:
  268.             cgetnetnum(&peeraddr);
  269.             cgetnetnum(&maskaddr);
  270.             i = cgetushort();
  271.  
  272.             /*
  273.              * Use peerversion as flags, peerkey as mflags.  Ick.
  274.              */
  275.             peerversion = 0;
  276.             peerkey = 0;
  277.             if (i & CONF_RES_IGNORE)
  278.                 peerversion |= RES_IGNORE;
  279.             if (i & CONF_RES_NOSERVE)
  280.                 peerversion |= RES_DONTSERVE;
  281.             if (i & CONF_RES_NOTRUST)
  282.                 peerversion |= RES_DONTTRUST;
  283.             if (i & CONF_RES_NOQUERY)
  284.                 peerversion |= RES_NOQUERY;
  285.             if (i & CONF_RES_NOMODIFY)
  286.                 peerversion |= RES_NOMODIFY;
  287.             if (i & CONF_RES_NOPEER)
  288.                 peerversion |= RES_NOPEER;
  289.             if (i & CONF_RES_NOTRAP)
  290.                 peerversion |= RES_NOTRAP;
  291.             if (i & CONF_RES_LPTRAP)
  292.                 peerversion |= RES_LPTRAP;
  293.             if (i & CONF_RES_NTPPORT)
  294.                 peerkey |= RESM_NTPONLY;
  295.             if (SRCADR(&peeraddr) == INADDR_ANY)
  296.                 maskaddr.sin_addr.s_addr = 0;
  297.             if (applyit)
  298.                 restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
  299.                     (int)peerkey, peerversion);
  300.             break;
  301.  
  302.         case CONFIG_BDELAY:
  303.             cgetts(&ts);
  304.             peerkey = LFPTOFP(&ts);
  305.             if (applyit)
  306.                 proto_config(PROTO_BROADDELAY, peerkey);
  307.             break;
  308.  
  309.         case CONFIG_TRUSTEDKEY:
  310.             i = cgetuchar();
  311.             while (i-- > 0) {
  312.                 peerkey = cgetulong();
  313.                 if (applyit)
  314.                     authtrust(peerkey, 1);
  315.             }
  316.             break;
  317.  
  318.         case CONFIG_REQUESTKEY:
  319.             peerkey = cgetulong();
  320.             if (applyit)
  321.                 info_auth_keyid = peerkey;
  322.             break;
  323.  
  324.         case CONFIG_CONTROLKEY:
  325.             peerkey = cgetulong();
  326.             if (applyit)
  327.                 ctl_auth_keyid = peerkey;
  328.             break;
  329.         
  330.         case CONFIG_TRAP:
  331.             cgetnetnum(&peeraddr);
  332.  
  333.             /*
  334.              * Use peerversion for port number.  Barf.
  335.              */
  336.             errflg = 0;
  337.             peerversion = 0;
  338.             localaddr = 0;
  339.             while ((tok = cgettoken()) != CONFIG_END) {
  340.                 switch (tok) {
  341.                 case CONF_TRAP_PORT:
  342.                     peerversion = cgetushort();
  343.                     if (peerversion == 0
  344.                         || peerversion > 32767) {
  345.                         syslog(LOG_ERR,
  346.                 "invalid port number %d, trap %s ignored",
  347.                           peerversion, ntoa(&peeraddr));
  348.                         errflg = 1;
  349.                     }
  350.                     break;
  351.  
  352.                 case CONF_TRAP_INTERFACE:
  353.                     cgetnetnum(&maskaddr);
  354.                     if (applyit) {
  355.                         localaddr
  356.                             = findinterface(&maskaddr);
  357.                         if (localaddr == NULL) {
  358.                             syslog(LOG_ERR,
  359.                     "can't find interface with address %s",
  360.                                 ntoa(&maskaddr));
  361.                             errflg = 1;
  362.                         }
  363.                     }
  364.                     break;
  365.  
  366.                 default:
  367.                     errflg++;
  368.                     break;
  369.                 }
  370.             }
  371.  
  372.             if (!errflg && applyit) {
  373.                 extern struct interface *any_interface;
  374.  
  375.                 if (peerversion != 0)
  376.                     peeraddr.sin_port = htons(peerversion);
  377.                 else
  378.                     peeraddr.sin_port = htons(TRAPPORT);
  379.                 if (localaddr == NULL)
  380.                     localaddr = any_interface;
  381.                 if (!ctlsettrap(&peeraddr, localaddr, 0,
  382.                     NTP_VERSION))
  383.                     syslog(LOG_ERR,
  384.                     "can't set trap for %s, no resources",
  385.                         ntoa(&peeraddr));
  386.             }
  387.             break;
  388.  
  389.         case CONFIG_FUDGE:
  390.             cgetnetnum(&peeraddr);
  391.  
  392.             errflg = 0;
  393.             if (!ISREFCLOCKADR(&peeraddr)) {
  394.                 syslog(LOG_ERR,
  395.             "%s is inappropriate address for the fudge command",
  396.                     ntoa(&peeraddr));
  397.                 errflg++;
  398.             }
  399.  
  400.             bzero((char *)&clock, sizeof clock);
  401.             while ((tok = cgettoken()) != CONFIG_END) {
  402.                 switch (tok) {
  403.                 case CONF_FDG_TIME1:
  404.                     cgetts(&clock.fudgetime1);
  405.                     clock.haveflags |= CLK_HAVETIME1;
  406.                     break;
  407.  
  408.                 case CONF_FDG_TIME2:
  409.                     cgetts(&clock.fudgetime2);
  410.                     clock.haveflags |= CLK_HAVETIME2;
  411.                     break;
  412.  
  413.                 case CONF_FDG_VALUE1:
  414.                     clock.fudgeval1 =
  415.                         (long) cgetulong();
  416.                     clock.haveflags |= CLK_HAVEVAL1;
  417.                     break;
  418.  
  419.                 case CONF_FDG_VALUE2:
  420.                     clock.fudgeval2 =
  421.                         (long) cgetulong();
  422.                     clock.haveflags |= CLK_HAVEVAL2;
  423.                     break;
  424.  
  425.                 case CONF_FDG_FLAG1:
  426.                 case CONF_FDG_FLAG2:
  427.                 case CONF_FDG_FLAG3:
  428.                 case CONF_FDG_FLAG4:
  429.                     peerversion = cgetuchar();
  430.                     if (peerversion != CONF_YORN_NO
  431.                         && peerversion != CONF_YORN_YES) {
  432.                         syslog(LOG_ERR,
  433.                 "incorrect flag value <%d> for fudge %s",
  434.                           peerversion, ntoa(&peeraddr));
  435.                         errflg++;
  436.                     }
  437.                     switch(tok) {
  438.                     case CONF_FDG_FLAG1:
  439.                         hmode = CLK_FLAG1;
  440.                         clock.haveflags|=CLK_HAVEFLAG1;
  441.                         break;
  442.                     case CONF_FDG_FLAG2:
  443.                         hmode = CLK_FLAG2;
  444.                         clock.haveflags|=CLK_HAVEFLAG2;
  445.                         break;
  446.                     case CONF_FDG_FLAG3:
  447.                         hmode = CLK_FLAG3;
  448.                         clock.haveflags|=CLK_HAVEFLAG3;
  449.                         break;
  450.                     case CONF_FDG_FLAG4:
  451.                         hmode = CLK_FLAG4;
  452.                         clock.haveflags|=CLK_HAVEFLAG4;
  453.                         break;
  454.                     }
  455.                     if (peerkey == CONF_YORN_NO)
  456.                         clock.flags &= ~hmode;
  457.                     else
  458.                         clock.flags |= hmode;
  459.                     break;
  460.  
  461.                 default:
  462.                     errflg++;
  463.                     break;
  464.                 }
  465.             }
  466.  
  467. #ifdef REFCLOCK
  468.             /*
  469.              * If reference clock support isn't defined the
  470.              * fudge line will still be accepted and syntax
  471.              * checked, but will essentially do nothing.
  472.              */
  473.             if (!errflg & applyit) {
  474.                 extern void refclock_control();
  475.  
  476.                 refclock_control(&peeraddr, &clock,
  477.                     (struct refclockstat *)0);
  478.             }
  479. #endif
  480.             break;
  481.  
  482.         case CONFIG_MAXSKEW:
  483.             peerkey = cgetulong();
  484.             if (applyit)
  485.                 proto_config(PROTO_MAXSKEW, peerkey);
  486.             break;
  487.  
  488.         case CONFIG_SYSLOGHOST:
  489.             cgetnetnum(&peeraddr);
  490.             setloghost(&peeraddr);
  491.             break;
  492.  
  493.         case CONFIG_DEBUGLEVEL:
  494.             i = cgetuchar();
  495. #ifdef DEBUG
  496.             debug = i;
  497.             if (debug)
  498.                 printf("debug level set to %d\n", i);
  499. #endif
  500.             break;
  501.         }
  502.     }
  503.  
  504.     /*
  505.      * If we got here, there should be a checksum in the next
  506.      * 4 bytes of the file.  Check it out.
  507.      */
  508.     check_size(4);
  509.     data_csum = 0;
  510.     for (i = 0; i < 4; i++) {
  511.         data_csum <<= 8;
  512.         data_csum += ((u_long)(*config_pt++)) & 0xff;
  513.     }
  514.     if ((config_csum + data_csum) != 0) {
  515.         syslog(LOG_ERR,
  516.             "configuration checksum error (0x%08x != 0x%08x)",
  517.             config_csum, -data_csum);
  518. #ifdef notdef
  519.         exit(1);
  520. #endif
  521.     }
  522. }
  523.  
  524.  
  525. /*
  526.  * check_size - check to see if there are enough bytes in the buffer.
  527.  */
  528. static void
  529. check_size(nbytes)
  530.     int nbytes;
  531. {
  532.     if ((config_pt + nbytes) > &gizmo_config_data[GIZMO_CONFIG_SIZE]) {
  533.         syslog(LOG_ERR, "whoops!  Slipped off end of config info");
  534.         exit(1);
  535.     }
  536. }
  537.  
  538. /*
  539.  * cgetuchar - return an unsigned char (as an int)
  540.  */
  541. int
  542. cgetuchar()
  543. {
  544.     register u_char u;
  545.  
  546.     check_size(sizeof(u_char));
  547.     u = *config_pt++;
  548.     config_csum += (u_long)u;
  549.     return (int)u;
  550. }
  551.  
  552.  
  553. /*
  554.  * cgettoken - return a token value
  555.  */
  556. int
  557. cgettoken()
  558. {
  559.     register u_char u;
  560.  
  561.     check_size(sizeof(u_char));
  562.     u = *config_pt++;
  563.     config_csum += (u_long)u;
  564.     return (int)u;
  565. }
  566.  
  567.  
  568. /*
  569.  * cgetushort - return an unsigned short value (as an int)
  570.  */
  571. int
  572. cgetushort()
  573. {
  574.     register u_char u;
  575.     register u_short s;
  576.  
  577.     check_size(sizeof(u_short));
  578.     u = *config_pt++;
  579.     config_csum += (u_long)u;
  580.     s = ((u_short)u) << 8;
  581.     u = *config_pt++;
  582.     config_csum += (u_long)u;
  583.     s += (u_short)u;
  584.  
  585.     return (int)s;
  586. }
  587.  
  588.  
  589. /*
  590.  * cgetulong - return an unsigned long value
  591.  */
  592. u_long
  593. cgetulong()
  594. {
  595.     register int i;
  596.     register u_long v;
  597.     register u_char u;
  598.  
  599.     check_size(sizeof(u_long));
  600.     v = 0;
  601.     for (i = 0; i < sizeof(u_long); i++) {
  602.         u = *config_pt++;
  603.         config_csum += (u_long)u;
  604.         v <<= 8;
  605.         v += (u_long)u;
  606.     }
  607.  
  608.     return v;
  609. }
  610.  
  611.  
  612. /*
  613.  * cgetchar - return a signed char value
  614.  */
  615. int
  616. cgetchar()
  617. {
  618.     register int i;
  619.  
  620.     config_csum += (u_long)(*config_pt);
  621.     i = (int)*((s_char *)config_pt);
  622.     config_pt++;
  623.     config_csum += (u_long)(i & 0xff);
  624.     return i;
  625. }
  626.  
  627.  
  628. /*
  629.  * cgetts - return an l_fp timestamp
  630.  */
  631. void
  632. cgetts(ts)
  633.     l_fp *ts;
  634. {
  635.     register int i;
  636.     register u_long v;
  637.     register u_char u;
  638.  
  639.     check_size(sizeof(l_fp));
  640.     v = 0;
  641.     for (i = 0; i < sizeof(l_fp); i++) {
  642.         if (i == (sizeof(l_fp)/2)) {
  643.             ts->l_ui = v;
  644.             v = 0;
  645.         }
  646.         u = *config_pt++;
  647.         config_csum += (u_long)u;
  648.         v <<= 8;
  649.         v += (u_long)u;
  650.     }
  651.     ts->l_uf = v;
  652. }
  653.  
  654.  
  655.  
  656. /*
  657.  * cgetnetnum - return a net number
  658.  */
  659. void
  660. cgetnetnum(addr)
  661.     struct sockaddr_in *addr;
  662. {
  663.     register int i;
  664.     register u_long uaddr;
  665.     register u_char u;
  666.  
  667.     /*
  668.      * make up socket address.  Clear it out for neatness.
  669.      */
  670.     bzero((char *)addr, sizeof(struct sockaddr_in));
  671.     addr->sin_family = AF_INET;
  672.     addr->sin_port = htons(NTP_PORT);
  673.  
  674.     check_size(sizeof(u_long));
  675.     for (i = 0, uaddr = 0; i < sizeof(u_long); i++) {
  676.         u = *config_pt++;
  677.         config_csum += (u_long)u;
  678.         uaddr <<= 8;
  679.         uaddr += (u_long)u;
  680.     }
  681.     addr->sin_addr.s_addr = htonl(uaddr);
  682. }
  683.