home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.lbl.gov / 2014.05.ftp.ee.lbl.gov.tar / ftp.ee.lbl.gov / acld-1.11.tar.gz / acld-1.11.tar / acld-1.11 / util.c < prev    next >
C/C++ Source or Header  |  2012-02-08  |  22KB  |  1,138 lines

  1. /*
  2.  * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011, 2012
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21.  
  22. #ifndef lint
  23. static const char rcsid[] =
  24.     "@(#) $Id: util.c 809 2012-02-09 01:17:58Z leres $ (LBL)";
  25. #endif
  26.  
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <sys/time.h>
  30.  
  31. #include <netinet/in.h>
  32.  
  33. #include <arpa/inet.h>
  34.  
  35. #include <ctype.h>
  36. #include <errno.h>
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <sysexits.h>
  41. #include <syslog.h>
  42. #include <unistd.h>
  43.  
  44. #include "acld.h"
  45.  
  46. /* Locals */
  47. struct s2v syslog2str[] = {
  48.     { "auth",    LOG_AUTH, },
  49.     { "authpriv",    LOG_AUTHPRIV, },
  50. #ifdef LOG_CONSOLE
  51.     { "console",    LOG_CONSOLE, },
  52. #endif
  53.     { "cron",    LOG_CRON, },
  54.     { "daemon",    LOG_DAEMON, },
  55.     { "ftp",    LOG_FTP, },
  56.     { "kern",    LOG_KERN, },
  57.     { "lpr",    LOG_LPR, },
  58.     { "mail",    LOG_MAIL, },
  59.     { "news",    LOG_NEWS, },
  60. #ifdef LOG_NTP
  61.     { "ntp",    LOG_NTP, },
  62. #endif
  63. #ifdef LOG_SECURITY
  64.     { "security",    LOG_SECURITY, },
  65. #endif
  66.     { "syslog",    LOG_SYSLOG, },
  67.     { "user",    LOG_USER, },
  68.     { "uucp",    LOG_UUCP, },
  69.     { "local0",    LOG_LOCAL0, },
  70.     { "local1",    LOG_LOCAL1, },
  71.     { "local2",    LOG_LOCAL2, },
  72.     { "local3",    LOG_LOCAL3, },
  73.     { "local4",    LOG_LOCAL4, },
  74.     { "local5",    LOG_LOCAL5, },
  75.     { "local6",    LOG_LOCAL6, },
  76.     { "local7",    LOG_LOCAL7, },
  77.     { NULL,        -1, }
  78. };
  79.  
  80. static struct stat sbuf;
  81.  
  82. void
  83. addr2sa(struct addr *a, u_short port, struct sockaddr *sap)
  84. {
  85.     struct sockaddr_in *s4p;
  86.     struct sockaddr_in6 *s6p;
  87.  
  88.     memset(sap, 0, sizeof(*sap));
  89. #ifdef HAVE_SOCKADDR_SA_LEN
  90.     sap->sa_len = sizeof(*sap);
  91. #endif
  92.     sap->sa_family = a->family;
  93.  
  94.     switch (a->family) {
  95.  
  96.     case AF_INET:
  97.         s4p = (struct sockaddr_in *)sap;
  98.         s4p->sin_port = htons(port);
  99.         memmove(&s4p->sin_addr, &a->addr4, sizeof(s4p->sin_addr));
  100.         break;
  101.  
  102.     case AF_INET6:
  103.         s6p = (struct sockaddr_in6 *)sap;
  104.         s6p->sin6_port = htons(port);
  105.         memmove(&s6p->sin6_addr, &a->addr6, sizeof(s6p->sin6_addr));
  106.         break;
  107.  
  108.     default:
  109.         abort();
  110.     }
  111. }
  112.  
  113. const char *
  114. addr2str(const struct addr *addr)
  115. {
  116.     int w;
  117.     size_t len, size;
  118.     char *cp;
  119.     static char buf[128];
  120.  
  121.     w = maskwidth(addr);
  122.     switch (addr->family) {
  123.  
  124.     case AF_INET:
  125.         if (inet_ntop(addr->family, &addr->addr4,
  126.             buf, sizeof(buf)) == NULL) {
  127.             lg(LOG_ERR, "addr2str: v4 botch");
  128.             abort();
  129.         }
  130.         if (w == 32)
  131.             return (buf);
  132.         break;
  133.  
  134.     case AF_INET6:
  135.         if (inet_ntop(addr->family, &addr->addr6,
  136.             buf, sizeof(buf)) == NULL) {
  137.             lg(LOG_ERR, "addr2str: v6 botch");
  138.             abort();
  139.         }
  140.         if (w == 128)
  141.             return (buf);
  142.         break;
  143.  
  144.     default:
  145.         abort();
  146.     }
  147.  
  148.     /* Append address mask width */
  149.     cp = buf;
  150.     len = strlen(cp);
  151.     cp += len;
  152.     size = sizeof(buf) - len;
  153.     (void)snprintf(cp, size, "/%d", w);
  154.     return (buf);
  155. }
  156.  
  157. /* Return and error message if there is a problem */
  158. const char *
  159. checklimits(struct cf *cf, struct acllist *ap)
  160. {
  161.     struct acllimit *alp;
  162.     static char buf[128];
  163.  
  164.     /* Check cap on maxium number of acls */
  165.     if (cf->c_maxseq > 0 && ap->acllen >= cf->c_maxseq) {
  166.         (void)snprintf(buf, sizeof(buf),
  167.             "No free slots in ACL %s (%d in use, %d allowed)",
  168.             ap->name, (int)ap->acllen, (int)cf->c_maxseq);
  169.         return (buf);
  170.     }
  171.  
  172.     /* Check limit on ACLs group */
  173.     if ((alp = ap->limitp) != NULL && alp->a_len >= alp->a_maxseq) {
  174.         (void)snprintf(buf, sizeof(buf),
  175.             "No free slots in ACL %s (group %s)"
  176.             " (%d in use, %d allowed)",
  177.             ap->name,
  178.             fmtargv(alp->a_nacls, alp->a_acls),
  179.             alp->a_len,
  180.             alp->a_maxseq);
  181.         return (buf);
  182.     }
  183.     return (NULL);
  184. }
  185.  
  186. /* Reopen logfile if necessary */
  187. void
  188. checklf()
  189. {
  190.     struct stat sbuf2;
  191.  
  192.     /* Bail if not managing a logfile */
  193.     if (logfile == NULL)
  194.         return;
  195.  
  196.     /* Do checks if not first time through */
  197.     if (lf != NULL) {
  198.         /* Done if the file info matches */
  199.         if (stat(logfile, &sbuf2) >= 0 &&
  200.             sbuf2.st_ino == sbuf.st_ino && sbuf2.st_dev == sbuf.st_dev)
  201.             return;
  202.  
  203.         /* Close file */
  204.         if (fclose(lf) == EOF)
  205.             syslog(LOG_ERR, "checklf: fclose: %s: %m", logfile);
  206.     }
  207.  
  208.     /* Open for append in case logfile already exists */
  209.     lf = fopen(logfile, "a");
  210.     if (lf == NULL) {
  211.         fprintf(stderr, "%s: fopen: %s: %s\n",
  212.             prog, logfile, strerror(errno));
  213.         syslog(LOG_ERR, "checklf: fopen: %s: %m", logfile);
  214.         exit(EX_OSERR);
  215.     }
  216.  
  217.     /* Line buffering */
  218.     setlinebuf(lf);
  219.  
  220.     /* Sock away stat() info */
  221.     if (fstat(fileno(lf), &sbuf) < 0) {
  222.         fprintf(stderr, "%s: fstat: %s: %s\n",
  223.             prog, logfile, strerror(errno));
  224.         syslog(LOG_ERR, "checklf: fstat: %s: %m", logfile);
  225.     }
  226. }
  227.  
  228. const char *
  229. checkmaskwidth(struct cf *cf, const struct addr *a)
  230. {
  231.     int w;
  232.     static char buf[64];
  233.  
  234.     w = (a->family == AF_INET) ? cf->c_ipv4_maxwidth : cf->c_ipv6_maxwidth;
  235.     if (maskwidth(a) < w) {
  236.         (void)snprintf(buf, sizeof(buf),
  237.             "Subnet mask wider than /%d not supported", w);
  238.         return (buf);
  239.     }
  240.     return (NULL);
  241. }
  242.  
  243. /*
  244.  *    p    - pointer to dynamic memory
  245.  *    len    - desired new length (objects)
  246.  *    sizep    - returned length of dynamic buffer (objects)
  247.  *    osize    - object size (bytes)
  248.  *    isize    - initial size (objects)
  249.  *    inc    - incremental size (objects)
  250.  *    what    - string for error message
  251.  */
  252. void *
  253. dynarray(void *p, size_t len, size_t *sizep, size_t osize, int isize,
  254.     int inc, const char *what)
  255. {
  256.  
  257.     /* Initial allocation? */
  258.     if (p == NULL) {
  259.         /* Get initial size from *sizep, isize or len */
  260.         if (*sizep <= 0)
  261.             *sizep = isize;
  262.         if (*sizep < len)
  263.             *sizep = len;
  264.         p = new(*sizep, osize, what);
  265.         return (p);
  266.     }
  267.     if (*sizep <= (len + inc/2)) {
  268.         *sizep = len + inc;
  269.         p = realloc(p, *sizep * osize);
  270.         if (p == NULL) {
  271.             lg(LOG_ERR, "dynarray: realloc %s: %s",
  272.                 what, strerror(errno));
  273.             exit(EX_OSERR);
  274.         }
  275.         memset(p + len * osize, 0, (*sizep - len) * osize);
  276.     }
  277.     return (p);
  278. }
  279.  
  280. const char *
  281. escapestr(const char *str)
  282. {
  283.     char *cp;
  284.     const char *p;
  285.     size_t n;
  286.     static char *result = NULL;
  287.     static char escapes[] = "$[]{}\"\\";    /* XXX check this in book */
  288.  
  289.     if (result != NULL) {
  290.         free(result);
  291.         result = NULL;
  292.     }
  293.  
  294.     /* Return a expect style null */
  295.     if (str == NULL || *str == '\0')
  296.         return ("{}");
  297.  
  298.     /* Enough space for string and EOS */
  299.     n = strlen(str) + 1;
  300.  
  301.     /* Add room for escapes */
  302.     for (p = str; *p != '\0'; ++p)
  303.         if (strchr(escapes, *p) != NULL)
  304.             ++n;
  305.  
  306.     result = malloc(n);
  307.     if (result == NULL) {
  308.         fprintf(lf, "%s: escapenaem: malloc: %s",
  309.             prog, strerror(errno));
  310.         exit(EX_OSERR);
  311.     }
  312.     p = str;
  313.     cp = result;
  314.     while (*p != '\0') {
  315.         if (strchr(escapes, *p) != NULL)
  316.             *cp++ = '\\';
  317.         *cp++ = *p++;
  318.     }
  319.     *cp = '\0';
  320.  
  321.     return (result);
  322. }
  323.  
  324. /* Extract an IPv4 or IPv6 host or network address */
  325. const char *
  326. extractaddr(const char *s1, const char *s2, struct addr *a)
  327. {
  328.     int i;
  329.     long w;
  330.     char *cp, *ep;
  331.     const char *p;
  332.     char temp[64];
  333.  
  334.     memset(a, 0, sizeof(*a));
  335.  
  336.     /* Let's see what we've got here */
  337.     if (strchr(s1, '.') != NULL) {
  338.         a->family = AF_INET;
  339.         w = 32;
  340.     } else if (strchr(s1, ':') != NULL) {
  341.         a->family = AF_INET6;
  342.         w = 128;
  343.     } else
  344.         return ("unrecognized address type");
  345.  
  346.     p = strchr(s1, '/');
  347.     if (p != NULL) {
  348.         /* Mask length was specified */
  349.         if (s2 != NULL)
  350.             return ("garbage following mask width");
  351.  
  352.         strncpy(temp, s1, sizeof(temp));
  353.         temp[sizeof(temp) - 1] = '\0';
  354.         cp = strchr(temp, '/');
  355.         if (cp == NULL)
  356.             abort();
  357.         *cp++ = '\0';
  358.         ep = NULL;
  359.         w = strtol(cp, &ep, 10);
  360.         if (*ep != '\0')
  361.             return ("garbage following mask width");
  362.         s1 = temp;
  363.     }
  364.  
  365.     switch (a->family) {
  366.  
  367.     case AF_INET:
  368.         if (!inet_pton(a->family, s1, &a->addr4))
  369.             return ("cannot parse IPv4 address");
  370.         if (s2 != NULL) {
  371.             if (!inet_pton(a->family, s2, &a->mask4))
  372.                 return ("cannot parse IPv4 address mask");
  373.             w = maskwidth(a);
  374.         }
  375.  
  376.         if (w > 32)
  377.             return ("mask length must be <= 32");
  378.         setmaskwidth(w, a);
  379.  
  380.         if ((a->addr4 & ~a->mask4) != 0)
  381.             return ("non-network bits set in addr");
  382.  
  383. #ifdef notdef
  384.         if ((ntohl(a->addr4) & 0xff000000) == 0)
  385.             return ("high octet must be non-zero");
  386. #endif
  387.         break;
  388.  
  389.     case AF_INET6:
  390.         if (!inet_pton(a->family, s1, &a->addr6))
  391.             return ("cannot parse IPv6 address");
  392.         if (s2 != NULL) {
  393.             if (!inet_pton(a->family, s2, &a->mask6))
  394.                 return ("cannot parse IPv6 address mask");
  395.             w = maskwidth(a);
  396.         }
  397.         if (w > 128)
  398.             return ("mask length must be <= 128");
  399.         setmaskwidth(w, a);
  400.  
  401.         for (i = 0; i < 16; ++i) {
  402.             if ((a->addr6[i] & ~a->mask6[i]) != 0)
  403.                 return ("non-network bits set in addr");
  404.         }
  405.         break;
  406.  
  407.     default:
  408.         abort();
  409.     }
  410.  
  411.  
  412.     return (NULL);
  413. }
  414.  
  415. /* Extract an IPv4 or IPv6 host address */
  416. const char *
  417. extracthost(const char *s1, const char *s2, struct addr *a)
  418. {
  419.     const char *p;
  420.  
  421.     p = extractaddr(s1, s2, a);
  422.     if (p == NULL && !ISHOST(a))
  423.         p = "must be an address, not a network";
  424.     return (p);
  425. }
  426.  
  427. void
  428. freeargv(char **av)
  429. {
  430.     char **av2;
  431.  
  432.     if (av != NULL) {
  433.         av2 = av;
  434.         while (*av2 != NULL)
  435.             free(*av2++);
  436.         free(av);
  437.     }
  438. }
  439.  
  440. void *
  441. freedynarray(void *p, size_t *lenp, size_t *sizep)
  442. {
  443.     if (p != NULL)
  444.         free(p);
  445.     *lenp = 0;
  446.     *sizep = 0;
  447.     return (NULL);
  448. }
  449.  
  450. void
  451. getts(struct timeval *tsp)
  452. {
  453.  
  454.     if (gettimeofday(tsp, NULL) < 0) {
  455.         /* Can't use lg() since it can indirectly call us */
  456.         syslog(LOG_ERR, "getts: gettimeofday: %s", strerror(errno));
  457.         exit(EX_OSERR);
  458.     }
  459. }
  460.  
  461. int
  462. insubnet(const struct addr *net, const struct addr *a)
  463. {
  464.     int i;
  465.  
  466.     if (net->family != a->family)
  467.         return (0);
  468.  
  469.     switch (net->family) {
  470.  
  471.     case AF_INET:
  472.         return (net->addr4 == (a->addr4 & net->mask4));
  473.  
  474.     case AF_INET6:
  475.         for (i = 0; i < 16; ++i)
  476.             if (net->addr6[i] != (a->addr6[i] & net->mask6[i]))
  477.                 return (0);
  478.         return (1);
  479.  
  480.     default:
  481.         abort();
  482.     }
  483. }
  484.  
  485. /*
  486.  * Return true if the addr is a default for its address family
  487.  * This means all address and maskbits are zero
  488.  */
  489. int
  490. isdefaultaddr(struct addr *a)
  491. {
  492.     int i;
  493.  
  494.     switch (a->family) {
  495.  
  496.     case AF_INET:
  497.         return (a->addr4 == 0 && a->mask4 == 0);
  498.  
  499.     case AF_INET6:
  500.         for (i = 0; i < 16; ++i)
  501.             if (a->addr6[i] != 0 || a->mask6[i] != 0)
  502.                 return (0);
  503.     
  504.         /* If we got here, all bytes were zero */
  505.         return (1);
  506.      
  507.     default:
  508.         abort();
  509.     }
  510. }
  511.  
  512. void
  513. lg(int pri, const char *fmt, ...)
  514. {
  515.     va_list ap;
  516.  
  517.     if (debug) {
  518.         if (logfile != NULL)
  519.             checklf();
  520.         fputs(tsstr(), lf);
  521.         putc(' ', lf);
  522.         va_start(ap, fmt);
  523.         (void)vfprintf(lf, fmt, ap);
  524.         va_end(ap);
  525.         putc('\n', lf);
  526.     }
  527.  
  528.     va_start(ap, fmt);
  529.     vsyslog(pri, fmt, ap);
  530.     va_end(ap);
  531. }
  532.  
  533. const char *
  534. fmtargv(int ac, char **av)
  535. {
  536.     int i;
  537.     static char buf[256];
  538.     char *cp;
  539.     size_t len, size;
  540.  
  541.     cp = buf;
  542.     size = sizeof(buf);
  543.  
  544.     for (i = 0; i < ac; ++i) {
  545.         if (i > 0 && size > 1) {
  546.             *cp++ = ' ';
  547.             --size;
  548.         }
  549.         len = snprintf(cp, size, "%s", av[i]);
  550.         if (len < 0)
  551.             abort();
  552.         cp += len;
  553.         size -= len;
  554.     }
  555.     *cp = '\0';
  556.     return (buf);
  557. }
  558.  
  559. int
  560. makeargv(const char *args, char ***avp)
  561. {
  562.     const char *p, *p2, *ep;
  563.     int n, len;
  564.     char **av;
  565.  
  566.     if (args == NULL)
  567.         return (0);
  568.  
  569.     /* Setup end pointer (trimming trailing whitespace) */
  570.     p = args;
  571.     ep = args + strlen(args);
  572.     while (ep - 1 >= args && isspace((int)ep[-1]))
  573.         --ep;
  574.  
  575.     /* Eat leading whitespace */
  576.     while (isspace((int)*args))
  577.         ++args;
  578.     /* Count arguments */
  579.     n = 0;
  580.     while (p < ep) {
  581.         if (!isspace((int)*p)) {
  582.             ++n;
  583.             while (p < ep && !isspace((int)*p))
  584.                 ++p;
  585.         }
  586.         while (p < ep && isspace((int)*p))
  587.             ++p;
  588.     }
  589.  
  590.     av = new(n + 1, sizeof(*av), "makeargs av");
  591.     *avp = av;
  592.  
  593.     /* Copy arguments */
  594.     n = 0;
  595.     p = args;
  596.     p2 = p;
  597.     while (p < ep) {
  598.         if (!isspace((int)*p)) {
  599.             ++n;
  600.             while (p < ep && !isspace((int)*p))
  601.                 ++p;
  602.             len = p - p2;
  603.             *av = new(len + 1, sizeof(char), "makeargs string");
  604.             strncpy(*av, p2, len);
  605.             av[0][len] = '\0';
  606.             ++av;
  607.         }
  608.         while (p < ep && isspace((int)*p))
  609.             ++p;
  610.         p2 = p;
  611.     }
  612.  
  613.     return (n);
  614. }
  615.  
  616. int
  617. maskwidth(const struct addr *a)
  618. {
  619.     int w;
  620.     int i, j;
  621.     u_int32_t m, tm;
  622.  
  623.     /* Work backwards until we find a set bit */
  624.     switch (a->family) {
  625.  
  626.     case AF_INET:
  627.         m = ntohl(a->mask4);
  628.         for (w = 32; w > 0; --w) {
  629.             tm = 0xffffffff << (32 - w);
  630.             if (tm == m)
  631.                 break;
  632.         }
  633.         break;
  634.  
  635.     case AF_INET6:
  636.         w = 128;
  637.         for (j = 15; j >= 0; --j) {
  638.             m = a->mask6[j];
  639.             for (i = 8; i > 0; --w, --i) {
  640.                 tm = (0xff << (8 - i)) & 0xff;
  641.                 if (tm == m)
  642.                     return (w);
  643.             }
  644.         }
  645.         break;
  646.  
  647.     default:
  648.         abort();
  649.     }
  650.     return (w);
  651. }
  652.  
  653. void
  654. nets_log(struct state *sp, struct req *rp)
  655. {
  656.     char *cp;
  657.     const char *p;
  658.     struct timeval *tvp;
  659.     char detail[1024];
  660.     size_t cc, len;
  661.  
  662.     /* Completion timestamp */
  663.     tvp = &rp->cts;
  664.     if (tvp->tv_sec == 0 && tvp->tv_sec == 0)
  665.         getts(tvp);
  666.  
  667.     /* Initial pointer/size left */
  668.     cp = detail;
  669.     cc = sizeof(detail) - 1;
  670.  
  671.     /* Optional NETS id */
  672.     if (sp->cf->c_id != NULL) {
  673.         (void)snprintf(cp, cc, " id=%s", sp->cf->c_id);
  674.         len = strlen(cp);
  675.         cp += len;
  676.         cc -= len;
  677.     }
  678.  
  679.     /* Log the acllist name if we know it */
  680.     if (rp->acllist != NULL) {
  681.         (void)snprintf(cp, cc, " acl=%s", rp->acllist->name);
  682.         len = strlen(cp);
  683.         cp += len;
  684.         cc -= len;
  685.     }
  686.  
  687.     /* No default so we'll get an error for missing cases */
  688.     switch (rp->type) {
  689.  
  690.     case REQ_NULLZERO:
  691.     case REQ_NONULLZERO:
  692.         /* route detail */
  693.         if (rp->nullzero.type == ROUTE_NULLZERO )
  694.             (void)snprintf(cp, cc, " ip=%s",
  695.                 addr2str(&rp->nullzero.dst));
  696.         break;
  697.  
  698.     case REQ_DROP:
  699.     case REQ_RESTORE:
  700.     case REQ_BLOCKHOSTHOST:
  701.     case REQ_RESTOREHOSTHOST:
  702.     case REQ_DROPUDPPORT:
  703.     case REQ_RESTOREUDPPORT:
  704.     case REQ_DROPTCPPORT:
  705.     case REQ_RESTORETCPPORT:
  706.     case REQ_PERMITUDPDSTHOSTPORT:
  707.     case REQ_UNPERMITUDPDSTHOSTPORT:
  708.     case REQ_PERMITTCPDSTHOSTPORT:
  709.     case REQ_UNPERMITTCPDSTHOSTPORT:
  710.     case REQ_DROPTCPDSTHOSTPORT:
  711.     case REQ_RESTORETCPDSTHOSTPORT:
  712.     case REQ_COMPACT:
  713.         /* ACL detail */
  714.         switch (rp->acl.type) {
  715.  
  716.         case ATYPE_PERMITHOST:
  717.         case ATYPE_BLOCKHOST:
  718.             (void)snprintf(cp, cc, " ip=%s",
  719.                 addr2str(&rp->acl.addr1));
  720.             break;
  721.  
  722.         case ATYPE_PERMITNET:
  723.         case ATYPE_BLOCKNET:
  724.             (void)snprintf(cp, cc, " net=%s",
  725.                 addr2str(&rp->acl.addr1));
  726.             break;
  727.  
  728.         case ATYPE_PERMITHOSTHOST:
  729.         case ATYPE_BLOCKHOSTHOST:
  730.             (void)snprintf(cp, cc, " ip=%s",
  731.                 addr2str(&rp->acl.addr1));
  732.             len = strlen(cp);
  733.             cp += len;
  734.             cc -= len;
  735.  
  736.             (void)snprintf(cp, cc, " ip2=%s",
  737.                 addr2str(&rp->acl.addr2));
  738.             break;
  739.  
  740.         case ATYPE_PERMITUDPPORT:
  741.         case ATYPE_BLOCKUDPPORT:
  742.         case ATYPE_PERMITTCPPORT:
  743.         case ATYPE_BLOCKTCPPORT:
  744.             (void)snprintf(cp, cc, " port=%s", rp->acl.port1);
  745.             break;
  746.  
  747.         case ATYPE_PERMITUDPHOSTPORT:
  748.         case ATYPE_BLOCKUDPHOSTPORT:
  749.         case ATYPE_PERMITTCPHOSTPORT:
  750.         case ATYPE_BLOCKTCPHOSTPORT:
  751.         case ATYPE_PERMITUDPDSTHOSTPORT:
  752.         case ATYPE_BLOCKUDPDSTHOSTPORT:
  753.         case ATYPE_PERMITTCPDSTHOSTPORT:
  754.         case ATYPE_BLOCKTCPDSTHOSTPORT:
  755.         case ATYPE_PERMITUDPHOSTSRCPORT:
  756.         case ATYPE_BLOCKUDPHOSTSRCPORT:
  757.         case ATYPE_PERMITTCPHOSTSRCPORT:
  758.         case ATYPE_BLOCKTCPHOSTSRCPORT:
  759.             (void)snprintf(cp, cc, " ip=%s port=%s",
  760.                 addr2str(&rp->acl.addr1), rp->acl.port1);
  761.             break;
  762.  
  763.         default:
  764.             (void)snprintf(cp, cc, " ?=ATYPE_#%d",
  765.                 rp->acl.type);
  766.             break;
  767.         }
  768.         break;
  769.  
  770.     case REQ_ADDWHITELIST:
  771.     case REQ_REMWHITELIST:
  772.         /* whitelist detail */
  773.         if (ISHOST(&rp->whitelist))
  774.             p = "ip";
  775.         else
  776.             p = "net";
  777.         (void)snprintf(cp, cc, " %s=%s", p, addr2str(&rp->whitelist));
  778.         break;
  779.  
  780.     case REQ_AYT:
  781.     case REQ_EXIT:
  782.     case REQ_HELP:
  783.     case REQ_LISTACL:
  784.     case REQ_LISTROUTE:
  785.     case REQ_QUERY:
  786.     case REQ_QUERYNULLZERO:
  787.     case REQ_QUERYWHITELIST:
  788.     case REQ_RELOAD:
  789.     case REQ_STATE:
  790.     case REQ_SYNC:
  791.     case REQ_TEST:
  792.     case REQ_UNKNOWN:
  793.     case REQ_WHITELIST:
  794.         /* Don't nets_log these */
  795.         return;
  796.     }
  797.  
  798.     /* Status */
  799.     if ((rp->flags & RFLAG_FAILED) != 0)
  800.         p = "failed";
  801.     else if ((rp->flags & RFLAG_IGNORE) != 0)
  802.         p = "ignore";
  803.     else
  804.         p = "success";
  805.  
  806.     syslog(sp->cf->c_netsfac | LOG_DEBUG,
  807.         "NETS status=%s cmd=%s%s ats=%lu.%06lu cts=%lu.%06lu cmt=%s",
  808.         p,
  809.         rp->cmd,
  810.         detail,
  811.         (u_long)rp->ats.tv_sec, (u_long)rp->ats.tv_usec,
  812.         (u_long)rp->cts.tv_sec, (u_long)rp->cts.tv_usec,
  813.         pretty(rp->comment));
  814. }
  815.  
  816. void *
  817. new(size_t num, size_t size, const char *what)
  818. {
  819.     void *p;
  820.  
  821.     p = calloc(num, size);
  822.     if (p == NULL) {
  823.         lg(LOG_ERR, "new: calloc %s: %s", what, strerror(errno));
  824.         exit(EX_OSERR);
  825.     }
  826.     return (p);
  827. }
  828.  
  829. const char *
  830. pretty(const char *str)
  831. {
  832.     size_t cc;
  833.     char *cp;
  834.     const char *p;
  835.     static char buf[8192];
  836.  
  837.     if (str == NULL)
  838.         return ("");
  839.  
  840.     cp = buf;
  841.     cc = sizeof(buf) - 1;
  842.  
  843.     /* Leave room for possible escape, char and eos */
  844.     for (p = str; *p != '\0' && cc >= 3; ++p) {
  845.         if (*p == '\n') {
  846.             *cp++ = '\\';
  847.             *cp++ = 'n';
  848.             cc -= 2;
  849.         } else if (*p == '\r') {
  850.             *cp++ = '\\';
  851.             *cp++ = 'r';
  852.             cc -= 2;
  853.         } else if (isprint((int)*p)) {
  854.             *cp++ = *p;
  855.             --cc;
  856.         } else {
  857.             /* DEL to ?, others to alpha */
  858.             *cp++ = '^';
  859.             *cp++ = *p ^ 0x40;
  860.             cc -= 2;
  861.         }
  862.     }
  863.     *cp = '\0';
  864.     return (buf);
  865. }
  866.  
  867. void
  868. sa2addr(struct sockaddr *sap, struct addr *a, u_int16_t *portp)
  869. {
  870.     struct sockaddr_in *s4p;
  871.     struct sockaddr_in6 *s6p;
  872.  
  873.     memset(a, 0, sizeof(*a));
  874.     a->family = sap->sa_family;
  875.  
  876.     switch (a->family) {
  877.  
  878.     case AF_INET:
  879.         s4p = (struct sockaddr_in *)sap;
  880.         *portp = ntohs(s4p->sin_port);
  881.         memmove(&a->addr4, &s4p->sin_addr, sizeof(a->addr4));
  882.         a->mask4 = 0xffffffff;
  883.         break;
  884.  
  885.     case AF_INET6:
  886.         s6p = (struct sockaddr_in6 *)sap;
  887.         *portp = ntohs(s6p->sin6_port);
  888.         memmove(&a->addr6, &s6p->sin6_addr, sizeof(a->addr6));
  889.         setmaskwidth(128, a);
  890.         break;
  891.  
  892.     default:
  893.         abort();
  894.     }
  895. }
  896.  
  897. /* Set address mask in network order */
  898. void
  899. setmaskwidth(u_int w, struct addr *a)
  900. {
  901.     int i, j;
  902.  
  903.     switch (a->family) {
  904.  
  905.     case AF_INET:
  906.         if (w <= 0)
  907.             a->mask4 = 0;
  908.         else
  909.             a->mask4 = htonl(0xffffffff << (32 - w));
  910.         break;
  911.  
  912.     case AF_INET6:
  913.         /* XXX is this right? */
  914.         memset(a->mask6, 0, sizeof(a->mask6));
  915.         for (i = 0; i < w / 8; ++i)
  916.             a->mask6[i] = 0xff;
  917.         i = w / 8;
  918.         j = w % 8;
  919.         if (j > 0 && i < 16)
  920.             a->mask6[i] = 0xff << (8 - j);
  921.         break;
  922.  
  923.     default:
  924.         abort();
  925.     }
  926. }
  927.  
  928. const char *
  929. simplewd(void)
  930. {
  931.     char *cp;
  932.     static char wd[1024];
  933.  
  934.     if (getcwd(wd, sizeof(wd)) == NULL) {
  935.         lg(LOG_ERR, "simplewd: getcwd: %s", strerror(errno));
  936.         exit(EX_OSERR);
  937.     }
  938.     cp = strrchr(wd, '/');
  939.     if (cp == NULL)
  940.         return (wd);
  941.     return (++cp);
  942. }
  943.  
  944. int
  945. suck2dot(FILE *f, char **pp)
  946. {
  947.     int n, size, len, i;
  948.     char *p, *cp;
  949.     char buf[1024];
  950.  
  951.     n = 0;
  952.     size = 256;
  953.     len = 0;
  954.     p = (char *)malloc(size);
  955.     if (p == NULL) {
  956.         lg(LOG_ERR, "suck2dot: malloc: %s", strerror(errno));
  957.         exit(EX_OSERR);
  958.     }
  959.     *p = '\0';
  960.     *pp = p;
  961.     while (fgets(buf, sizeof(buf), f) != NULL) {
  962.         ++n;
  963.         cp = buf;
  964.         /* Eat leading dot; done if there was only one */
  965.         if (*cp == '.' && *++cp == '\n' && cp[1] == '\0')
  966.             break;
  967.  
  968.         i = strlen(cp);
  969.         if (len + i + 1 > size) {
  970.             size += i + 256;
  971.             *pp = (char *)realloc(*pp, size);
  972.             if (*pp == NULL) {
  973.                 lg(LOG_ERR, "suck2dot: realloc: %s",
  974.                     strerror(errno));
  975.                 exit(EX_OSERR);
  976.             }
  977.             p = *pp + len;
  978.         }
  979.         strcpy(p, cp);
  980.         p += i;
  981.         len += i;
  982.     }
  983.     return (n);
  984. }
  985.  
  986. int
  987. str2val(const struct s2v *lp, const char *suffix)
  988. {
  989.     const struct s2v *tp;
  990.  
  991.     for (tp = lp; tp->s != NULL; ++tp)
  992.         if (strcmp(suffix, tp->s) == 0)
  993.             break;
  994.  
  995.     return (tp->v);
  996. }
  997.  
  998. int
  999. str2valcase(const struct s2v *lp, const char *suffix)
  1000. {
  1001.     const struct s2v *tp;
  1002.  
  1003.     for (tp = lp; tp->s != NULL; ++tp)
  1004.         if (strcasecmp(suffix, tp->s) == 0)
  1005.             break;
  1006.  
  1007.     return (tp->v);
  1008. }
  1009.  
  1010. void
  1011. strappend(char **pp, const char *str)
  1012. {
  1013.     int len;
  1014.  
  1015.     if (*pp == NULL)
  1016.         *pp = strsave(str);
  1017.     else {
  1018.         len = strlen(*pp);
  1019.         *pp = realloc(*pp, len + strlen(str) + 1);
  1020.         if (*pp == NULL) {
  1021.             lg(LOG_ERR, "strappend: realloc: %s", strerror(errno));
  1022.             exit(EX_OSERR);
  1023.         }
  1024.         strcpy(*pp + len, str);
  1025.     }
  1026. }
  1027.  
  1028. char *
  1029. strsave(const char *str)
  1030. {
  1031.     char *cp;
  1032.  
  1033.     cp = strdup(str);
  1034.     if (cp == NULL) {
  1035.         lg(LOG_ERR, "strsave: strdup: %s", strerror(errno));
  1036.         exit(EX_OSERR);
  1037.     }
  1038.     return (cp);
  1039. }
  1040.  
  1041. const char *
  1042. tcporudpreqstr(int rtype)
  1043. {
  1044.     const char *p;
  1045.  
  1046.     p = "?";
  1047.     switch (rtype) {
  1048.  
  1049.     case REQ_DROPUDPPORT:
  1050.     case REQ_RESTOREUDPPORT:
  1051.     case REQ_PERMITUDPDSTHOSTPORT:
  1052.     case REQ_UNPERMITUDPDSTHOSTPORT:
  1053.         p = "UDP";
  1054.         break;
  1055.  
  1056.     case REQ_DROPTCPPORT:
  1057.     case REQ_RESTORETCPPORT:
  1058.     case REQ_PERMITTCPDSTHOSTPORT:
  1059.     case REQ_UNPERMITTCPDSTHOSTPORT:
  1060.     case REQ_DROPTCPDSTHOSTPORT:
  1061.     case REQ_RESTORETCPDSTHOSTPORT:
  1062.         p = "TCP";
  1063.         break;
  1064.  
  1065.     case REQ_UNKNOWN:
  1066.     case REQ_RELOAD:
  1067.     case REQ_DROP:
  1068.     case REQ_RESTORE:
  1069.     case REQ_BLOCKHOSTHOST:
  1070.     case REQ_RESTOREHOSTHOST:
  1071.     case REQ_NULLZERO:
  1072.     case REQ_NONULLZERO:
  1073.     case REQ_STATE:
  1074.     case REQ_LISTACL:
  1075.     case REQ_LISTROUTE:
  1076.     case REQ_WHITELIST:
  1077.     case REQ_ADDWHITELIST:
  1078.     case REQ_REMWHITELIST:
  1079.     case REQ_QUERY:
  1080.     case REQ_QUERYNULLZERO:
  1081.     case REQ_QUERYWHITELIST:
  1082.     case REQ_COMPACT:
  1083.     case REQ_TEST:
  1084.     case REQ_EXIT:
  1085.     case REQ_HELP:
  1086.     case REQ_SYNC:
  1087.     case REQ_AYT:
  1088.         break;
  1089.     }
  1090.     return (p);
  1091. }
  1092.  
  1093. void
  1094. trimws(char *str, size_t len)
  1095. {
  1096.     char *cp;
  1097.  
  1098.     cp = str + len;
  1099.     while (cp > str && isspace((int)cp[-1]))
  1100.         --cp;
  1101.     *cp = '\0';
  1102. }
  1103.  
  1104. const char *
  1105. tsstr()
  1106. {
  1107.     struct timeval tv;
  1108.     static char buf[32];
  1109.  
  1110.     getts(&tv);
  1111.     (void)snprintf(buf, sizeof(buf), "%ld.%06ld",
  1112.         (u_long)tv.tv_sec, (u_long)tv.tv_usec);
  1113.     return (buf);
  1114. }
  1115.  
  1116. int
  1117. typ2flag(const struct v2v *lp, int wtype)
  1118. {
  1119.     const struct v2v *vp;
  1120.  
  1121.     for (vp = lp; vp->v1 != 0; ++vp)
  1122.         if (vp->v1 == wtype)
  1123.             break;
  1124.     return (vp->v2);
  1125. }
  1126.  
  1127. const char *
  1128. val2str(const struct s2v *lp, int val)
  1129. {
  1130.     const struct s2v *tp;
  1131.  
  1132.     for (tp = lp; tp->s != NULL; ++tp)
  1133.         if (val == tp->v)
  1134.             break;
  1135.  
  1136.     return (tp->s);
  1137. }
  1138.