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 / acl.c next >
C/C++ Source or Header  |  2011-10-16  |  24KB  |  1,018 lines

  1. /*
  2.  * Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011
  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: acl.c 796 2011-10-16 03:36:15Z leres $ (LBL)";
  25. #endif
  26.  
  27. #include <sys/types.h>
  28. #include <sys/time.h>
  29.  
  30. #include <ctype.h>
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <sysexits.h>
  35. #include <syslog.h>
  36.  
  37. #include "acld.h"
  38. #include "cf.h"
  39.  
  40. /* Globals */
  41. struct s2v str2acl[] = {
  42.     { "notconnected",    ATYPE_UNKNOWN },
  43.  
  44.     { "permitany",        ATYPE_PERMITANY },
  45.     { "blockany",        ATYPE_BLOCKANY },
  46.  
  47.     { "permithost",        ATYPE_PERMITHOST },
  48.     { "blockhost",        ATYPE_BLOCKHOST },
  49.  
  50.     { "permithosthost",    ATYPE_PERMITHOSTHOST },
  51.     { "blockhosthost",    ATYPE_BLOCKHOSTHOST },
  52.  
  53.     { "permitnet",        ATYPE_PERMITNET },
  54.     { "blocknet",        ATYPE_BLOCKNET },
  55.  
  56.     { "permitnethost",    ATYPE_PERMITNETHOST },
  57.     { "blocknethost",    ATYPE_BLOCKNETHOST },
  58.  
  59.     { "permitudpport",    ATYPE_PERMITUDPPORT },
  60.     { "blockudpport",    ATYPE_BLOCKUDPPORT },
  61.     { "permittcpport",    ATYPE_PERMITTCPPORT },
  62.     { "blocktcpport",    ATYPE_BLOCKTCPPORT },
  63.  
  64.     { "permitudphostport",    ATYPE_PERMITUDPHOSTPORT },
  65.     { "blockudphostport",    ATYPE_BLOCKUDPHOSTPORT },
  66.     { "permittcphostport",    ATYPE_PERMITTCPHOSTPORT },
  67.     { "blocktcphostport",    ATYPE_BLOCKTCPHOSTPORT },
  68.  
  69.     { "permitudpdsthost",    ATYPE_PERMITUDPDSTHOST },
  70.     { "blockudpdsthost",    ATYPE_BLOCKUDPDSTHOST },
  71.     { "permittcpdsthost",    ATYPE_PERMITTCPDSTHOST },
  72.     { "blocktcpdsthost",    ATYPE_BLOCKTCPDSTHOST },
  73.  
  74.     { "permitdsthost",    ATYPE_PERMITDSTHOST },
  75.     { "blockdsthost",    ATYPE_BLOCKDSTHOST },
  76.     { "permiticmpdsthost",    ATYPE_PERMITICMPDSTHOST },
  77.     { "blockicmpdsthost",    ATYPE_BLOCKICMPDSTHOST },
  78.  
  79.     { "permitdstnet",    ATYPE_PERMITDSTNET },
  80.     { "blockdstnet",    ATYPE_BLOCKDSTNET },
  81.     { "permiticmpdstnet",    ATYPE_PERMITICMPDSTNET },
  82.     { "blockicmpdstnet",    ATYPE_BLOCKICMPDSTNET },
  83.  
  84.     { "blockudpdsthostport", ATYPE_BLOCKUDPDSTHOSTPORT },
  85.     { "blocktcpdsthostport", ATYPE_BLOCKTCPDSTHOSTPORT },
  86.     { "permitudpdsthostport", ATYPE_PERMITUDPDSTHOSTPORT },
  87.     { "permittcpdsthostport", ATYPE_PERMITTCPDSTHOSTPORT },
  88.  
  89.     { "permitudpnetport",    ATYPE_PERMITUDPNETPORT },
  90.     { "blockudpnetport",    ATYPE_BLOCKUDPNETPORT },
  91.     { "permittcpnetport",    ATYPE_PERMITTCPNETPORT },
  92.     { "blocktcpnetport",    ATYPE_BLOCKTCPNETPORT },
  93.  
  94.     { "permitudphostsrcport", ATYPE_PERMITUDPHOSTSRCPORT },
  95.     { "blockudphostsrcport", ATYPE_BLOCKUDPHOSTSRCPORT },
  96.     { "permittcphostsrcport", ATYPE_PERMITTCPHOSTSRCPORT },
  97.     { "blocktcphostsrcport", ATYPE_BLOCKTCPHOSTSRCPORT },
  98.  
  99.     { "permitudphostpairdstport", ATYPE_PERMITUDPHOSTPAIRDSTPORT },
  100.     { "blockudphostpairdstport", ATYPE_BLOCKUDPHOSTPAIRDSTPORT },
  101.     { "permittcphostpairdstport", ATYPE_PERMITTCPHOSTPAIRDSTPORT },
  102.     { "blocktcphostpairdstport", ATYPE_BLOCKTCPHOSTPAIRDSTPORT },
  103.  
  104.     { "permitudpdstnet",    ATYPE_PERMITUDPDSTNET },
  105.     { "blockudpdstnet",    ATYPE_BLOCKUDPDSTNET },
  106.     { "permittcpdstnet",    ATYPE_PERMITTCPDSTNET },
  107.     { "blocktcpdstnet",    ATYPE_BLOCKTCPDSTNET },
  108.  
  109.     { "permitudpdstnetport", ATYPE_PERMITUDPDSTNETPORT },
  110.     { "blockudpdstnetport",    ATYPE_BLOCKUDPDSTNETPORT },
  111.     { "permittcpdstnetport", ATYPE_PERMITTCPDSTNETPORT },
  112.     { "blocktcpdstnetport",    ATYPE_BLOCKTCPDSTNETPORT },
  113.  
  114.     { "permitudpnethostport", ATYPE_PERMITUDPNETHOSTPORT },
  115.     { "blockudpnethostport", ATYPE_PERMITUDPNETHOSTPORT },
  116.     { "permittcpnethostport", ATYPE_PERMITTCPNETHOSTPORT },
  117.     { "blocktcpnethostport", ATYPE_PERMITTCPNETHOSTPORT },
  118.  
  119.     { NULL,            0 }
  120. };
  121.  
  122. /* Forwards */
  123. int aclcmp(const void *, const void *);
  124. int acllistcmp(const void *, const void *);
  125. int addrcmp(const void *, const void *);
  126.  
  127. void
  128. acladdacl(struct acllist *ap, struct acl *nal)
  129. {
  130.     struct acl *al;
  131.  
  132.     DYNARRAY(ap->acl, ap->acllen, &ap->aclsize,
  133.         sizeof(*ap->acl), 1024, 1024, "acl array");
  134.  
  135.     al = ap->acl + ap->acllen;
  136.     aclcopy(al, nal);
  137.  
  138.     ++ap->acllen;
  139.     stats_sethiwater(&ap->stats, ap->acllen);
  140.  
  141.     if (ap->limitp != NULL)
  142.         ++ap->limitp->a_len;
  143.  
  144.     /* Sort on sequence number (if we have them) */
  145.     if (ap->lastportseq >= 0 || ap->lastseq >= 0 ||
  146.         ap->lastpermithostportseq >= 0)
  147.         qsort(ap->acl, (size_t)ap->acllen, sizeof(*al), aclcmp);
  148. }
  149.  
  150. void
  151. acladdacllist(struct cf *cf, const char *str)
  152. {
  153.     int an;
  154.     const char *p;
  155.     char **av;
  156.     struct addr *a;
  157.     struct acllist *ap;
  158.  
  159.     an = makeargv(str, &av);
  160.     if (an != 2) {
  161.         lg(LOG_ERR, "acladdacllist wrong number of args: \"%s\"", str);
  162.         freeargv(av);
  163.         return;
  164.     }
  165.     ap = aclfindlistbyname(cf, av[0]);
  166.     if (ap == NULL) {
  167.         DYNARRAY(cf->c_acllist, cf->c_acllistlen,
  168.             &cf->c_acllistsize, sizeof(*cf->c_acllist),
  169.             1, 1, "cf acllist");
  170.         ap = cf->c_acllist + cf->c_acllistlen;
  171.         ap->name = strsave(av[0]);
  172.         ++cf->c_acllistlen;
  173.         ap->lastseq = -1;
  174.         ap->lastportseq = -1;
  175.         ap->lastpermithostportseq = -1;
  176.  
  177.     }
  178.     DYNARRAY(ap->addr, ap->addrlen, &ap->addrsize,
  179.         sizeof(*ap->addr), 128, 128, "acllist addrs");
  180.     stats_init(&ap->stats, 10, 60, "acladdacllist: stats");
  181.  
  182.     a = ap->addr + ap->addrlen;
  183.     p = extractaddr(av[1], NULL, a);
  184.     if (p != NULL) {
  185.         lg(LOG_ERR, "acladdacllist extractaddr: %s", p);
  186.         freeargv(av);
  187.         return;
  188.     }
  189.  
  190.     ++ap->addrlen;
  191.     freeargv(av);
  192. }
  193.  
  194. /* Copy an ACL saving char fields as required */
  195. void
  196. aclcopy(struct acl *dst, const struct acl *src)
  197. {
  198.  
  199.     *dst = *src;
  200.     if (dst->port1 != NULL)
  201.         dst->port1 = strsave(dst->port1);
  202.     if (dst->port2 != NULL)
  203.         dst->port2 = strsave(dst->port2);
  204.     if (dst->raw != NULL)
  205.         dst->raw = strsave(dst->raw);
  206. }
  207.  
  208. int
  209. aclcmp(const void *arg1, const void *arg2)
  210. {
  211.     const struct acl *al1, *al2;
  212.  
  213.     al1 = (const struct acl *)arg1;
  214.     al2 = (const struct acl *)arg2;
  215.     return (al1->seq - al2->seq);
  216. }
  217.  
  218. int
  219. acldeleteacl(struct acllist *ap, struct acl *oal)
  220. {
  221.     struct acl *al;
  222.     int i, n;
  223.  
  224.     for (i = 0, al = ap->acl; i < ap->acllen; ++i, ++al) {
  225.         if (al->type != oal->type)
  226.             continue;
  227.  
  228.         /* addr1 */
  229.         if (!ADDREQ(&al->addr1, &oal->addr1))
  230.             continue;
  231.  
  232.         /* addr2 */
  233.         if (!ADDREQ(&al->addr2, &oal->addr2))
  234.             continue;
  235.  
  236.         /* port1 */
  237.         if ((al->port1 != NULL) ^ (oal->port1 != NULL))
  238.             continue;
  239.         if (al->port1 != NULL && strcasecmp(al->port1, oal->port1) != 0)
  240.             continue;
  241.  
  242.         /* port2 */
  243.         if ((al->port2 != NULL) ^ (oal->port2 != NULL))
  244.             continue;
  245.         if (al->port2 != NULL && strcasecmp(al->port2, oal->port2) != 0)
  246.             continue;
  247.         break;
  248.     }
  249.     if (i >= ap->acllen)
  250.         return (0);
  251.  
  252.     if (al->port1 != NULL) {
  253.         free(al->port1);
  254.         al->port1 = NULL;
  255.     }
  256.     if (al->port2 != NULL) {
  257.         free(al->port2);
  258.         al->port2 = NULL;
  259.     }
  260.     if (al->raw != NULL) {
  261.         free(al->raw);
  262.         al->raw = NULL;
  263.     }
  264.  
  265.     n = ap->acllen - (i + 1);
  266.     memmove(al, al + 1, n * sizeof(*al));
  267.     --ap->acllen;
  268.     if (ap->limitp != NULL)
  269.         --ap->limitp->a_len;
  270.     memset(ap->acl + ap->acllen, 0, sizeof(*ap->acl));
  271.     return (1);
  272. }
  273.  
  274. /* If checksubnet, check for address in subnet */
  275. struct acl *
  276. aclfindacl(struct acllist *ap, struct acl *al, int checksubnet)
  277. {
  278.     int i;
  279.     struct acl *al2;
  280.  
  281.     for (i = 0, al2 = ap->acl; i < ap->acllen; ++i, ++al2) {
  282.         if (al->type != al2->type &&
  283.             (!checksubnet ||
  284.             al->type != ATYPE_BLOCKHOST ||
  285.             al2->type != ATYPE_BLOCKNET))
  286.             continue;
  287.  
  288.         switch (al->type) {
  289.  
  290.         case ATYPE_PERMITHOST:
  291.         case ATYPE_BLOCKHOST:
  292.             if (checksubnet && insubnet(&al2->addr1, &al->addr1))
  293.                 return (al2);
  294.             if (ADDREQ(&al->addr1, &al2->addr1))
  295.                 return (al2);
  296.             break;
  297.  
  298.         case ATYPE_PERMITNET:
  299.         case ATYPE_BLOCKNET:
  300.             if (ADDREQ(&al->addr1, &al2->addr1))
  301.                 return (al2);
  302.             break;
  303.  
  304.         case ATYPE_BLOCKHOSTHOST:
  305.             if (ADDREQ(&al->addr1, &al2->addr1) &&
  306.                 ADDREQ(&al->addr2, &al2->addr2))
  307.                 return (al2);
  308.             break;
  309.  
  310.         case ATYPE_BLOCKUDPPORT:
  311.         case ATYPE_BLOCKTCPPORT:
  312.             if (strcasecmp(al->port1, al2->port1) == 0)
  313.                 return (al2);
  314.             break;
  315.  
  316.         case ATYPE_PERMITUDPDSTHOSTPORT:
  317.         case ATYPE_BLOCKUDPDSTHOSTPORT:
  318.         case ATYPE_PERMITTCPDSTHOSTPORT:
  319.         case ATYPE_BLOCKTCPDSTHOSTPORT:
  320.             if (ADDREQ(&al->addr1, &al2->addr1) &&
  321.                 strcasecmp(al->port1, al2->port1) == 0)
  322.                 return (al2);
  323.             break;
  324.  
  325.         default:
  326.             break;
  327.         }
  328.     }
  329.     return (NULL);
  330. }
  331.  
  332. /* XXX when searching for a network, this doesn't find the widest mask match */
  333. struct acllist *
  334. aclfindlistbyaddr(struct cf *cf, struct addr *a)
  335. {
  336.     int i, j;
  337.     struct acllist *ap;
  338.     struct addr *a2;
  339.  
  340.     for (i = 0, ap = cf->c_acllist; i < cf->c_acllistlen; ++i, ++ap)
  341.         for (j = 0, a2 = ap->addr; j < ap->addrlen; ++j, ++a2)
  342.             if (insubnet(a2, a))
  343.                 return (ap);
  344.     return (NULL);
  345. }
  346.  
  347. struct acllist *
  348. aclfindlistbyname(struct cf *cf, const char *name)
  349. {
  350.     int i;
  351.     struct acllist *ap;
  352.  
  353.     for (i = 0, ap = cf->c_acllist; i < cf->c_acllistlen; ++i, ++ap)
  354.         if (strcmp(ap->name, name) == 0)
  355.             return (ap);
  356.     return (NULL);
  357. }
  358.  
  359. /* Find the default ACL list for the address family of the passed addr */
  360. struct acllist *
  361. aclfindlistdefault(struct cf *cf, struct addr *a)
  362. {
  363.     int i, j;
  364.     struct addr *a2;
  365.     struct acllist *ap;
  366.  
  367.     /*
  368.      * XXX We could probably move the family check to the outer
  369.      * loop but we would also have to make sure that each acl
  370.      * list contained homogenious address families
  371.      * (Which we should do!)
  372.      */
  373.     for (i = 0, ap = cf->c_acllist; i < cf->c_acllistlen; ++i, ++ap)
  374.         for (j = 0, a2 = ap->addr; j < ap->addrlen; ++j, ++a2)
  375.             if (a->family == a2->family && isdefaultaddr(a2))
  376.                 return (ap);
  377.     return (NULL);
  378. }
  379.  
  380. const char *
  381. aclformat(struct acl *al)
  382. {
  383.     const char *p;
  384.     char *cp;
  385.     size_t size, len;
  386.     static char buf[1024];
  387.  
  388.     p = val2str(str2acl, al->type);
  389.     cp = buf;
  390.     size = sizeof(buf);
  391.     (void)snprintf(cp, size, "%d %llu %s", al->seq, al->count, p);
  392.     len = strlen(cp);
  393.     size -= len;
  394.     cp += len;
  395.  
  396.     switch (al->type) {
  397.  
  398.     case ATYPE_PERMITANY:
  399.     case ATYPE_BLOCKANY:
  400.         break;
  401.  
  402.     case ATYPE_PERMITHOST:
  403.     case ATYPE_BLOCKHOST:
  404.     case ATYPE_PERMITUDPDSTHOST:
  405.     case ATYPE_BLOCKUDPDSTHOST:
  406.     case ATYPE_PERMITTCPDSTHOST:
  407.     case ATYPE_BLOCKTCPDSTHOST:
  408.     case ATYPE_PERMITDSTHOST:
  409.     case ATYPE_BLOCKDSTHOST:
  410.     case ATYPE_PERMITICMPDSTHOST:
  411.     case ATYPE_BLOCKICMPDSTHOST:
  412.     case ATYPE_PERMITNET:
  413.     case ATYPE_BLOCKNET:
  414.     case ATYPE_PERMITDSTNET:
  415.     case ATYPE_BLOCKDSTNET:
  416.     case ATYPE_PERMITICMPDSTNET:
  417.     case ATYPE_BLOCKICMPDSTNET:
  418.     case ATYPE_PERMITUDPDSTNET:
  419.     case ATYPE_BLOCKUDPDSTNET:
  420.     case ATYPE_PERMITTCPDSTNET:
  421.     case ATYPE_BLOCKTCPDSTNET:
  422.         (void)snprintf(cp, size, " %s", addr2str(&al->addr1));
  423.         break;
  424.  
  425.     case ATYPE_BLOCKHOSTHOST:
  426.     case ATYPE_PERMITHOSTHOST:
  427.         (void)snprintf(cp, size, " %s", addr2str(&al->addr1));
  428.  
  429.         len = strlen(cp);
  430.         size -= len;
  431.         cp += len;
  432.         (void)snprintf(cp, size, " %s", addr2str(&al->addr2));
  433.         break;
  434.  
  435.     case ATYPE_BLOCKNETHOST:
  436.     case ATYPE_PERMITNETHOST:
  437.         (void)snprintf(cp, size, " %s", addr2str(&al->addr1));
  438.  
  439.         len = strlen(cp);
  440.         size -= len;
  441.         cp += len;
  442.         (void)snprintf(cp, size, " %s", addr2str(&al->addr2));
  443.         break;
  444.  
  445.     case ATYPE_PERMITUDPPORT:
  446.     case ATYPE_BLOCKUDPPORT:
  447.     case ATYPE_PERMITTCPPORT:
  448.     case ATYPE_BLOCKTCPPORT:
  449.         (void)snprintf(cp, size, " %s", al->port1);
  450.         break;
  451.  
  452.     case ATYPE_PERMITUDPHOSTPORT:
  453.     case ATYPE_BLOCKUDPHOSTPORT:
  454.     case ATYPE_PERMITTCPHOSTPORT:
  455.     case ATYPE_BLOCKTCPHOSTPORT:
  456.     case ATYPE_PERMITUDPDSTHOSTPORT:
  457.     case ATYPE_BLOCKUDPDSTHOSTPORT:
  458.     case ATYPE_PERMITTCPDSTHOSTPORT:
  459.     case ATYPE_BLOCKTCPDSTHOSTPORT:
  460.     case ATYPE_PERMITUDPHOSTSRCPORT:
  461.     case ATYPE_BLOCKUDPHOSTSRCPORT:
  462.     case ATYPE_PERMITTCPHOSTSRCPORT:
  463.     case ATYPE_BLOCKTCPHOSTSRCPORT:
  464.     case ATYPE_PERMITUDPDSTNETPORT:
  465.     case ATYPE_BLOCKUDPDSTNETPORT:
  466.     case ATYPE_PERMITTCPDSTNETPORT:
  467.     case ATYPE_BLOCKTCPDSTNETPORT:
  468.         (void)snprintf(cp, size, " %s %s",
  469.             addr2str(&al->addr1), al->port1);
  470.         break;
  471.  
  472.     case ATYPE_PERMITUDPNETPORT:
  473.     case ATYPE_BLOCKUDPNETPORT:
  474.     case ATYPE_PERMITTCPNETPORT:
  475.     case ATYPE_BLOCKTCPNETPORT:
  476.         (void)snprintf(cp, size, " %s %s",
  477.             addr2str(&al->addr1), al->port1);
  478.         break;
  479.  
  480.     case ATYPE_PERMITUDPHOSTPAIRDSTPORT:
  481.     case ATYPE_BLOCKUDPHOSTPAIRDSTPORT:
  482.     case ATYPE_PERMITTCPHOSTPAIRDSTPORT:
  483.     case ATYPE_BLOCKTCPHOSTPAIRDSTPORT:
  484.         (void)snprintf(cp, size, " %s", addr2str(&al->addr1));
  485.  
  486.         len = strlen(cp);
  487.         size -= len;
  488.         cp += len;
  489.         (void)snprintf(cp, size, " %s %s",
  490.             addr2str(&al->addr2), al->port1);
  491.         break;
  492.  
  493.     case ATYPE_PERMITUDPNETHOSTPORT:
  494.     case ATYPE_BLOCKUDPNETHOSTPORT:
  495.     case ATYPE_PERMITTCPNETHOSTPORT:
  496.     case ATYPE_BLOCKTCPNETHOSTPORT:
  497.         (void)snprintf(cp, size, " %s", addr2str(&al->addr1));
  498.  
  499.         len = strlen(cp);
  500.         size -= len;
  501.         cp += len;
  502.         (void)snprintf(cp, size, " %s %s",
  503.             addr2str(&al->addr2), al->port1);
  504.         break;
  505.         break;
  506.  
  507.     case ATYPE_UNKNOWN:
  508.         (void)snprintf(buf, sizeof(buf), "# %d unsupported ACL \"%s\"",
  509.             al->seq, al->raw != NULL ? al->raw : "");
  510.         break;
  511.  
  512. #ifdef notdef
  513.     default:
  514.         lg(LOG_ERR, "aclformat: bad type %d", al->type);
  515.         exit(EX_SOFTWARE);
  516. #endif
  517.     }
  518.     return (buf);
  519. }
  520.  
  521. void
  522. aclfree(struct acllist *ap)
  523. {
  524.     int i;
  525.     struct acl *al;
  526.     struct req *rp;
  527.  
  528.     if (ap->name != NULL) {
  529.         free(ap->name);
  530.         ap->name = NULL;
  531.     }
  532.  
  533.     /* Compaction cleanup */
  534.     ap->compactclient = NULL;
  535.     if ((rp = ap->compactreq) != NULL) {
  536.         ap->compactreq = NULL;
  537.         freereq(rp);
  538.     }
  539.  
  540.     if (ap->acl != NULL) {
  541.         for (i = 0, al = ap->acl; i < ap->acllen; ++i, ++al) {
  542.             if (al->port1 != NULL)
  543.                 free(al->port1);
  544.             if (al->port2 != NULL)
  545.                 free(al->port2);
  546.             if (al->raw != NULL)
  547.                 free(al->raw);
  548.         }
  549.         FREEDYNARRAY(ap->acl, &ap->acllen, &ap->aclsize);
  550.     }
  551.     if (ap->addr != NULL)
  552.         FREEDYNARRAY(ap->addr, &ap->addrlen, &ap->addrsize);
  553.     ap->sentlistacl = 0;
  554.  
  555.     ap->limitp = NULL;
  556.  
  557.     stats_free(&ap->stats);
  558. }
  559.  
  560. int
  561. acllistcmp(const void *arg1, const void *arg2)
  562. {
  563.     const struct acllist *ap1, *ap2;
  564.  
  565.     ap1 = (const struct acllist *)arg1;
  566.     ap2 = (const struct acllist *)arg2;
  567.     /* Sort on the first address (good enough to move default to the end) */
  568.     return (addrcmp(ap1->addr, ap2->addr));
  569. }
  570.  
  571. /* Free just the ACL entries from all ACL lists */
  572. void
  573. acllistsfree(struct state  *sp)
  574. {
  575.     int i, j;
  576.     struct acllist *ap;
  577.     struct acl *al;
  578.     struct cf *cf;
  579.  
  580.     cf = sp->cf;
  581.     for (i = 0, ap  = cf->c_acllist; i < cf->c_acllistlen; ++i, ++ap) {
  582.         if (ap->acl == NULL)
  583.             continue;
  584.         for (j = 0, al = ap->acl; j < ap->acllen; ++j, ++al) {
  585.             if (al->port1 != NULL)
  586.                 free(al->port1);
  587.             if (al->port2 != NULL)
  588.                 free(al->port2);
  589.             if (al->raw != NULL)
  590.                 free(al->raw);
  591.         }
  592.         FREEDYNARRAY(ap->acl, &ap->acllen, &ap->aclsize);
  593.         ap->sentlistacl = 0;
  594.     }
  595.     sp->listedallacls = 0;
  596. }
  597.  
  598. /* Returns number of matching host, hosthost or subnet acl entries reported */
  599. int
  600. aclquery(struct acllist *ap, struct addr *addrp, struct iobuf *ip)
  601. {
  602.     int i, cnt;
  603.     struct acl *al;
  604.     char buf[128];
  605.  
  606.     cnt = 0;
  607.     for (i = 0, al = ap->acl; i < ap->acllen; ++i, ++al) {
  608.         switch (al->type) {
  609.  
  610.         case ATYPE_BLOCKHOST:
  611.             if (ADDREQ(addrp, &al->addr1)) {
  612.                 ioappendfmt(ip, "%s",
  613.                     val2str(str2acl, al->type));
  614.                 ++cnt;
  615.             }
  616.             break;
  617.  
  618.         case ATYPE_BLOCKHOSTHOST:
  619.             if (ADDREQ(addrp, &al->addr1)) {
  620.                 strncpy(buf, addr2str(&al->addr1), sizeof(buf));
  621.                 buf[sizeof(buf) - 1] = '\0';
  622.                 ioappendfmt(ip, "%s %s %s",
  623.                     val2str(str2acl, al->type),
  624.                     buf,
  625.                     addr2str(&al->addr2));
  626.                 ++cnt;
  627.             }
  628.             break;
  629.  
  630.         case ATYPE_BLOCKNET:
  631.             /*
  632.              * Look for ATYPE_BLOCKNET vs. ATYPE_BLOCKNET
  633.              * or ATYPE_BLOCKNET vs. ATYPE_BLOCKHOST
  634.              */
  635.             if (ADDREQ(addrp, &al->addr1) ||
  636.                 insubnet(&al->addr1, addrp)) {
  637.                 ioappendfmt(ip, "%s %s",
  638.                     val2str(str2acl, al->type),
  639.                     addr2str(&al->addr1));
  640.                 ++cnt;
  641.             }
  642.             break;
  643.  
  644.         default:
  645.             break;
  646.         }
  647.     }
  648.     return (cnt);
  649. }
  650.  
  651. void
  652. aclsortacls(struct cf *cf)
  653. {
  654.     int i;
  655.     struct acllist *ap;
  656.     struct addr *a;
  657.  
  658.     ap = cf->c_acllist;
  659.     qsort(ap, (size_t)cf->c_acllistlen, sizeof(*ap), acllistcmp);
  660.     for (i = 0, ap = cf->c_acllist; i < cf->c_acllistlen; ++i, ++ap) {
  661.         if (ap->addrlen > 1) {
  662.             a = ap->addr;
  663.             qsort(a, (size_t)ap->addrlen, sizeof(*a), addrcmp);
  664.         }
  665. #ifdef HAVE_CFORCE 
  666.         /* The rest of this isn't needed for the cForce */
  667.         if (cf->c_cforceaddr != NULL)
  668.             continue;
  669. #endif
  670.         if (cf->c_lowportseq >= 0 &&
  671.             (ap->lastportseq < 0 || ap->lastportseq < cf->c_lowportseq))
  672.             ap->lastportseq = cf->c_lowportseq - 1;
  673.         if (cf->c_lowpermithostportseq >= 0 &&
  674.             (ap->lastpermithostportseq < 0 ||
  675.             ap->lastpermithostportseq < cf->c_lowpermithostportseq))
  676.             ap->lastpermithostportseq =
  677.                 cf->c_lowpermithostportseq - 1;
  678.         if (cf->c_incrseq) {
  679.             if (cf->c_lowseq >= 0 &&
  680.                 (ap->lastseq < 0 || ap->lastseq < cf->c_lowseq))
  681.                 ap->lastseq = cf->c_lowseq - 1;
  682.         } else {
  683.             if (cf->c_highseq >= 0 &&
  684.                 (ap->lastseq < 0 || ap->lastseq > cf->c_highseq))
  685.                 ap->lastseq = cf->c_highseq + 1;
  686.         }
  687.     }
  688. }
  689.  
  690. int
  691. aclstraddacl(struct cf *cf, struct acllist *ap, const char *str)
  692. {
  693.     int an;
  694.     const char *p;
  695.     char **av;
  696.     struct acl *al;
  697.     struct acl acl;
  698.  
  699.     /* Eat leading dot; done if there was only one */
  700.     if (*str == '.') {
  701.         ++str;
  702.         if (*str == '\n'|| *str == '\0')
  703.             return (1);
  704.     }
  705.  
  706.     /* syslog any comments we get */
  707.     if (*str == '#') {
  708.         ++str;
  709.         while (*str == ' ')
  710.             ++str;
  711.         lg(LOG_INFO, "listacl: \"%s\"", str);
  712.         return (0);
  713.     }
  714.  
  715.     al = &acl;
  716.     memset(al, 0, sizeof(*al));
  717.     an = makeargv(str, &av);
  718.  
  719.     if (an < 3) {
  720.         lg(LOG_ERR, "aclstraddacl: missing args \"%s\"", str);
  721.         freeargv(av);
  722.         return (0);
  723.     }
  724.  
  725.     al->seq = atoi(av[0]);
  726.     al->count = strtoull(av[1], NULL, 10);
  727.     al->type = str2val(str2acl, av[2]);
  728.     switch (al->type) {
  729.  
  730.     case ATYPE_PERMITANY:
  731.     case ATYPE_BLOCKANY:
  732.         /* No args */
  733.         if (an != 3) {
  734.             lg(LOG_ERR, "aclstraddacl: wrong number of args \"%s\"",
  735.                 str);
  736.             freeargv(av);
  737.             return (0);
  738.         }
  739.         break;
  740.  
  741.     case ATYPE_PERMITHOST:
  742.     case ATYPE_BLOCKHOST:
  743.     case ATYPE_PERMITUDPDSTHOST:
  744.     case ATYPE_BLOCKUDPDSTHOST:
  745.     case ATYPE_PERMITTCPDSTHOST:
  746.     case ATYPE_BLOCKTCPDSTHOST:
  747.     case ATYPE_PERMITDSTHOST:
  748.     case ATYPE_BLOCKDSTHOST:
  749.     case ATYPE_PERMITICMPDSTHOST:
  750.     case ATYPE_BLOCKICMPDSTHOST:
  751.     case ATYPE_PERMITNET:
  752.     case ATYPE_BLOCKNET:
  753.     case ATYPE_PERMITUDPDSTNET:
  754.     case ATYPE_BLOCKUDPDSTNET:
  755.     case ATYPE_PERMITTCPDSTNET:
  756.     case ATYPE_BLOCKTCPDSTNET:
  757.     case ATYPE_PERMITDSTNET:
  758.     case ATYPE_BLOCKDSTNET:
  759.     case ATYPE_PERMITICMPDSTNET:
  760.     case ATYPE_BLOCKICMPDSTNET:
  761.         /* One host or network */
  762.         if (an != 4) {
  763.             lg(LOG_ERR, "aclstraddacl: wrong number of args \"%s\"",
  764.                 str);
  765.             freeargv(av);
  766.             return (0);
  767.         }
  768.         p = extractaddr(av[3], NULL, &al->addr1);
  769.         if (p != NULL) {
  770.             lg(LOG_ERR, "aclstraddacl: bad addr: %s", p);
  771.             freeargv(av);
  772.             return (0);
  773.         }
  774.         break;
  775.  
  776.     case ATYPE_PERMITHOSTHOST:
  777.     case ATYPE_BLOCKHOSTHOST:
  778.     case ATYPE_PERMITNETHOST:
  779.     case ATYPE_BLOCKNETHOST:
  780.         /* Two hosts or networks */
  781.         if (an != 5) {
  782.             lg(LOG_ERR, "aclstraddacl: wrong number of args \"%s\"",
  783.                 str);
  784.             freeargv(av);
  785.             return (0);
  786.         }
  787.         if ((p = extractaddr(av[3], NULL, &al->addr1)) != NULL ||
  788.             (p = extractaddr(av[4], NULL, &al->addr2)) != NULL) {
  789.             lg(LOG_ERR, "aclstraddacl: bad addr: %s", p);
  790.             freeargv(av);
  791.             return (0);
  792.         }
  793.         break;
  794.  
  795.     case ATYPE_PERMITUDPPORT:
  796.     case ATYPE_BLOCKUDPPORT:
  797.     case ATYPE_PERMITTCPPORT:
  798.     case ATYPE_BLOCKTCPPORT:
  799.         /* A port */
  800.         if (an != 4) {
  801.             lg(LOG_ERR, "aclstraddacl: wrong number of args \"%s\"",
  802.                 str);
  803.             freeargv(av);
  804.             return (0);
  805.         }
  806.         al->port1 = av[3];
  807.         break;
  808.  
  809.     case ATYPE_PERMITUDPHOSTPORT:
  810.     case ATYPE_BLOCKUDPHOSTPORT:
  811.     case ATYPE_PERMITTCPHOSTPORT:
  812.     case ATYPE_BLOCKTCPHOSTPORT:
  813.     case ATYPE_PERMITUDPDSTHOSTPORT:
  814.     case ATYPE_BLOCKUDPDSTHOSTPORT:
  815.     case ATYPE_PERMITTCPDSTHOSTPORT:
  816.     case ATYPE_BLOCKTCPDSTHOSTPORT:
  817.     case ATYPE_PERMITUDPHOSTSRCPORT:
  818.     case ATYPE_BLOCKUDPHOSTSRCPORT:
  819.     case ATYPE_PERMITTCPHOSTSRCPORT:
  820.     case ATYPE_BLOCKTCPHOSTSRCPORT:
  821.     case ATYPE_PERMITUDPNETPORT:
  822.     case ATYPE_BLOCKUDPNETPORT:
  823.     case ATYPE_PERMITTCPNETPORT:
  824.     case ATYPE_BLOCKTCPNETPORT:
  825.     case ATYPE_PERMITUDPDSTNETPORT:
  826.     case ATYPE_BLOCKUDPDSTNETPORT:
  827.     case ATYPE_PERMITTCPDSTNETPORT:
  828.     case ATYPE_BLOCKTCPDSTNETPORT:
  829.         /* A host or network and a port */
  830.         if (an != 5) {
  831.             lg(LOG_ERR, "aclstraddacl: wrong number of args \"%s\"",
  832.                 str);
  833.             freeargv(av);
  834.             return (0);
  835.         }
  836.         p = extractaddr(av[3], NULL, &al->addr1);
  837.         if (p != NULL) {
  838.             lg(LOG_ERR, "aclstraddacl: bad addr/net: %s", p);
  839.             freeargv(av);
  840.             return (0);
  841.         }
  842.         al->port1 = av[4];
  843.         break;
  844.  
  845.     case ATYPE_PERMITUDPHOSTPAIRDSTPORT:
  846.     case ATYPE_BLOCKUDPHOSTPAIRDSTPORT:
  847.     case ATYPE_PERMITTCPHOSTPAIRDSTPORT:
  848.     case ATYPE_BLOCKTCPHOSTPAIRDSTPORT:
  849.     case ATYPE_PERMITUDPNETHOSTPORT:
  850.     case ATYPE_BLOCKUDPNETHOSTPORT:
  851.     case ATYPE_PERMITTCPNETHOSTPORT:
  852.     case ATYPE_BLOCKTCPNETHOSTPORT:
  853.         /* Two hosts or networks and a port */
  854.         if (an != 6) {
  855.             lg(LOG_ERR, "aclstraddacl: wrong number of args \"%s\"",
  856.                 str);
  857.             freeargv(av);
  858.             return (0);
  859.         }
  860.         if ((p = extractaddr(av[3], NULL, &al->addr1)) != NULL ||
  861.             (p = extractaddr(av[4], NULL, &al->addr2)) != NULL) {
  862.             lg(LOG_ERR, "aclstraddacl: bad addr: %s", p);
  863.             freeargv(av);
  864.             return (0);
  865.         }
  866.         al->port1 = av[5];
  867.         break;
  868.  
  869.     case ATYPE_UNKNOWN:
  870.         /* Save the raw text so we can print it out later */
  871.         p = strchr(str, '#');
  872.         if (p == NULL)
  873.             p = str;
  874.         else {
  875.             ++p;
  876.             while (isspace((int)*p))
  877.                 ++p;
  878.         }
  879.         al->raw = (char *)p;
  880.         lg(LOG_ERR, "aclstraddacl: unknown \"%s\"", str);
  881.         break;
  882.  
  883. #ifdef notdef
  884.     default:
  885.         lg(LOG_ERR, "aclstraddacl: no such type \"%s\"", str);
  886.         exit(EX_SOFTWARE);
  887. #endif
  888.     }
  889.  
  890.     acladdacl(ap, al);
  891.  
  892.     if ((cf->c_highseq == 0 || al->seq <= cf->c_highseq) &&
  893.         (cf->c_lowseq == 0 || al->seq >= cf->c_lowseq)) {
  894.         if (cf->c_incrseq) {
  895.             if (ap->lastseq < al->seq)
  896.                 ap->lastseq = al->seq;
  897.         } else {
  898.             if (ap->lastseq < 0 || ap->lastseq > al->seq)
  899.                 ap->lastseq = al->seq;
  900.         }
  901.     }
  902.  
  903.     if ((cf->c_highportseq == 0 || al->seq <= cf->c_highportseq) &&
  904.         (cf->c_lowportseq == 0 || al->seq >= cf->c_lowportseq)) {
  905.         if (ap->lastportseq < al->seq)
  906.             ap->lastportseq = al->seq;
  907.     }
  908.  
  909.     if ((cf->c_highpermithostportseq == 0 ||
  910.         al->seq <= cf->c_highpermithostportseq) &&
  911.         (cf->c_lowpermithostportseq == 0 ||
  912.         al->seq >= cf->c_lowpermithostportseq)) {
  913.         if (ap->lastpermithostportseq < al->seq)
  914.             ap->lastpermithostportseq = al->seq;
  915.     }
  916.  
  917.     freeargv(av);
  918.     return (0);
  919. }
  920.  
  921. int
  922. addrcmp(const void *arg1, const void *arg2)
  923. {
  924.     int i, r1, r2;
  925.     const struct addr *a1, *a2;
  926.  
  927.     a1 = (const struct addr *)arg1;
  928.     a2 = (const struct addr *)arg2;
  929.  
  930.     /* IPv4 before IPv6 */
  931.     if (a1->family != a2->family)
  932.         return ((a1->family == AF_INET) ? -1 : 1);
  933.  
  934.     switch (a1->family) {
  935.  
  936.     case AF_INET:
  937.         /* Address */
  938.         if (ntohl(a1->addr4) < ntohl(a2->addr4))
  939.             r1 = -1;
  940.         else if (ntohl(a1->addr4) > ntohl(a2->addr4))
  941.             r1 = 1;
  942.         else
  943.             r1 = 0;
  944.  
  945.         /* Mask */
  946.         if (ntohl(a1->mask4) < ntohl(a2->mask4))
  947.             r2 = 1;
  948.         else if (ntohl(a1->mask4) > ntohl(a2->mask4))
  949.             r2 = -1;
  950.         else
  951.             r2 = 0;
  952.         break;
  953.  
  954.     case AF_INET6:
  955.         /* Address */
  956.         r1 = 0;
  957.         for (i = 0; i < 16; ++i) {
  958.             if (ntohl(a1->addr6[i]) < ntohl(a2->addr6[i])) {
  959.                 r1 = -1;
  960.                 break;
  961.             }
  962.             if (ntohl(a1->addr6[i]) > ntohl(a2->addr6[i])) {
  963.                 r1 = 1;
  964.                 break;
  965.             }
  966.         }
  967.  
  968.         /* Mask */
  969.         r2 = 0;
  970.         for (i = 0; i < 16; ++i) {
  971.             if (a1->mask6[i] < a2->mask6[i]) {
  972.                 r2 = 1;
  973.                 break;
  974.             }
  975.             if (a1->mask6[i] > a2->mask6[i]) {
  976.                 r2 = -1;
  977.                 break;
  978.             }
  979.         }
  980.         break;
  981.  
  982.     default:
  983.         abort();
  984.     }
  985.  
  986.     /* If the masks are the same, sort on addr */
  987.     if (r2 == 0)
  988.         return (r1);
  989.  
  990.     /* Otherwise, sort on mask */
  991.     return (r2);
  992. }
  993.  
  994. void
  995. attrclear(struct state  *sp)
  996. {
  997.     int i;
  998.     struct cf *cf;
  999.     struct attrlist *atp;
  1000.  
  1001.     cf = sp->cf;
  1002.     for (i = 0, atp = cf->c_attrlist; i < cf->c_attrlistlen; ++i, ++atp)
  1003.         atp->a_sentattr = 0;
  1004.     sp->sentattrs = 0;
  1005. }
  1006.  
  1007. const char *
  1008. attrfmt(struct attrlist *atp)
  1009. {
  1010.     static char buf[64];
  1011.  
  1012.     /* XXX only one attribute right now */
  1013.     if (atp->a_attr != ATTR_IPV6)
  1014.         abort();
  1015.     (void)snprintf(buf, sizeof(buf), "attr %s ipv6", atp->a_acl);
  1016.     return (buf);
  1017. }
  1018.