summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--spamd-setup.patch_1939
1 files changed, 0 insertions, 939 deletions
diff --git a/spamd-setup.patch_1 b/spamd-setup.patch_1
deleted file mode 100644
index 08b37cc..0000000
--- a/spamd-setup.patch_1
+++ /dev/null
@@ -1,939 +0,0 @@
-Index: spamd-setup.c
-===================================================================
-RCS file: /cvs/src/libexec/spamd-setup/spamd-setup.c,v
-retrieving revision 1.47
-diff -u -p -u -r1.47 spamd-setup.c
---- spamd-setup.c 12 Dec 2015 20:09:28 -0000 1.47
-+++ spamd-setup.c 10 Jan 2016 19:23:12 -0000
-@@ -30,6 +30,7 @@
- #include <errno.h>
- #include <fcntl.h>
- #include <stdio.h>
-+#include <stdint.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
-@@ -43,12 +44,20 @@
- #define SPAMD_ARG_MAX 256 /* max # of args to an exec */
-
- struct cidr {
-- u_int32_t addr;
-+ sa_family_t ai_family;
-+ union {
-+ u_int32_t addr4;
-+ u_int8_t addr6[16];
-+ } addr;
- u_int8_t bits;
- };
-
- struct bl {
-- u_int32_t addr;
-+ sa_family_t ai_family;
-+ union {
-+ u_int32_t addr4;
-+ u_int8_t addr6[16];
-+ } addr;
- int8_t b;
- int8_t w;
- };
-@@ -58,6 +67,8 @@ struct blacklist {
- char *message;
- struct bl *bl;
- size_t blc, bls;
-+ struct bl *bl6;
-+ size_t blc6, bls6;
- u_int8_t black;
- };
-
-@@ -66,19 +77,30 @@ u_int8_t maxblock(u_int32_t, u_int8_t);
- u_int8_t maxdiff(u_int32_t, u_int32_t);
- struct cidr *range2cidrlist(struct cidr *, u_int *, u_int *, u_int32_t,
- u_int32_t);
-+struct cidr *range2cidrlist6(struct cidr *, u_int *, u_int *, u_int8_t *,
-+ u_int8_t *);
- void cidr2range(struct cidr, u_int32_t *, u_int32_t *);
-+void cidr2range6(struct cidr, u_int8_t *, u_int8_t *);
- char *atop(u_int32_t);
--int parse_netblock(char *, struct bl *, struct bl *, int);
-+int parse_netblock(char *, struct bl *, struct bl *, struct bl*,
-+ struct bl *, int);
- int open_child(char *, char **);
- int fileget(char *);
- int open_file(char *, char *);
- char *fix_quoted_colons(char *);
- void do_message(FILE *, char *);
--struct bl *add_blacklist(struct bl *, size_t *, size_t *, gzFile, int);
-+int add_blacklist(struct bl **, size_t *, size_t *, struct bl **,
-+ size_t *, size_t *, gzFile, int);
-+int cmp_ipv6(const u_int8_t *, const u_int8_t *);
- int cmpbl(const void *, const void *);
--struct cidr *collapse_blacklist(struct bl *, size_t, u_int *);
--int configure_spamd(u_short, char *, char *, struct cidr *, u_int);
--int configure_pf(struct cidr *);
-+int cmpbl6(const void *, const void *);
-+int collapse_blacklist(struct bl *, size_t, struct bl *, size_t,
-+ struct cidr **, u_int *, struct cidr **, u_int *);
-+struct cidr *collapse_blacklist4(struct bl *, size_t, u_int *);
-+struct cidr *collapse_blacklist6(struct bl *, size_t, u_int *);
-+int configure_spamd(u_short, char *, char *, struct cidr *, u_int,
-+ struct cidr *, u_int);
-+int configure_pf(struct cidr *, u_int, struct cidr *, u_int);
- int getlist(char **, char *, struct blacklist *, struct blacklist *);
- __dead void usage(void);
-
-@@ -89,6 +111,74 @@ int greyonly = 1;
- extern char *__progname;
-
- #define MAXIMUM(a,b) (((a)>(b))?(a):(b))
-+#define MINIMUM(a,b) (((a)<(b))?(a):(b))
-+
-+void
-+ipv6_add(u_int8_t *addr, u_int8_t num)
-+{
-+ int i;
-+ u_int8_t tmp;
-+
-+ for (i = 15; i >= 0; i--) {
-+ if (num == 0)
-+ break;
-+
-+ if (num > (UINT8_MAX - addr[i]))
-+ tmp = 1;
-+ else
-+ tmp = 0;
-+
-+ addr[i] += num;
-+
-+ num = tmp;
-+ }
-+}
-+
-+void
-+ipv6_add2(u_int8_t *addr, u_int8_t *src)
-+{
-+ int i, j;
-+ u_int8_t tmp, num;
-+
-+ for (i = 15; i >= 0; i--) {
-+ num = src[i];
-+
-+ for (j = i; j >= 0; j--) {
-+ if (num == 0)
-+ break;
-+
-+ if (num > (UINT8_MAX - addr[j]))
-+ tmp = 1;
-+ else
-+ tmp = 0;
-+
-+ addr[j] += num;
-+
-+ num = tmp;
-+ }
-+ }
-+}
-+
-+void
-+ipv6_sub(u_int8_t *addr, u_int8_t num)
-+{
-+ int i;
-+ u_int8_t tmp;
-+
-+ for (i = 15; i >= 0; i--) {
-+ if (num == 0)
-+ break;
-+
-+ if (num > addr[i])
-+ tmp = 1;
-+ else
-+ tmp = 0;
-+
-+ addr[i] -= num;
-+
-+ num = tmp;
-+ }
-+}
-
- u_int32_t
- imask(u_int8_t b)
-@@ -98,6 +188,24 @@ imask(u_int8_t b)
- return (0xffffffffU << (32 - b));
- }
-
-+void
-+imask6(u_int8_t *m, u_int8_t b)
-+{
-+ int i;
-+ u_int8_t tmp;
-+ memset(m, 0, sizeof(u_int8_t) * 16);
-+
-+ for (i = 0; i < 16; i++) {
-+ if (b == 0)
-+ break;
-+
-+ tmp = MINIMUM(b, 8);
-+ b -= tmp;
-+
-+ m[i] = (0xffU << (8 - tmp));
-+ }
-+}
-+
- u_int8_t
- maxblock(u_int32_t addr, u_int8_t bits)
- {
-@@ -114,6 +222,26 @@ maxblock(u_int32_t addr, u_int8_t bits)
- }
-
- u_int8_t
-+maxblock6(u_int8_t *addr, u_int8_t bits)
-+{
-+ u_int8_t m[16];
-+ int i;
-+
-+ while (bits > 0) {
-+ imask6(m, bits - 1);
-+
-+ for (i = 0; i < 16; i++) {
-+ if ((addr[i] & m[i]) != addr[i]) {
-+ return bits;
-+ }
-+ }
-+
-+ bits--;
-+ }
-+ return (bits);
-+}
-+
-+u_int8_t
- maxdiff(u_int32_t a, u_int32_t b)
- {
- u_int8_t bits = 0;
-@@ -130,6 +258,28 @@ maxdiff(u_int32_t a, u_int32_t b)
- return (bits);
- }
-
-+u_int8_t
-+maxdiff6(u_int8_t *a, u_int8_t *b)
-+{
-+ u_int8_t bits = 0;
-+ u_int8_t m[16], tmp[16];
-+ int i;
-+
-+ memcpy(tmp, b, sizeof(tmp));
-+
-+ ipv6_add(tmp, 1);
-+ while (bits < 128) {
-+ imask6(m, bits);
-+
-+ for (i = 0; i < 15; i++) {
-+ if ((a[i] & m[i]) != (tmp[i] & m[i]))
-+ return (bits);
-+ }
-+ bits++;
-+ }
-+ return (bits);
-+}
-+
- struct cidr *
- range2cidrlist(struct cidr *list, u_int *cli, u_int *cls, u_int32_t start,
- u_int32_t end)
-@@ -150,7 +300,7 @@ range2cidrlist(struct cidr *list, u_int
- list = tmp;
- *cls += 32;
- }
-- list[*cli].addr = start;
-+ list[*cli].addr.addr4 = start;
- list[*cli].bits = maxsize;
- (*cli)++;
- start = start + (1 << (32 - maxsize));
-@@ -158,11 +308,102 @@ range2cidrlist(struct cidr *list, u_int
- return (list);
- }
-
-+struct cidr *
-+range2cidrlist6(struct cidr *list, u_int *cli, u_int *cls, u_int8_t *start,
-+ u_int8_t *end)
-+{
-+ u_int8_t maxsize, diff, btmp;
-+ struct cidr *tmp;
-+ int i;
-+
-+ while (cmp_ipv6(end, start) >= 0) {
-+ /*{ // XXX
-+ char s[INET6_ADDRSTRLEN], e[INET6_ADDRSTRLEN];
-+
-+ inet_ntop(AF_INET6, start, s, sizeof(s));
-+ inet_ntop(AF_INET6, end, e, sizeof(e));
-+
-+ fprintf(stderr, "DEBUG: s=%s, e=%s\n", s, e);
-+ }*/
-+ maxsize = maxblock6(start, 128);
-+ diff = maxdiff6(start, end);
-+
-+ maxsize = MAXIMUM(maxsize, diff);
-+ if (*cls <= *cli + 1) {
-+ tmp = reallocarray(list, *cls + 32,
-+ sizeof(struct cidr));
-+ if (tmp == NULL)
-+ err(1, NULL);
-+ list = tmp;
-+ *cls += 32;
-+ }
-+ memcpy(list[*cli].addr.addr6, start,
-+ sizeof(list[*cli].addr.addr6));
-+ list[*cli].bits = maxsize;
-+ (*cli)++;
-+
-+ maxsize = 128 - maxsize;
-+ u_int8_t mask[16];
-+ memset(mask, 0, sizeof(mask));
-+
-+ for (i = 15; i >= 0; i--) {
-+ btmp = ((maxsize < 8) ? maxsize : 8);
-+ maxsize -= btmp;
-+
-+ mask[i] = ((1 << btmp) - 1);
-+
-+ if (maxsize == 0)
-+ break;
-+ }
-+
-+ ipv6_add(mask, 1);
-+ ipv6_add2(start, mask);
-+
-+ /* { // XXX
-+ char m[INET6_ADDRSTRLEN];
-+
-+ inet_ntop(AF_INET6, mask, m, sizeof(m));
-+
-+ fprintf(stderr, "DEBUG: m=%s\n", m);
-+ }*/
-+ }
-+
-+ return (list);
-+}
-+
- void
- cidr2range(struct cidr cidr, u_int32_t *start, u_int32_t *end)
- {
-- *start = cidr.addr;
-- *end = cidr.addr + (1 << (32 - cidr.bits)) - 1;
-+ *start = cidr.addr.addr4;
-+ *end = cidr.addr.addr4 + (1 << (32 - cidr.bits)) - 1;
-+}
-+
-+void
-+cidr2range6(struct cidr cidr, u_int8_t *start, u_int8_t *end)
-+{
-+ int i;
-+ u_int8_t tmp, bits = 128 - cidr.bits;
-+ u_int8_t mask[16];
-+ memset(mask, 0, sizeof(mask));
-+
-+ for (i = 0; i < 16; i++)
-+ end[i] = start[i] = cidr.addr.addr6[i];
-+ //start[i] = cidr.addr.addr6[i];
-+
-+ for (i = 15; i >= 0; i--) {
-+ if (bits == 0) {
-+ //end[i] = start[i];
-+ break;
-+ } else {
-+ tmp = MINIMUM(bits, 8);
-+ bits -= tmp;
-+
-+ //end[i] = start[i] + ((1 << tmp) - 1); // XXX
-+ mask[i] = ((1 << tmp) - 1);
-+ }
-+ }
-+
-+ ipv6_add2(end, mask);
- }
-
- char *
-@@ -176,11 +417,13 @@ atop(u_int32_t addr)
- }
-
- int
--parse_netblock(char *buf, struct bl *start, struct bl *end, int white)
-+parse_netblock(char *buf, struct bl *start, struct bl *end, struct bl *start6,
-+ struct bl *end6, int white)
- {
-- char astring[16], astring2[16];
-+ char astring[40], astring2[40];
- unsigned maskbits;
- struct cidr c;
-+ int ret = 0;
-
- /* skip leading spaces */
- while (*buf == ' ')
-@@ -189,56 +432,130 @@ parse_netblock(char *buf, struct bl *sta
- if (*buf == '#')
- return (0);
- /* otherwise, look for a netblock of some sort */
-- if (sscanf(buf, "%15[^/]/%u", astring, &maskbits) == 2) {
-- /* looks like a cidr */
-+ if (sscanf(buf, "%15[0123456789.]/%u", astring, &maskbits) == 2) {
-+ /* looks like IPv4 cidr */
- memset(&c.addr, 0, sizeof(c.addr));
-- if (inet_net_pton(AF_INET, astring, &c.addr, sizeof(c.addr))
-- == -1)
-+ if (inet_net_pton(AF_INET, astring, &c.addr.addr4,
-+ sizeof(c.addr.addr4)) == -1)
- return (0);
-- c.addr = ntohl(c.addr);
-+ c.ai_family = AF_INET;
-+ c.addr.addr4 = ntohl(c.addr.addr4);
- if (maskbits > 32)
- return (0);
- c.bits = maskbits;
-- cidr2range(c, &start->addr, &end->addr);
-- end->addr += 1;
-+ cidr2range(c, &start->addr.addr4, &end->addr.addr4);
-+ start->ai_family = end->ai_family = AF_INET;
-+ end->addr.addr4 += 1;
-+
-+ ret = AF_INET;
-+ } else if (sscanf(buf, "%39[0123456789ABCDEFabcdef:]/%u",
-+ astring, &maskbits) == 2) {
-+ /* looks like IPv6 cidr */
-+ memset(&c.addr, 0, sizeof(c.addr));
-+ if (inet_net_pton(AF_INET6, astring, &c.addr.addr6,
-+ sizeof(c.addr.addr6)) == -1)
-+ return (0);
-+ c.ai_family = AF_INET6;
-+ if (maskbits > 128)
-+ return (0);
-+ c.bits = maskbits;
-+ cidr2range6(c, start6->addr.addr6, end6->addr.addr6);
-+ start6->ai_family = end6->ai_family = AF_INET6;
-+ ipv6_add(end6->addr.addr6, 1);
-+
-+ ret = AF_INET6;
- } else if (sscanf(buf, "%15[0123456789.]%*[ -]%15[0123456789.]",
- astring, astring2) == 2) {
-- /* looks like start - end */
-+ /* looks like IPv4 start - end */
- memset(&start->addr, 0, sizeof(start->addr));
- memset(&end->addr, 0, sizeof(end->addr));
-- if (inet_net_pton(AF_INET, astring, &start->addr,
-- sizeof(start->addr)) == -1)
-+ if (inet_net_pton(AF_INET, astring, &start->addr.addr4,
-+ sizeof(start->addr.addr4)) == -1)
- return (0);
-- start->addr = ntohl(start->addr);
-- if (inet_net_pton(AF_INET, astring2, &end->addr,
-- sizeof(end->addr)) == -1)
-+ start->ai_family = AF_INET;
-+ start->addr.addr4 = ntohl(start->addr.addr4);
-+ if (inet_net_pton(AF_INET, astring2, &end->addr.addr4,
-+ sizeof(end->addr.addr4)) == -1)
- return (0);
-- end->addr = ntohl(end->addr) + 1;
-+ end->ai_family = AF_INET;
-+ end->addr.addr4 = ntohl(end->addr.addr4) + 1;
- if (start > end)
- return (0);
-+
-+ ret = AF_INET;
-+ } else if (sscanf(buf, "%39[0123456789ABCDEFabcdef:]%*[ -]"
-+ "%39[0123456789ABCDEFabcdef:]", astring, astring2) == 2) {
-+ /* loks like IPv6 start - end */
-+ memset(&start6->addr, 0, sizeof(start6->addr));
-+ memset(&end6->addr, 0, sizeof(end6->addr));
-+ if (inet_net_pton(AF_INET6, astring, &start6->addr.addr6,
-+ sizeof(start6->addr.addr6)) == -1)
-+ return (0);
-+ start6->ai_family = AF_INET6;
-+ if (inet_net_pton(AF_INET6, astring2, &end6->addr.addr6,
-+ sizeof(end6->addr.addr6)) == -1)
-+ return (0);
-+ end6->ai_family = AF_INET6;
-+ ipv6_add(end6->addr.addr6, 1);
-+ if (start6 > end6)
-+ return (0);
-+
-+ ret = AF_INET6;
- } else if (sscanf(buf, "%15[0123456789.]", astring) == 1) {
-- /* just a single address */
-+ /* just a single IPv4 address */
- memset(&start->addr, 0, sizeof(start->addr));
-- if (inet_net_pton(AF_INET, astring, &start->addr,
-- sizeof(start->addr)) == -1)
-+ if (inet_net_pton(AF_INET, astring, &start->addr.addr4,
-+ sizeof(start->addr.addr4)) == -1)
- return (0);
-- start->addr = ntohl(start->addr);
-- end->addr = start->addr + 1;
-+ start->ai_family = AF_INET;
-+ end->ai_family = AF_INET;
-+ start->addr.addr4 = ntohl(start->addr.addr4);
-+ end->addr.addr4 = start->addr.addr4 + 1;
-+
-+ ret = AF_INET;
-+ } else if (sscanf(buf, "%39[0123456789ABCDEFabcdef:]", astring) == 1) {
-+ /* just a single IPv6 address */
-+ memset(&start6->addr, 0, sizeof(start6->addr));
-+ if (inet_net_pton(AF_INET6, astring, &start6->addr.addr6,
-+ sizeof(start6->addr.addr6)) == -1)
-+ return (0);
-+ start6->ai_family = AF_INET6;
-+ end6->ai_family = AF_INET6;
-+ memcpy(&end6->addr.addr6, &start6->addr.addr6,
-+ sizeof(start6->addr.addr6));
-+
-+ ipv6_add(end6->addr.addr6, 1);
-+
-+ ret = AF_INET6;
- } else
- return (0);
-
- if (white) {
-- start->b = 0;
-- start->w = 1;
-- end->b = 0;
-- end->w = -1;
-+ if (ret == AF_INET) {
-+ start->b = 0;
-+ start->w = 1;
-+ end->b = 0;
-+ end->w = -1;
-+ } else {
-+ start6->b = 0;
-+ start6->w = 1;
-+ end->b = 0;
-+ end->w = -1;
-+ }
- } else {
-- start->b = 1;
-- start->w = 0;
-- end->b = -1;
-- end->w = 0;
-+ if (ret == AF_INET) {
-+ start->b = 1;
-+ start->w = 0;
-+ end->b = -1;
-+ end->w = 0;
-+ } else {
-+ start6->b = 1;
-+ start6->w = 0;
-+ end6->b = -1;
-+ end6->w = 0;
-+ }
- }
-- return (1);
-+ return (ret);
- }
-
- int
-@@ -445,8 +762,9 @@ do_message(FILE *sdc, char *msg)
- }
-
- /* retrieve a list from fd. add to blacklist bl */
--struct bl *
--add_blacklist(struct bl *bl, size_t *blc, size_t *bls, gzFile gzf, int white)
-+int
-+add_blacklist(struct bl **bl, size_t *blc, size_t *bls, struct bl **bl6,
-+ size_t *blc6, size_t *bls6, gzFile gzf, int white)
- {
- int i, n, start, bu = 0, bs = 0, serrno = 0;
- char *buf = NULL, *tmp;
-@@ -481,30 +799,55 @@ add_blacklist(struct bl *bl, size_t *blc
- /* we assume that there is an IP for every 14 bytes */
- if (*blc + bu / 7 >= *bls) {
- *bls += bu / 7;
-- blt = reallocarray(bl, *bls, sizeof(struct bl));
-+ blt = reallocarray(*bl, *bls, sizeof(struct bl));
- if (blt == NULL) {
- *bls -= bu / 7;
- serrno = errno;
- goto bldone;
- }
-- bl = blt;
-+ *bl = blt;
-+ }
-+ if (*blc6 + bu / 7 >= *bls6) {
-+ *bls6 += bu / 7;
-+ blt = reallocarray(*bl6, *bls6, sizeof(struct bl));
-+ if (blt == NULL) {
-+ *bls6 -= bu / 7;
-+ serrno = errno;
-+ goto bldone;
-+ }
-+ *bl6 = blt;
- }
- for (i = 0; i <= bu; i++) {
- if (*blc + 1 >= *bls) {
- *bls += 1024;
-- blt = reallocarray(bl, *bls, sizeof(struct bl));
-+ blt = reallocarray(*bl, *bls, sizeof(struct bl));
- if (blt == NULL) {
- *bls -= 1024;
- serrno = errno;
- goto bldone;
- }
-- bl = blt;
-+ *bl = blt;
-+ }
-+ if (*blc6 + 1 >= *bls6) {
-+ *bls6 += 1024;
-+ blt = reallocarray(*bl6, *bls6, sizeof(struct bl));
-+ if (blt == NULL) {
-+ *bls6 -= 1024;
-+ serrno = errno;
-+ goto bldone;
-+ }
-+ *bl6 = blt;
- }
- if (i == bu || buf[i] == '\n') {
- buf[i] = '\0';
-- if (parse_netblock(buf + start,
-- bl + *blc, bl + *blc + 1, white))
-+ n = parse_netblock(buf + start,
-+ *bl + *blc, *bl + *blc + 1,
-+ *bl6 + *blc6, *bl6 + *blc6 + 1, white);
-+
-+ if (n == AF_INET)
- *blc += 2;
-+ else if (n == AF_INET6)
-+ *blc6 += 2;
- start = i + 1;
- }
- }
-@@ -512,29 +855,78 @@ add_blacklist(struct bl *bl, size_t *blc
- errno = EIO;
- bldone:
- free(buf);
-- if (serrno)
-+ if (serrno) {
- errno = serrno;
-- return (bl);
-+ return (0);
-+ }
-+ return (1);;
-+}
-+
-+int
-+cmp_ipv6(const u_int8_t *a, const u_int8_t *b)
-+{
-+ int i;
-+ for (i = 0; i < 16; i++) {
-+ if (a[i] > b[i])
-+ return (1);
-+ if (a[i] < b[i])
-+ return (-1);
-+ }
-+ return (0);
- }
-
- int
- cmpbl(const void *a, const void *b)
- {
-- if (((struct bl *)a)->addr > ((struct bl *) b)->addr)
-+ if (((struct bl *)a)->addr.addr4 > ((struct bl *) b)->addr.addr4)
- return (1);
-- if (((struct bl *)a)->addr < ((struct bl *) b)->addr)
-+ if (((struct bl *)a)->addr.addr4 < ((struct bl *) b)->addr.addr4)
- return (-1);
- return (0);
- }
-
-+int
-+cmpbl6(const void *a, const void *b)
-+{
-+ u_int8_t *addr1, *addr2;
-+
-+ addr1 = ((struct bl *)a)->addr.addr6;
-+ addr2 = ((struct bl *)b)->addr.addr6;
-+
-+ return cmp_ipv6(addr1, addr2);
-+}
-+
- /*
- * collapse_blacklist takes blacklist/whitelist entries sorts, removes
- * overlaps and whitelist portions, and returns netblocks to blacklist
- * as lists of nonoverlapping cidr blocks suitable for feeding in
- * printable form to pfctl or spamd.
- */
-+
-+int
-+collapse_blacklist(struct bl *bl, size_t blc, struct bl *bl6, size_t blc6,
-+ struct cidr **cidr, u_int *clc, struct cidr **cidr6, u_int *clc6)
-+{
-+ if (blc == 0 && blc6 == 0)
-+ return (0);
-+
-+ if (blc > 0) {
-+ *cidr = collapse_blacklist4(bl, blc, clc);
-+ if (*cidr == NULL)
-+ return (0);
-+ }
-+
-+ if (blc6 > 0) {
-+ *cidr6 = collapse_blacklist6(bl6, blc6, clc6);
-+ if (*cidr6 == NULL)
-+ return (0);
-+ }
-+
-+ return (1);
-+}
-+
- struct cidr *
--collapse_blacklist(struct bl *bl, size_t blc, u_int *clc)
-+collapse_blacklist4(struct bl *bl, size_t blc, u_int *clc)
- {
- int bs = 0, ws = 0, state=0;
- u_int cli, cls, i;
-@@ -558,13 +950,13 @@ collapse_blacklist(struct bl *bl, size_t
- qsort(bl, blc, sizeof(struct bl), cmpbl);
- for (i = 0; i < blc;) {
- laststate = state;
-- addr = bl[i].addr;
-+ addr = bl[i].addr.addr4;
-
- do {
- bs += bl[i].b;
- ws += bl[i].w;
- i++;
-- } while (bl[i].addr == addr);
-+ } while (bl[i].addr.addr4 == addr);
- if (state == 1 && bs == 0)
- state = 0;
- else if (state == 0 && bs > 0)
-@@ -581,18 +973,74 @@ collapse_blacklist(struct bl *bl, size_t
- }
- laststate = state;
- }
-- cl[cli].addr = 0;
-+ cl[cli].addr.addr4 = 0;
- *clc = cli;
- return (cl);
- }
-
-+struct cidr *
-+collapse_blacklist6(struct bl *bl6, size_t blc6, u_int *clc6)
-+{
-+ int bs = 0, ws = 0, state = 0;
-+ u_int cli, cls, i;
-+ struct cidr *cl;
-+ int laststate;
-+ u_int8_t bstart[16];
-+ u_int8_t addr[16];
-+
-+ memset(bstart, 0, sizeof(bstart));
-+
-+ if (blc6 == 0)
-+ return (NULL);
-+
-+ cli = 0;
-+ cls = (blc6 / 2) + (blc6 / 20) + 1;
-+ cl = reallocarray(NULL, cls, sizeof(struct cidr));
-+ if (cl == NULL)
-+ return (NULL);
-+ qsort(bl6, blc6, sizeof(struct bl), cmpbl6);
-+
-+ for (i = 0; i < blc6;) {
-+ laststate = state;
-+ memcpy(addr, bl6[i].addr.addr6, sizeof(addr));
-+
-+ do {
-+ bs += bl6[i].b;
-+ ws += bl6[i].w;
-+ i++;
-+ } while (cmp_ipv6(bl6[i].addr.addr6, addr) == 0);
-+ if (state == 1 && bs == 0)
-+ state = 0;
-+ else if (state == 0 && bs > 0)
-+ state = 1;
-+ if (ws > 0)
-+ state = 0;
-+ if (laststate == 0 && state == 1) {
-+ /* start blacklist */
-+ memcpy(bstart, addr, sizeof(addr));
-+ }
-+ if (laststate == 1 && state == 0) {
-+ /* end blacklist */
-+ ipv6_sub(addr, 1);
-+ cl = range2cidrlist6(cl, &cli, &cls, bstart, addr);
-+ }
-+ laststate = state;
-+ }
-+
-+ memset(&cl[cli].addr.addr6, 0, sizeof(cl[cli].addr.addr6));
-+ *clc6 = cli;
-+
-+ return (cl);
-+}
-+
- int
- configure_spamd(u_short dport, char *name, char *message,
-- struct cidr *blacklists, u_int count)
-+ struct cidr *blacklists, u_int count, struct cidr *blacklists6, u_int count6)
- {
-- int lport = IPPORT_RESERVED - 1, s;
-+ int lport = IPPORT_RESERVED - 1, s, i;
- struct sockaddr_in sin;
- FILE* sdc;
-+ char buf[INET6_ADDRSTRLEN];
-
- s = rresvport(&lport);
- if (s == -1)
-@@ -612,10 +1060,14 @@ configure_spamd(u_short dport, char *nam
- fputs(name, sdc);
- do_message(sdc, message);
- fprintf(sdc, ";inet;%u", count);
-- while (blacklists->addr != 0) {
-- fprintf(sdc, ";%s/%u", atop(blacklists->addr),
-- blacklists->bits);
-- blacklists++;
-+ for (i = 0; i < count; i++) {
-+ fprintf(sdc, ";%s/%u", atop(blacklists[i].addr.addr4),
-+ blacklists[i].bits);
-+ }
-+ fprintf(sdc, ";inet6;%u", count6);
-+ for (i = 0; i < count6; i++) {
-+ inet_ntop(AF_INET6, blacklists6[i].addr.addr6, buf, sizeof(buf));
-+ fprintf(sdc, ";%s/%u", buf, blacklists6[i].bits);
- }
- fputc('\n', sdc);
- fclose(sdc);
-@@ -625,12 +1077,14 @@ configure_spamd(u_short dport, char *nam
-
-
- int
--configure_pf(struct cidr *blacklists)
-+configure_pf(struct cidr *blacklists, u_int count, struct cidr *blacklists6,
-+ u_int count6)
- {
- char *argv[9]= {"pfctl", "-q", "-t", "spamd", "-T", "replace",
- "-f" "-", NULL};
-+ char buf[INET6_ADDRSTRLEN];
- static FILE *pf = NULL;
-- int pdes[2];
-+ int pdes[2], i;
-
- if (pf == NULL) {
- if (pipe(pdes) != 0)
-@@ -659,10 +1113,13 @@ configure_pf(struct cidr *blacklists)
- return (-1);
- }
- }
-- while (blacklists->addr != 0) {
-- fprintf(pf, "%s/%u\n", atop(blacklists->addr),
-- blacklists->bits);
-- blacklists++;
-+ for (i = 0; i < count; i++) {
-+ fprintf(pf, "%s/%u\n", atop(blacklists[i].addr.addr4),
-+ blacklists[i].bits);
-+ }
-+ for (i = 0; i < count; i++) {
-+ inet_ntop(AF_INET6, blacklists6[i].addr.addr6, buf, sizeof(buf));
-+ fprintf(pf, "%s/%u\n", buf, blacklists6[i].bits);
- }
- return (0);
- }
-@@ -672,9 +1129,10 @@ getlist(char ** db_array, char *name, st
- struct blacklist *blistnew)
- {
- char *buf, *method, *file, *message;
-- int fd, black = 0, serror;
-- size_t blc, bls;
-+ int fd, black = 0, serror, ret;
-+ size_t blc, bls, blc6, bls6;
- struct bl *bl = NULL;
-+ struct bl *bl6 = NULL;
- gzFile gzf;
-
- if (cgetent(&buf, db_array, name) != 0)
-@@ -686,12 +1144,18 @@ getlist(char ** db_array, char *name, st
- blc = blistnew->blc;
- bls = blistnew->bls;
- bl = blistnew->bl;
-+ blc6 = blistnew->blc6;
-+ bls6 = blistnew->bls6;
-+ bl6 = blistnew->bl6;
- } else if (cgetcap(buf, "white", ':') != NULL) {
- /* apply to most recent blacklist */
- black = 0;
- blc = blist->blc;
- bls = blist->bls;
- bl = blist->bl;
-+ blc6 = blist->blc6;
-+ bls6 = blist->bls6;
-+ bl6 = blist->bl6;
- } else
- errx(1, "Must have \"black\" or \"white\" in %s", name);
-
-@@ -730,10 +1194,10 @@ getlist(char ** db_array, char *name, st
- errx(1, "gzdopen");
- }
- free(buf);
-- bl = add_blacklist(bl, &blc, &bls, gzf, !black);
-+ ret = add_blacklist(&bl, &blc, &bls, &bl6, &blc6, &bls6, gzf, !black);
- serror = errno;
- gzclose(gzf);
-- if (bl == NULL) {
-+ if (!ret) {
- errno = serror;
- warn("Could not add %slist %s", black ? "black" : "white",
- name);
-@@ -742,13 +1206,16 @@ getlist(char ** db_array, char *name, st
- if (black) {
- if (debug)
- fprintf(stderr, "blacklist %s %zu entries\n",
-- name, blc / 2);
-+ name, ((blc / 2) + (blc6 / 2)));
- blistnew->message = message;
- blistnew->name = name;
- blistnew->black = black;
- blistnew->bl = bl;
- blistnew->blc = blc;
- blistnew->bls = bls;
-+ blistnew->bl6 = bl6;
-+ blistnew->blc6 = blc6;
-+ blistnew->bls6 = bls6;
- } else {
- /* whitelist applied to last active blacklist */
- if (debug)
-@@ -757,6 +1224,9 @@ getlist(char ** db_array, char *name, st
- blist->bl = bl;
- blist->blc = blc;
- blist->bls = bls;
-+ blist->bl6 = bl6;
-+ blist->blc6 = blc6;
-+ blist->bls6 = bls6;
- }
- return (black);
- }
-@@ -764,22 +1234,24 @@ getlist(char ** db_array, char *name, st
- void
- send_blacklist(struct blacklist *blist, in_port_t port)
- {
-- struct cidr *cidrs;
-- u_int clc;
-+ struct cidr *cidrs = NULL, *cidrs6 = NULL;
-+ u_int clc = 0, clc6 = 0;
-
-- if (blist->blc > 0) {
-- cidrs = collapse_blacklist(blist->bl, blist->blc, &clc);
-- if (cidrs == NULL)
-+ if (blist->blc > 0 || blist->blc6 > 0) {
-+ if (!collapse_blacklist(blist->bl, blist->blc, blist->bl6,
-+ blist->blc6, &cidrs, &clc, &cidrs6, &clc6))
- err(1, NULL);
- if (!dryrun) {
- if (configure_spamd(port, blist->name,
-- blist->message, cidrs, clc) == -1)
-+ blist->message, cidrs, clc, cidrs6, clc6) == -1)
- err(1, "Can't connect to spamd on port %d",
- port);
-- if (!greyonly && configure_pf(cidrs) == -1)
-+ if (!greyonly && configure_pf(cidrs, clc, cidrs6, clc6)
-+ == -1)
- err(1, "pfctl failed");
- }
- free(cidrs);
-+ free(cidrs6);
- free(blist->bl);
- }
- }