home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / ppp / dp-2.3 / dpd / readconfig.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-28  |  27.2 KB  |  1,245 lines

  1. /*
  2. **  Copyright (c) 1991 Bolt Beranek and Newman, Inc.
  3. **  All rights reserved.
  4. **
  5. **  Redistribution and use in source and binary forms are permitted
  6. **  provided that: (1) source distributions retain this entire copyright
  7. **  notice and comment, and (2) distributions including binaries display
  8. **  the following acknowledgement:  ``This product includes software
  9. **  developed by Bolt Beranek and Newman, Inc. and CREN/CSNET'' in the
  10. **  documentation or other materials provided with the distribution and in
  11. **  all advertising materials mentioning features or use of this software.
  12. **  Neither the name of Bolt Beranek and Newman nor CREN/CSNET may be used
  13. **  to endorse or promote products derived from this software without
  14. **  specific prior written permission.
  15. **
  16. **  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  17. **  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  18. **  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19. */
  20. /*
  21.  * Copyright (c) 1992 Purdue University
  22.  * All rights reserved.
  23.  *
  24.  * Redistribution and use in source and binary forms are permitted
  25.  * provided that the above copyright notice and this paragraph are
  26.  * duplicated in all such forms and that any documentation,
  27.  * advertising materials, and other materials related to such
  28.  * distribution and use acknowledge that the software was developed
  29.  * by Purdue University.  The name of the University may not be used
  30.  * to endorse or promote products derived * from this software without
  31.  * specific prior written permission.
  32.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  33.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  34.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  35.  *
  36.  * Note: this copyright applies to portions of this software developed
  37.  * at Purdue beyond the software covered by the original copyright.
  38.  */
  39. #include <stdio.h>
  40. #include <ctype.h>
  41. #include <netdb.h>
  42. #include <memory.h>
  43. #include <string.h>
  44. #include <sys/types.h>
  45. #include <sys/param.h>
  46. #include <sys/socket.h>
  47. #include <sys/stream.h>
  48. #include <sys/ioctl.h>
  49. #include <netinet/in_systm.h>
  50. #include <netinet/in.h>
  51. #include <netinet/ip.h>
  52. #include <net/if.h>
  53. #include <arpa/inet.h>
  54. #include "dp_str.h"
  55. #include "dp.h"
  56. #include "dpd.h"
  57. #include "dpconf.h"
  58.  
  59.  
  60. /*
  61. **  Some systems don't have these in their <netinet/in.h>
  62. */
  63. #ifndef    IPPROTO_EGP
  64. #define IPPROTO_EGP    8
  65. #endif    /* IPPROTO_EGP */
  66. #ifndef    IPPROTO_RDP
  67. #define IPPROTO_RDP    27
  68. #endif    /* IPPROTO_EGP */
  69.  
  70.  
  71. #define EQ(a, b)    (strcmp((a), (b)) == 0)
  72. #define nexttok()    strtok((char *)NULL, SEPARATORS)
  73.  
  74.  
  75. static int        errorcount;
  76. static int        linenum;
  77. static char        SEPARATORS[] = " \t";
  78. static REMOTE        *RemoteTable;
  79. static MODEM        *ModemTable;
  80. static int        RemoteCount;
  81. static int        ModemCount;
  82. static char        WHERE[] = "readconfig";
  83. static void        d_vlog();
  84.  
  85. extern long        strtol();
  86.  
  87. /*
  88. **  Find this interface in our list.
  89. */
  90. REMOTE *
  91. findconfig(device)
  92.     register char    *device;
  93. {
  94.     register REMOTE    *rp;
  95.     register int    i;
  96.  
  97.     for (rp = RemoteTable, i = RemoteCount; --i >= 0; rp++)
  98.     if (strcmp(device, rp->Device) == 0)
  99.         return rp;
  100.     return NULL;
  101. }
  102.  
  103. /*
  104. **  Find this interface in our list by login name.
  105. */
  106. REMOTE *
  107. findlogin(login)
  108.     register char    *login;
  109. {
  110.     register REMOTE    *rp;
  111.     register int    i;
  112.  
  113.     for (rp = RemoteTable, i = RemoteCount; --i >= 0; rp++)
  114.     if (strcmp(login, rp->Login) == 0)
  115.         return rp;
  116.     return NULL;
  117. }
  118.  
  119. /*
  120. **  Find this modem or modem rotary in our list.
  121. */
  122. MODEM *
  123. findmodem(modem)
  124.     register char    *modem;
  125. {
  126.     register MODEM    *mp;
  127.     register int    i;
  128.  
  129.     for (mp = ModemTable, i = ModemCount; --i >= 0; mp++)
  130.     if (strcmp(modem, mp->Name) == 0)
  131.         return mp;
  132.     return NULL;
  133. }
  134.  
  135.  
  136. /*
  137.  * Functions to de-allocate memory that is allocated for each configuration
  138.  */
  139. free_remotes()
  140. {
  141.     REMOTE *rp;
  142.     int i;
  143.     if (RemoteTable) {
  144.     for (rp = RemoteTable, i = RemoteCount; --i >= 0; rp++)
  145.         free_remote(rp);
  146.     free((char *)RemoteTable);
  147.     }
  148.     RemoteCount = 0;
  149. }
  150.  
  151. free_remote(rp)
  152. REMOTE *rp;
  153. {
  154.     if (rp->Sitename)
  155.     (void)free(rp->Sitename);
  156.     if (rp->Login)
  157.     (void)free(rp->Login);
  158.     if (rp->Phone)
  159.     (void)free(rp->Phone);
  160.     if (rp->Script)
  161.     (void)free(rp->Script);
  162.     if (rp->ScriptArgs) {
  163.     if (rp->ScriptArgs[0])
  164.         (void)free(rp->ScriptArgs[0]);
  165.     (void)free((char *)rp->ScriptArgs);
  166.     }
  167.     if (rp->Transcript)
  168.     (void)free(rp->Transcript);
  169.     if (rp->PppArgs) {
  170.     if (rp->PppArgs[0])
  171.         (void)free(rp->PppArgs[0]);
  172.     (void)free((char *)rp->PppArgs);
  173.     }
  174.     if (rp->Modems)
  175.     (void)free((char *)rp->Modems);
  176.     if (rp->AuxProgram)
  177.     (void)free(rp->AuxProgram);
  178.     if (rp->AuxArgs) {
  179.     if (rp->AuxArgs[0])
  180.         (void)free(rp->AuxArgs[0]);
  181.     (void)free((char *)rp->AuxArgs);
  182.     }
  183. }
  184.  
  185. free_modems()
  186. {
  187.     MODEM *mp;
  188.     int i;
  189.     if (ModemTable) {
  190.     for (mp = ModemTable, i = ModemCount; --i >= 0; mp++)
  191.         free_modem(mp);
  192.     free((char *)ModemTable);
  193.     }
  194.     ModemCount = 0;
  195. }
  196.  
  197. free_modem(mp)
  198. MODEM *mp;
  199. {
  200.     if (mp->Name)
  201.     (void)free(mp->Name);
  202.     if (mp->Line)
  203.     (void)free(mp->Line);
  204.     if (mp->DialScript)
  205.     (void)free(mp->DialScript);
  206.     if (mp->DialCharMap)
  207.     (void)free(mp->DialCharMap);
  208.     if (mp->Modems)
  209.     (void)free((char *)mp->Modems);
  210. }
  211.  
  212. /*
  213. **  Is the host (or its network) on the list of hosts and networks?
  214. */
  215. int
  216. hostinlist(list, addr)
  217.     struct in_addr    *list;
  218.     struct in_addr    addr;
  219. {
  220.     register int    i;
  221.     register int    j;
  222.  
  223.     j = i = addr.s_addr % MAXHOSTS;
  224.  
  225.     do {
  226.     if (list[j].s_addr == 0)
  227.         return 0;
  228.     if (list[j].s_addr == addr.s_addr)
  229.         return 1;
  230.     if (inet_lnaof(list[j]) == 0
  231.      && inet_netof(list[j]) == inet_netof(addr))
  232.         return 1;
  233.  
  234.     if (++j == MAXHOSTS)
  235.         j = 0;
  236.     } while (j != i);
  237.  
  238.     return 0;
  239. }
  240.  
  241.  
  242. #include <varargs.h>
  243.  
  244. void
  245. yyerror(va_alist)
  246. va_dcl
  247. {
  248.     va_list ap;
  249.     char *path,
  250.      *fmt,
  251.      buff[256];
  252.  
  253.     va_start(ap);
  254.     path = va_arg(ap, char *);
  255.     fmt = va_arg(ap, char *);
  256.     (void)sprintf(buff, "Error near line %d of\n\t\"%s\":  %s",
  257.     linenum, path, fmt);
  258.     d_vlog(DLOG_GENERAL, WHERE, buff, ap);
  259.     va_end(ap);
  260.     errorcount++;
  261. }
  262.  
  263.  
  264. static void
  265. parseprotocols(path, lp, set)
  266.     char    *path;
  267.     u_long    *lp;
  268.     int        set;
  269. {
  270.     char    *p;
  271.     int        i;
  272.     struct protoent *pe;
  273.  
  274.     setprotoent(1);
  275.     while (p = nexttok()) {
  276.     if (pe = getprotobyname(p))
  277.         i = pe->p_proto;
  278.     else {
  279.         yyerror(path, "Bad protocol \"%s\"", p);
  280.         continue;
  281.     }
  282.     if (set == P_SET)
  283.         lp[P_WORD(i)] |=  P_BIT(i);
  284.     else
  285.         lp[P_WORD(i)] &= ~P_BIT(i);
  286.     }
  287.     endprotoent();
  288. }
  289.  
  290.  
  291. static int
  292. positivenumber(p)
  293.     char    *p;
  294. {
  295.     if (*p == '\0')
  296.     return 0;
  297.     for ( ; *p; p++)
  298.     if (!isdigit(*p))
  299.         return 0;
  300.     return 1;
  301. }
  302.  
  303.  
  304. static long
  305. parsetime(path)
  306.     char    *path;
  307. {
  308.     long    l;
  309.     int        i;
  310.     char    *p;
  311.  
  312.     for (l = 0; p = nexttok(); )
  313.     if (!positivenumber(p) || (i = atoi(p)) < 0 || i > 23)
  314.         yyerror(path, "Bad hour \"%s\"", p);
  315.     else
  316.         l |= (1L << i);
  317.     return l;
  318. }
  319.  
  320.  
  321. static int
  322. addhosttolist(list, addr)
  323.     struct in_addr    *list;
  324.     struct in_addr    addr;
  325. {
  326.     register int    i;
  327.     register int    j;
  328.  
  329.     j = i = addr.s_addr % MAXHOSTS;
  330.     do {
  331.     if (list[j].s_addr == 0) {
  332.         list[j] = addr;
  333.         return 1;
  334.     }
  335.     if (++j == MAXHOSTS)
  336.         j = 0;
  337.     } while (j != i);
  338.  
  339.     return 0;
  340. }
  341.  
  342.  
  343.  
  344. static int
  345. parseaddresslist(path, list)
  346.     char        *path;
  347.     struct in_addr    *list;
  348. {
  349.     char        *p;
  350.     struct in_addr    new;
  351.     int            i;
  352.     struct hostent    *hp;
  353.     struct netent    *np;
  354.     struct in_addr    in;
  355.  
  356.     for (i = 0; p = nexttok(); i++) {
  357.     if ((new.s_addr = inet_addr(p)) != -1)
  358.         ;
  359.     else if (np = getnetbyname(p)) {
  360.         in.s_addr = np->n_net;
  361.         new = inet_makeaddr(in, 0);
  362.     }
  363.     else if (hp = gethostbyname(p))
  364.         bcopy(hp->h_addr, (caddr_t)&new, sizeof new);
  365.     else {
  366.         yyerror(path, "Bad IP address \"%s\"", p);
  367.         continue;
  368.     }
  369.     if (!hostinlist(list, new) && !addhosttolist(list, new))
  370.         yyerror(path, "Can't add \"%s\" to address list", p);
  371.     }
  372.     return i;
  373. }
  374.  
  375. char TOK_SEP[] = " \t";
  376. #define issep(c) strchr(TOK_SEP, (c))
  377.  
  378. char *
  379. skip_sep(s)
  380. char *s;
  381. {
  382.     while (*s && issep(*s))
  383.     s++;
  384.     return s;
  385. }
  386.  
  387. char *
  388. next_tok(path, s)
  389. char *path,
  390.      *s;
  391. {
  392.     int inst = 0;
  393.     char *s0 = s,
  394.      *s1 = s,
  395.      ch;
  396.     s = skip_sep(s);
  397.     if (*s == '#') {
  398.     *s1++ = *s++;
  399.     *s1 = '\0';
  400.     return ++s;
  401.     }
  402.     for ( s1 = s ; ; s++)
  403.     if ((!inst && strchr(TOK_SEP, *s)) || !*s) {
  404.         if (inst)
  405.         yyerror(path, "Unterminated string: %s\n", s0);
  406.         *s1 = '\0';
  407.         return ++s;
  408.     }
  409.     else
  410.         switch (*s) {
  411.          case '\\':
  412.         s++;
  413.         if (isdigit(*s)) {
  414.             int i = 3;
  415.             ch = 0;
  416.             for ( ; *s && isdigit(*s) && i-- > 0 ; s++ )
  417.             ch = (ch << 3) | (*s - '0');
  418.         }
  419.         else {
  420.             switch (*s) {
  421.              case 'b': ch = '\b'; break;
  422.              case 'f': ch = '\f'; break;
  423.              case 'n': ch = '\n'; break;
  424.              case 'r': ch = '\r'; break;
  425.              case 't': ch = '\t'; break;
  426.              default:  ch = *s;   break;
  427.             }
  428.         }
  429.         *s1++ = ch;
  430.         break;
  431.          case '"':
  432.         inst = !inst;
  433.         break;
  434.          default:
  435.         *s1++ = *s;
  436.         break;
  437.         }
  438. }
  439.  
  440. static fln;
  441.  
  442. char *
  443. fgetln(buf, bufsz, f)
  444. char *buf;
  445. int bufsz;
  446. FILE *f;
  447. {
  448.     char *e, *b;
  449.     b = fgets(buf, bufsz, f);
  450.     if (b) {
  451.     e = buf + strlen(buf) - 1;
  452.     if (*e == '\n') {
  453.         fln++;
  454.         *e = '\0';
  455.     }
  456.     }
  457.     else {
  458.     fln = 0;
  459.     buf[0] = '\0';
  460.     if (ferror(f))
  461.         perror("read");
  462.     }
  463.     return b;
  464. }
  465.  
  466. sprascii(b, s)
  467. char *b,
  468.      *s;
  469. {
  470.     char c;
  471.     while (c = *s++)
  472.     if (!isascii(c)) {
  473.         (void)sprintf(b, "\\%03o", c & 0xff);
  474.         b += 4;
  475.     }
  476.     else if (!isprint(c)) {
  477.         (void)sprintf(b, "^%c", c ^ 0x40);
  478.         b += 2;
  479.     }
  480.     else
  481.         *b++ = c;
  482.     *b = '\0';
  483. }
  484.  
  485. parse_ln(path, vv, t)
  486. char *path;
  487. var_val *vv;
  488. char *t;
  489. {
  490.     int nv = 0;
  491.     char *nt;
  492.     for ( ; *t ; t = nt) {
  493.     t = skip_sep(t);
  494.     if (!*t || *t == '#')
  495.         break;
  496.     nt = next_tok(path, t);
  497.     vv->var = malloc((unsigned)strlen(t)+1);
  498.     (void)strcpy(vv->var, t);
  499.     if (vv->val = strchr(vv->var, '=')) {
  500.         *(vv->val)++ = '\0';
  501.         nv++;
  502.         vv++;
  503.     }
  504.     else {
  505.         char buf[256];
  506.         sprascii(buf, t);
  507.         yyerror(path, "Bad configuration option \"%s\"\n", buf);
  508.     }
  509.     }
  510.     return nv;
  511. }
  512.  
  513. #define    MAXCONFLN    1024
  514. #define    MAXVARS        32
  515.  
  516. var_val *
  517. readconf(path, cf)
  518. char *path;
  519. FILE *cf;
  520. {
  521.     static char lnbuf[MAXCONFLN];
  522.     static var_val vv[MAXVARS+1];
  523.     var_val *vp;
  524.     int n;
  525.     int nv = 0;
  526.     char *l;
  527.     int line = 0;
  528.  
  529.     /*
  530.      * De-allocate variable/value pairs from last time.
  531.      */
  532.     for (vp = vv ; vp->var ; vp++) {
  533.     (void)free(vp->var);
  534.     vp->var = vp->val = (char *)0;
  535.     vp->used = 0;
  536.     }
  537.     vp = vv;
  538.     linenum = 0;
  539.  
  540.     /*
  541.      * Skip over any blank or comment lines..
  542.      */
  543.     l = skip_sep(lnbuf);
  544.     while (*l == '#' || *l == '\0') {
  545.     if (!fgetln(lnbuf, sizeof(lnbuf), cf))
  546.          return (var_val *)0;
  547.     l = skip_sep(lnbuf);
  548.     }
  549.  
  550.     linenum = fln;
  551.     /*
  552.      * Definitions must start in column 0.
  553.      */
  554.     if (l != lnbuf) {
  555.     yyerror(path, "Config entries must start in the first column: %s",
  556.         lnbuf);
  557.     }
  558.     
  559.     /*
  560.      * We should be here with l pointing to a non-comment, non-blank line,
  561.      * starting in column 0.  Process lines until we either run into
  562.      * a blank line, EOF, or another line starting in column 0.
  563.      */
  564.     do {
  565.     if (*l != '#') {
  566.         /*
  567.          * Parse anything but a comment line.
  568.          *
  569.          * If we have read a line (line > 0), and something is in the
  570.          * first column, it is a new definition.
  571.          */
  572.         if (line && l == lnbuf)
  573.         break;
  574.         n = parse_ln(path, vp, l);
  575.         nv += n;
  576.         vp += n;
  577.         line++;
  578.     }
  579.     if (!fgetln(lnbuf, sizeof(lnbuf), cf))
  580.         break;
  581.     l = skip_sep(lnbuf);
  582.     } while (*l);
  583.  
  584.     return nv ? vv : (var_val *)0;
  585. }
  586.  
  587. int
  588. readconfig(path)
  589. char *path;
  590. {
  591.     var_val *v;
  592.     int nr = 0, nmr = 0, nm = 0;
  593.     char *cfn;
  594.     FILE *cf;
  595. #if    0
  596.     path = "dp-conf";
  597. #endif
  598.     cfn = expand_dir_file("$DPCONF_DIR", path);
  599.     if (!(cf = fopen(cfn, "r"))) {
  600.     perror(cfn);
  601.     (void)free(cfn);
  602.     return 0;
  603.     }
  604.     /*
  605.      * Scan the file so we can allocate memory for our configuration.
  606.      */
  607.     while (v = readconf(cfn, cf))
  608.     if (strcmp(v->var, "IF") == 0)
  609.         nr++;
  610.     else if (strcmp(v->var, "ROTARY") == 0)
  611.         nmr++;
  612.     else if (strcmp(v->var, "MODEM") == 0) {
  613.         nmr++;
  614.         nm++;
  615.     }
  616.     else
  617.         yyerror(cfn, "unknown configuration option: \"%s\"\n", v->var);
  618.  
  619.     if (nr == 0)
  620.     yyerror(cfn, "No Interfaces defined\n");
  621.     if (nm == 0)
  622.     yyerror(cfn, "No Modems defined\n");
  623.  
  624.     if (errorcount)
  625.     return 0;
  626.  
  627.     free_remotes();
  628.     RemoteTable = (REMOTE *)malloc((unsigned int)nr * sizeof(*RemoteTable));
  629.     if (RemoteTable == NULL) {
  630.     yyerror(cfn, "Can't allocate Remote table, %m");
  631.     (void)free(cfn);
  632.     return 0;
  633.     }
  634.     (void)memset((char *)RemoteTable, 0, nr * sizeof(*RemoteTable));
  635.     free_modems();
  636.     ModemTable = (MODEM *)malloc((unsigned int)nmr * sizeof(*ModemTable));
  637.     if (ModemTable == NULL) {
  638.     yyerror(cfn, "Can't allocate Modem table, %m");
  639.     (void)free(cfn);
  640.     return 0;
  641.     }
  642.     (void)memset((char *)ModemTable, 0, nmr * sizeof (*ModemTable));
  643.     /*
  644.      * Scan the file once for each type of configuration info.
  645.      */
  646.     rewind(cf);
  647.     while (v = readconf(cfn, cf))
  648.     if (strcmp(v->var, "MODEM") == 0)
  649.         def_modem(cfn, v);
  650.     rewind(cf);
  651.     while (v = readconf(cfn, cf))
  652.     if (strcmp(v->var, "ROTARY") == 0)
  653.         def_rotary(cfn, v);
  654.     rewind(cf);
  655.     while (v = readconf(cfn, cf))
  656.     if (strcmp(v->var, "IF") == 0)
  657.         def_if(cfn, v);
  658.  
  659.     (void)fclose(cf);
  660.     (void)free(cfn);
  661.  
  662.     return errorcount == 0;
  663. }
  664.  
  665. char *
  666. savestr(s)
  667. char *s;
  668. {
  669.     char *m = malloc((unsigned)strlen(s)+1);
  670.     (void)strcpy(m, s);
  671.     return m;
  672. }
  673.  
  674. char **
  675. saveargs(path, s)
  676. char *path;
  677. char *s;
  678. {
  679.     char *m, *nm;
  680.     char **a;
  681.     int n;
  682.  
  683.     if (!*s)
  684.     return (char **)0;
  685.     s = savestr(s);
  686.     for (n = 0, m = s ; m ; m = ((m = strchr(m, ',')) ? m+1 : (char *)0))
  687.     n++;
  688.     a = (char **)malloc((unsigned)(n+1) * sizeof(char **));
  689.     if (!a) {
  690.     yyerror(path, "Can't allocate Argument list");
  691.     return (char **)0;
  692.     }
  693.     n = 0;
  694.     for (m = s; m ; m = nm) {
  695.     if (nm = strchr(m, ','))
  696.         *nm++ = '\0';
  697.     a[n++] = m;
  698.     }
  699.     a[n] = (char *)0;
  700.     return a;
  701. }
  702.  
  703. char *
  704. find_val(v, var)
  705. var_val *v;
  706. char *var;
  707. {
  708.     for ( ; v->var ; v++)
  709.     if (strcmp(v->var, var) == 0) {
  710.         v->used++;
  711.         return v->val;
  712.     }
  713.     return (char *)0;
  714. }
  715.  
  716.  
  717. unused_vals(path, type, name, v)
  718. char *path,
  719.      *type,
  720.      *name;
  721. var_val *v;
  722. {
  723.     for ( ; v->var ; v++)
  724.     if (!v->used) {
  725.         yyerror(path, "Unrecognized definition in %s %s: %s=%s",
  726.             name, type, v->var, v->val);
  727.     }
  728. }
  729.  
  730. MODEM **
  731. modem_list(path, list, nmp, type, name)
  732. char *path, *list;
  733. int *nmp;
  734. char *type, *name;
  735. {
  736.     MODEM **mpp, *mmp;
  737.     char *m, *nm;
  738.     int n;
  739.     for (n = 0, m = list ; m ; m = ((m = strchr(m, ',')) ? m+1 : (char *)0))
  740.     n++;
  741.     mpp = (MODEM **)malloc((unsigned)n * sizeof(MODEM *));
  742.     if (!mpp)
  743.     yyerror(path, "Can't allocate Modem list");
  744.     else {
  745.     n = 0;
  746.     for (m = list; m ; m = nm) {
  747.         if (nm = strchr(m, ','))
  748.         *nm++ = '\0';
  749.         if (mmp = findmodem(m)) {
  750.         mpp[n++] = mmp;
  751.         }
  752.         else
  753.         yyerror(path, "Unknown MODEM \"%s\" in %s \"%s\"",
  754.             m, type, name);
  755.     }
  756.     }
  757.     *nmp = n;
  758.     return mpp;
  759. }
  760.  
  761. def_modem(path, v)
  762. char *path;
  763. var_val *v;
  764. {
  765.     MODEM *mp;
  766.     char *val;
  767.  
  768.     if (!(val = find_val(v, "MODEM")))
  769.     yyerror(path, "MODEM definition must have MODEM defined");
  770.     else {
  771.     if (mp = findmodem(val)) {
  772.         yyerror(path, "MODEM \"%s\" defined more than once");
  773.         free_modem(mp);
  774.     }
  775.     else
  776.         mp = &ModemTable[ModemCount++];
  777.     mp->Name = savestr(val);
  778.     }
  779.     mp->NModems = 0;    /* No rotary modems defined */
  780.     if (!(val = find_val(v, "DEV")))
  781.     yyerror(path, "MODEM definition must have DEV defined");
  782.     else
  783.     mp->Line = savestr(val);
  784.     
  785.     /*
  786.      * Interpret common definitions for modems and rotaries.
  787.      */
  788.     def_modem_rotary(path, mp, v);
  789.     /*
  790.      * Make sure we used everything that was given.
  791.      */
  792.     unused_vals(path, "MODEM", mp->Name, v);
  793. }
  794.  
  795. def_rotary(path, v)
  796. char *path;
  797. var_val *v;
  798. {
  799.     MODEM *mp, **mpp;
  800.     char *val;
  801.  
  802.     if (!(val = find_val(v, "ROTARY")))
  803.     yyerror(path, "ROTARY definition must have ROTARY defined");
  804.     else {
  805.     if (mp = findmodem(val)) {
  806.         yyerror(path, "ROTARY \"%s\" defined more than once", mp->Name);
  807.         free_modem(mp);
  808.     }
  809.     else
  810.         mp = &ModemTable[ModemCount++];
  811.     mp->Name = savestr(val);
  812.     }
  813.  
  814.     /*
  815.      * Interpret common definitions for modems and rotaries.
  816.      */
  817.     def_modem_rotary(path, mp, v);
  818.     /*
  819.      * Extract and verify list of modems.
  820.      */
  821.     if (!(val = find_val(v, "MODEMS")))
  822.     yyerror(path, "ROTARY definition must have MODEMS defined");
  823.     else {
  824.     int n;
  825.     mp->Modems = modem_list(path, val, &mp->NModems, "ROTARY", mp->Name);
  826.     if (!mp->DialScript)
  827.         for (n = mp->NModems, mpp = mp->Modems; n-- ; mpp++)
  828.         if (!(*mpp)->DialScript)
  829.             yyerror(path, "ROTARY/MODEM %s/%s has no dialing script",
  830.                 mp->Name, (*mpp)->Name);
  831.     if (!mp->Speed)
  832.         for (n = mp->NModems, mpp = mp->Modems; n-- ; mpp++)
  833.         if (!(*mpp)->Speed)
  834.             yyerror(path, "ROTARY/MODEM %s/%s has no baud rate set",
  835.                 mp->Name, (*mpp)->Name);
  836.     }
  837.     
  838.     /*
  839.      * Make sure we used everything that was given.
  840.      */
  841.     unused_vals(path, "ROTARY", mp->Name, v);
  842. }
  843.  
  844.  
  845. def_modem_rotary(path, mp, v)
  846. char *path;
  847. MODEM *mp;
  848. var_val *v;
  849. {
  850.     char *val;
  851.  
  852.     if (val = find_val(v, "BAUD"))
  853.     switch (mp->Speed = atoi(val)) {
  854.      case 1200:
  855.      case 2400:
  856.      case 4800:
  857.      case 9600:
  858.      case 19200:
  859.      case 38400:
  860. #ifdef    STS
  861.      case 57600:
  862. #endif    STS
  863. #ifdef    FASTZS
  864.      case 76800:
  865. #endif    FASTZS
  866.         break;
  867.      default:
  868.         yyerror(path, "Bad MODEM speed \"%s\"\n", val);
  869.         break;
  870.     }
  871.  
  872.     if (val = find_val(v, "DIAL_SCRIPT"))
  873.     mp->DialScript = savestr(val);
  874.  
  875.     if (val = find_val(v, "DIAL_CHARMAP"))
  876.     mp->DialCharMap = savestr(val);
  877.  
  878.     if (val = find_val(v, "ASYNC_MAP"))
  879.     mp->AsyncMap = strtol(val, (char **)0, 16);
  880. }
  881.  
  882. def_if(path, v)
  883. char *path;
  884. var_val *v;
  885. {
  886.     REMOTE *rp;
  887.     char *val;
  888.  
  889.     if (!(val = find_val(v, "IF")))
  890.     yyerror(path, "IF definition must have IF defined");
  891.     else {
  892.     if (rp = findconfig(val)) {
  893.         yyerror(path, "IF \"%s\" defined more than once", rp->Sitename);
  894.         free_remote(rp);
  895.     }
  896.     else
  897.         rp = &RemoteTable[RemoteCount++];
  898.     if (strlen(val) > MAXDEVLEN)
  899.         yyerror(path, "IF \"%s\" name too long (> %d)",
  900.             rp->Sitename, MAXDEVLEN);
  901.     else {
  902.         (void)strcpy(rp->Device, val);
  903.         while (*val && !isdigit(*val))
  904.         val++;
  905.         if ((rp->Unit = atoi(val)) < 0) {
  906.         yyerror(path, "IF \"%s\" bad unit number (%d)",
  907.             rp->Sitename, rp->Unit);
  908.         }
  909.     }
  910.     }
  911.  
  912.     if (!if_addrs(rp))
  913.     return;
  914.  
  915.     if (val = find_val(v, "SYS"))
  916.     rp->Sitename = savestr(val);
  917.     else {
  918.     struct hostent *hp = gethostbyaddr((char *)&rp->DstAddress,
  919.                        sizeof(rp->DstAddress), AF_INET);
  920.     rp->Sitename = savestr(hp ? hp->h_name : inet_ntoa(rp->DstAddress));
  921.     }
  922.  
  923.     if (!(val = find_val(v, "MODEMS")))
  924.     yyerror(path, "IF definition must have MODEMS defined");
  925.     else
  926.     rp->Modems = modem_list(path, val, &rp->NModems, "IF", rp->Sitename);
  927.  
  928.     if (val = find_val(v, "LOGIN_SCRIPT"))
  929.     rp->Script = savestr(val);
  930.     if (val = find_val(v, "LOGIN_ARGS"))
  931.     rp->ScriptArgs = saveargs(path, val);
  932.  
  933.     if (val = find_val(v, "LOGIN"))
  934.     rp->Login = savestr(val);
  935.  
  936.     if (val = find_val(v, "PHONE"))
  937.     rp->Phone = savestr(val);
  938.  
  939.     if (val = find_val(v, "ASYNC_MAP"))
  940.     rp->AsyncMap = strtol(val, (char **)0, 16);
  941.  
  942.     if (val = find_val(v, "LOG_LEVEL"))
  943.     rp->LogLevel = atoi(val);
  944.  
  945.     if (val = find_val(v, "TRACE")) {
  946.     char *p;
  947.     if ((p = strchr(val, '@')) && isdigit(p[1]) && p[2] == '\0')
  948.         rp->Transtyle = *++p == '0' ? TS_LOW : TS_HIGH;
  949.     else
  950.         rp->Transtyle = TS_LOW;
  951.     rp->Transcript = expand_dir_file("$DPTRACE_DIR", val);
  952.     }
  953.  
  954.     if (val = find_val(v, "PPP_ARGS"))
  955.     rp->PppArgs = saveargs(path, val);
  956.  
  957.     if (val = find_val(v, "AUX"))
  958.     rp->AuxProgram = savestr(val);
  959.     if (val = find_val(v, "AUX_ARGS"))
  960.     rp->AuxArgs = saveargs(path, val);
  961.  
  962.     if (val = find_val(v, "ACCESS"))
  963.     (void)readaccess(path, val, rp);
  964.  
  965.     /*
  966.      * Make sure we used everything that was given.
  967.      */
  968.     unused_vals(path, "IF", rp->Sitename, v);
  969. }
  970.  
  971. readaccess(cpath, path, rp)
  972. char *cpath,
  973.      *path;
  974. REMOTE *rp;
  975. {
  976.     int i;
  977.     FILE *F;
  978.     char *p, *word;
  979.     char buff[BUFSIZ];
  980.     long *timeouts;
  981.  
  982.     /* Set access defaults. */
  983.     for (i = 0; i < 7; i++)
  984.     rp->Times[i] = ~0;
  985.     for (i = 0; i < 8; i++)
  986.     rp->Protocols[i] = ~0;
  987.     for (rp->AllowCount = 0, i = 0; i < MAXHOSTS; i++)
  988.     rp->AllowTo[i].s_addr = 0;
  989.     for (rp->DisallowCount = 0, i = 0; i < MAXHOSTS; i++)
  990.     rp->DisallowFrom[i].s_addr = 0;
  991.     for (i = 0 ; i < DP_NTIMEOUTS ; i++)
  992.     rp->DTimeouts[i] = rp->ATimeouts[i] = DP_NO_TIMEOUT;
  993.  
  994.     /* Field five, the access file. */
  995.     if (*path == '\0')
  996.     return errorcount == 0;
  997.  
  998.     path = expand_dirs_file("$DPCONF_DIR:$DPACCESS_DIR", path);
  999.     if ((F = fopen(path, "r")) == NULL) {
  1000.     yyerror(cpath, "Can't open access file \"%s\"", path);
  1001.     (void)free(path);
  1002.     return 0;
  1003.     }
  1004.  
  1005.     /* Read lines. */
  1006.     for (linenum = 1; fgets(buff, sizeof buff, F); linenum++) {
  1007.     if ((p = strchr(buff, '\n')) == NULL) {
  1008.         yyerror(buff, "Line too long", (char *)NULL);
  1009.         (void)fclose(F);
  1010.         (void)free(path);
  1011.         return 0;
  1012.     }
  1013.     *p = '\0';
  1014.     if ((word = strtok(buff, SEPARATORS)) == NULL)
  1015.         continue;
  1016.     if (*word == '#')
  1017.         continue;
  1018.     /*
  1019.      * Allow the setting of Dial out or Answer call timeouts seperately.
  1020.      * This should also be done for allowable call times, etc., but that
  1021.      * has not yet been implemented.
  1022.      */
  1023.     timeouts = rp->DTimeouts;
  1024.     if (strncmp(word, "answer:", sizeof("answer:")-1) == 0) {
  1025.         word += sizeof("answer:")-1;
  1026.         timeouts = rp->ATimeouts;
  1027.     }
  1028.     else if (strncmp(word, "dial:", sizeof("dial:")-1) == 0)
  1029.         word += sizeof("dial:")-1;
  1030.  
  1031.     /*
  1032.      * Dispatch on the word to fill in the fields.
  1033.      */
  1034.     if (EQ(word, "allowto") || EQ(word, "gooddstaddresses"))
  1035.         rp->AllowCount += parseaddresslist(path, rp->AllowTo);
  1036.     else if (EQ(word, "disallowfrom") || EQ(word, "badsrcaddresses"))
  1037.         rp->DisallowCount += parseaddresslist(path, rp->DisallowFrom);
  1038.     else if (EQ(word, "protocols") || EQ(word, "goodprotocols")) {
  1039.         /*
  1040.          * specific protocols to allow
  1041.          * disallow all protocols first, then allow the specific ones
  1042.          * on the `protocols' line
  1043.          */
  1044.         for (i = 0 ;
  1045.          i < sizeof(rp->Protocols)/sizeof(rp->Protocols[0]) ;
  1046.          i++)
  1047.         rp->Protocols[i] = 0;
  1048.         parseprotocols(path, rp->Protocols, P_SET);
  1049.     }
  1050.     else if (EQ(word, "badprotocols")) {
  1051.         /*
  1052.          * specific protocols to disallow
  1053.          * start either with all enabled by default or with the ones
  1054.          * enabled by protocols or goodprotocols line
  1055.          */
  1056.         parseprotocols(path, rp->Protocols, P_RESET);
  1057.     }
  1058.     else if (EQ(word, "inactivity")) {
  1059.         if (p = nexttok())
  1060.         if (!positivenumber(p))
  1061.             yyerror(path, "Bad number \"%s\"", p);
  1062.         else
  1063.             timeouts[DP_ATIMEO] = atoi(p);
  1064.     }
  1065.     else if (EQ(word, "last_close")) {
  1066.         if (p = nexttok())
  1067.         if (!positivenumber(p))
  1068.             yyerror(path, "Bad number \"%s\"", p);
  1069.         else
  1070.             timeouts[DP_CTIMEO] = atoi(p);
  1071.     }
  1072.     else if (EQ(word, "non_tcp")) {
  1073.         if (p = nexttok())
  1074.         if (!positivenumber(p))
  1075.             yyerror(path, "Bad number \"%s\"", p);
  1076.         else
  1077.             timeouts[DP_UTIMEO] = atoi(p);
  1078.     }
  1079.     else if (EQ(word, "failedcall")) {
  1080.         if (p = nexttok())
  1081.         if (!positivenumber(p))
  1082.             yyerror(path, "Bad number \"%s\"", p);
  1083.         else
  1084.             timeouts[DP_FTIMEO] = atoi(p);
  1085.     }
  1086.     else if (EQ(word, "callwait")) {
  1087.         if (p = nexttok())
  1088.         if (!positivenumber(p))
  1089.             yyerror(path, "Bad number \"%s\"", p);
  1090.         else
  1091.             timeouts[DP_WTIMEO] = atoi(p);
  1092.     }
  1093.     else if (EQ(word, "weekdays"))
  1094.         rp->Times[1] = rp->Times[2] = rp->Times[3] =
  1095.         rp->Times[4] = rp->Times[5] = parsetime(path);
  1096.     else if (EQ(word, "weekends"))
  1097.         rp->Times[0] = rp->Times[6] = parsetime(path);
  1098.     else if (EQ(word, "sun") || EQ(word, "sunday"))
  1099.         rp->Times[0] = parsetime(path);
  1100.     else if (EQ(word, "mon") || EQ(word, "monday"))
  1101.         rp->Times[1] = parsetime(path);
  1102.     else if (EQ(word, "tue") || EQ(word, "tuesday"))
  1103.         rp->Times[2] = parsetime(path);
  1104.     else if (EQ(word, "wed") || EQ(word, "wednesday"))
  1105.         rp->Times[3] = parsetime(path);
  1106.     else if (EQ(word, "thu") || EQ(word, "thursday"))
  1107.         rp->Times[4] = parsetime(path);
  1108.     else if (EQ(word, "fri") || EQ(word, "friday"))
  1109.         rp->Times[5] = parsetime(path);
  1110.     else if (EQ(word, "sat") || EQ(word, "saturday"))
  1111.         rp->Times[6] = parsetime(path);
  1112.     else
  1113.         yyerror(path, "Bad parameter \"%s\"", word);
  1114.     }
  1115.  
  1116.     (void)free(path);
  1117.     (void)fclose(F);
  1118.     return errorcount == 0;
  1119. }
  1120.  
  1121.  
  1122. set_if_timeouts()
  1123. {
  1124.     REMOTE     *rp;
  1125.     int i;
  1126.  
  1127.     for (rp = RemoteTable, i = RemoteCount; --i >= 0; rp++)
  1128.     if (!if_dtimeouts(rp))
  1129.         return 0;
  1130.     return 1;
  1131. }
  1132.  
  1133. /*
  1134.  * Get the internet addresses from the kernel for the given interface.
  1135.  */
  1136. if_addrs(rp)
  1137. REMOTE        *rp;
  1138. {
  1139.     static char        WHERE[] = "if_addrs";
  1140.     int            s;
  1141.     struct ifreq    ifr;
  1142.  
  1143.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  1144.     d_log(DLOG_GENERAL, WHERE,
  1145.           "Can't create socket to read interface addresses for \"%s\", %m",
  1146.           rp->Device);
  1147.     return 0;
  1148.     }
  1149.     (void)strcpy(ifr.ifr_name, rp->Device);
  1150.     if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
  1151.     d_log(DLOG_GENERAL, WHERE,
  1152.           "Can't get interface address for \"%s\", %m", rp->Device);
  1153.     (void)close(s);
  1154.     return 0;
  1155.     }
  1156.     rp->Address = ((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr;
  1157.     if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
  1158.     d_log(DLOG_GENERAL, WHERE,
  1159.           "Can't get interface destination address for \"%s\", %m",
  1160.           rp->Device);
  1161.     (void)close(s);
  1162.     return 0;
  1163.     }
  1164.     rp->DstAddress = ((struct sockaddr_in *)(&ifr.ifr_dstaddr))->sin_addr;
  1165.     (void)close(s);
  1166.     if (rp->Address.s_addr == INADDR_ANY) {
  1167.     d_log(DLOG_GENERAL, WHERE,
  1168.           "Interface address for \"%s\" not configured, %m",
  1169.           rp->Device);
  1170.     return 0;
  1171.     }
  1172.     if (rp->DstAddress.s_addr == INADDR_ANY) {
  1173.     d_log(DLOG_GENERAL, WHERE,
  1174.           "Destination interface address for \"%s\" not configured, %m",
  1175.           rp->Device);
  1176.     return 0;
  1177.     }
  1178.     return 1;
  1179. }
  1180.  
  1181. if_dtimeouts(rp)
  1182. REMOTE     *rp;
  1183. {
  1184.     static char        WHERE[] = "if_dtimeouts";
  1185.     int            s;
  1186.     struct ifreq    ifr;
  1187. #define    to        ((u_long *)(ifr.ifr_data))
  1188.  
  1189.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  1190.     d_log(DLOG_GENERAL, WHERE,
  1191.           "Can't create socket to configure timeouts for \"%s\", %m",
  1192.           rp->Device);
  1193.     return 0;
  1194.     }
  1195.     (void)strcpy(ifr.ifr_name, rp->Device);
  1196.     (void)memcpy((caddr_t)to, (char *)&rp->DTimeouts[DP_ATIMEOUTS],
  1197.          DP_NATIMEOUTS * sizeof(rp->DTimeouts[0]));
  1198.     if (ioctl(s, SIOCSDPIATIMEO, (caddr_t)&ifr) < 0) {
  1199.     d_log(DLOG_GENERAL, WHERE,
  1200.           "Can't set Dial Activity Timeouts on \"%s\", %m", rp->Device);
  1201.     (void)close(s);
  1202.     return 0;
  1203.     }
  1204.     (void)strcpy(ifr.ifr_name, rp->Device);
  1205.     (void)memcpy((caddr_t)to, (char *)&rp->DTimeouts[DP_CTIMEOUTS],
  1206.          DP_NCTIMEOUTS * sizeof(rp->DTimeouts[0]));
  1207.     if (ioctl(s, SIOCSDPICTIMEO, (caddr_t)&ifr) < 0) {
  1208.     d_log(DLOG_GENERAL, WHERE,
  1209.           "Can't set Dial Call Timeouts on \"%s\", %m", rp->Device);
  1210.     (void)close(s);
  1211.     return 0;
  1212.     }
  1213.     d_log(DLOG_ALL, WHERE, "Set Dial Timeouts for \"%s\"", rp->Device);
  1214.     (void)close(s);
  1215.     return 1;
  1216. }
  1217.  
  1218. if_atimeouts(rp)
  1219. REMOTE     *rp;
  1220. {
  1221.     static char        WHERE[] = "if_atimeouts";
  1222.     int            s;
  1223.     struct ifreq    ifr;
  1224. #define    to        ((u_long *)(ifr.ifr_data))
  1225.  
  1226.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  1227.     d_log(DLOG_GENERAL, WHERE,
  1228.           "Can't create socket to configure timeouts for \"%s\", %m",
  1229.           rp->Device);
  1230.     return 0;
  1231.     }
  1232.     (void)strcpy(ifr.ifr_name, rp->Device);
  1233.     (void)memcpy((caddr_t)to, (char *)&rp->ATimeouts[DP_ATIMEOUTS],
  1234.          DP_NATIMEOUTS * sizeof(rp->ATimeouts[0]));
  1235.     if (ioctl(s, SIOCSDPIATIMEO, (caddr_t)&ifr) < 0) {
  1236.     d_log(DLOG_GENERAL, WHERE,
  1237.           "Can't set Answer Activity Timeouts on \"%s\", %m", rp->Device);
  1238.     (void)close(s);
  1239.     return 0;
  1240.     }
  1241.     d_log(DLOG_ALL, WHERE, "Set Answer Timeouts for \"%s\"", rp->Device);
  1242.     (void)close(s);
  1243.     return 1;
  1244. }
  1245.