spamd stores the IP addr/mask in a union that can hold either ipv4
or ipv6. This simplifies the data structures but means that ipv4
addrs/masks take up 4x as much space as they need to. This can
be an issue with very large blacklists, like we use on the
mailing list server. It also means spamd compares addrs regardless
of the address family.
Adding insult to injury, neither spamd-setup nor the greytrapper
in spamd support anything other than ipv4. Rather than just
rip out the unused ipv6 support, I've changed the spamd config
protocol from:
tag;message;a/m;a/m;a/m...\n
to:
tag;message;af;count;a/m;a/m;a/m...\n
where addr/mask lists are specified on a per-address family basis.
This lets us store addr/mask pairs in a per-address family list.
This results in a spamd process that uses almost 1/4 of the old
one and we never try to match IP addresses of the wrong family.
Before:
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
_spamd 9520 0.0 13.1 1088112 1085244 ?? S Mon01PM 31:50.51 spamd:
[priv] (greylist) (spamd)
After:
_spamd 9781 0.0 2.8 236880 232224 ?? S Thu08PM 4:07.29 spamd:
[priv] (greylist) (spamd)
Comments?
- todd
Index: libexec/spamd/grey.c
=================================================================== RCS
file: /cvs/src/libexec/spamd/grey.c,v retrieving revision 1.57 diff
-u -r1.57 grey.c --- libexec/spamd/grey.c 23 Nov 2014 21:19:47
-0000 1.57 +++ libexec/spamd/grey.c 9 Jan 2015 13:38:08
-0000 @@ -58,7 +58,7 @@
int server_lookup6(struct sockaddr_in6 *, struct sockaddr_in6 *,
struct sockaddr_in6 *);
-void configure_spamd(char **, size_t, FILE *);
+void configure_spamd(char **, u_int, FILE *);
int server_lookup(struct sockaddr *, struct sockaddr *,
struct sockaddr *);
int configure_pf(char **, int);
@@ -76,8 +76,8 @@
void greyscanner(void);
-size_t whitecount, whitealloc;
-size_t trapcount, trapalloc;
+u_int whitecount, whitealloc;
+u_int trapcount, trapalloc;
char **whitelist;
char **traplist;
@@ -137,17 +137,18 @@
* host hits.
*/
void
-configure_spamd(char **addrs, size_t count, FILE *sdc)
+configure_spamd(char **addrs, u_int count, FILE *sdc)
{
- size_t i;
+ u_int i;
+ /* XXX - doesn't support IPV6 yet */
fprintf(sdc, "%s;", traplist_name);
if (count != 0) {
- fprintf(sdc, "%s;", traplist_msg);
+ fprintf(sdc, "%s;inet;%u", traplist_msg, count);
for (i = 0; i < count; i++)
- fprintf(sdc, "%s/32;", addrs[i]);
+ fprintf(sdc, ";%s/32", addrs[i]);
}
- fprintf(sdc, "\n");
+ fputc('\n', sdc);
if (fflush(sdc) == EOF)
syslog_r(LOG_DEBUG, &sdata, "configure_spamd: fflush failed
(%m)");
}
Index: libexec/spamd/sdl.c
===================================================================
RCS file: /cvs/src/libexec/spamd/sdl.c,v
retrieving revision 1.20
diff -u -r1.20 sdl.c
--- libexec/spamd/sdl.c 8 Jan 2015 22:10:08 -0000 1.20
+++ libexec/spamd/sdl.c 9 Jan 2015 13:38:08 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: sdl.c,v 1.20 2015/01/08 22:10:08 millert Exp $ */
+/* $OpenBSD: sdl.c,v 1.19 2014/10/11 03:25:16 doug Exp $ */
/*
* Copyright (c) 2003-2007 Bob Beck. All rights reserved.
@@ -40,20 +40,18 @@
static void sdl_free(struct sdlist *);
static void sdl_clear(struct sdlist *);
-int match_addr(struct sdaddr *a, struct sdaddr *m, struct sdaddr *b,
- sa_family_t af);
extern int debug;
struct sdlist *blacklists = NULL;
int blc = 0, blu = 0;
int
-sdl_add(char *sdname, char *sdstring, char ** addrs, int addrc)
+sdl_add(char *sdname, char *sdstring, char **v4, u_int nv4, char **v6, u_int
nv6)
{
int i, idx = -1;
char astring[40];
+ char *addr = NULL;
unsigned int maskbits;
- struct sdaddr *m, *n;
/*
* if a blacklist of same tag name is already there, replace it,
@@ -67,12 +65,12 @@
}
if (idx != -1) {
if (debug > 0)
- printf("replacing list %s; %d new entries\n",
- blacklists[idx].tag, addrc);
+ printf("replacing list %s; %u new entries\n",
+ blacklists[idx].tag, nv4 + nv6);
sdl_free(&blacklists[idx]);
} else {
if (debug > 0)
- printf("adding list %s; %d entries\n", sdname, addrc);
+ printf("adding list %s; %u entries\n", sdname, nv4 +
nv6);
if (blu == blc) {
struct sdlist *tmp;
@@ -92,62 +90,95 @@
if ((blacklists[idx].string = strdup(sdstring)) == NULL)
goto misc_error;
- blacklists[idx].naddrs = addrc;
-
/*
- * Cycle through addrs, converting. We assume they are correctly
- * formatted v4 and v6 addrs, if they don't all convert correctly, the
- * add fails. Each address should be address/maskbits
+ * Cycle through addrs by family, converting. We assume they are
+ * correctly formatted v4 and v6 addrs, if they don't all convert
+ * correctly, the add fails. Each address should be address/maskbits.
*/
- blacklists[idx].addrs = calloc(addrc, sizeof(struct sdentry));
- if (blacklists[idx].addrs == NULL)
- goto misc_error;
-
- for (i = 0; i < addrc; i++) {
- int j, k, af;
-
- n = &blacklists[idx].addrs[i].sda;
- m = &blacklists[idx].addrs[i].sdm;
+ if (nv4 != 0) {
+ blacklists[idx].v4.naddrs = nv4;
+ blacklists[idx].v4.addrs = reallocarray(NULL, nv4,
+ sizeof(struct sdentry_v4));
+ if (blacklists[idx].v4.addrs == NULL)
+ goto misc_error;
+ for (i = 0; i < nv4; i++) {
+ struct in_addr *m, *n;
+ int j;
+
+ n = &blacklists[idx].v4.addrs[i].sda;
+ m = &blacklists[idx].v4.addrs[i].sdm;
+
+ addr = v4[i];
+ j = sscanf(addr, "%15[^/]/%u", astring, &maskbits);
+ if (j != 2)
+ goto parse_error;
+ /*
+ * sanity check! we don't allow a 0 mask -
+ * don't blacklist the entire net.
+ */
+ if (maskbits == 0 || maskbits > 32)
+ goto parse_error;
+ j = inet_pton(AF_INET, astring, n);
+ if (j != 1)
+ goto parse_error;
+ if (debug > 0)
+ printf("added %s/%u\n", astring, maskbits);
+
+ /* set mask. */
+ m->s_addr = 0xffffffffU << (32 - maskbits);
+ m->s_addr = htonl(m->s_addr);
- j = sscanf(addrs[i], "%39[^/]/%u", astring, &maskbits);
- if (j != 2)
- goto parse_error;
- if (maskbits > 128)
- goto parse_error;
- /*
- * sanity check! we don't allow a 0 mask -
- * don't blacklist the entire net.
- */
- if (maskbits == 0)
- goto parse_error;
- if (strchr(astring, ':') != NULL)
- af = AF_INET6;
- else
- af = AF_INET;
- if (af == AF_INET && maskbits > 32)
- goto parse_error;
- j = inet_pton(af, astring, n);
- if (j != 1)
- goto parse_error;
- if (debug > 0)
- printf("added %s/%u\n", astring, maskbits);
-
- /* set mask, borrowed from pf */
- k = 0;
- for (j = 0; j < 4; j++)
- m->addr32[j] = 0;
- while (maskbits >= 32) {
- m->addr32[k++] = 0xffffffff;
- maskbits -= 32;
+ /* mask off address bits that won't ever be used */
+ n->s_addr = n->s_addr & m->s_addr;
+ }
+ }
+ if (nv6 != 0) {
+ blacklists[idx].v6.naddrs = nv6;
+ blacklists[idx].v6.addrs = reallocarray(NULL, nv6,
+ sizeof(struct sdentry_v6));
+ if (blacklists[idx].v6.addrs == NULL)
+ goto misc_error;
+
+ for (i = 0; i < nv6; i++) {
+ int j, k;
+ struct sdaddr_v6 *m, *n;
+
+ n = &blacklists[idx].v6.addrs[i].sda;
+ m = &blacklists[idx].v6.addrs[i].sdm;
+
+ addr = v6[i];
+ j = sscanf(addr, "%39[^/]/%u", astring, &maskbits);
+ if (j != 2)
+ goto parse_error;
+ /*
+ * sanity check! we don't allow a 0 mask -
+ * don't blacklist the entire net.
+ */
+ if (maskbits == 0 || maskbits > 128)
+ goto parse_error;
+ j = inet_pton(AF_INET6, astring, n);
+ if (j != 1)
+ goto parse_error;
+ if (debug > 0)
+ printf("added %s/%u\n", astring, maskbits);
+
+ /* set mask, borrowed from pf */
+ k = 0;
+ for (j = 0; j < 4; j++)
+ m->addr32[j] = 0;
+ while (maskbits >= 32) {
+ m->addr32[k++] = 0xffffffff;
+ maskbits -= 32;
+ }
+ for (j = 31; j > 31 - maskbits; --j)
+ m->addr32[k] |= (1 << j);
+ if (maskbits)
+ m->addr32[k] = htonl(m->addr32[k]);
+
+ /* mask off address bits that won't ever be used */
+ for (j = 0; j < 4; j++)
+ n->addr32[j] = n->addr32[j] & m->addr32[j];
}
- for (j = 31; j > 31 - maskbits; --j)
- m->addr32[k] |= (1 << j);
- if (maskbits)
- m->addr32[k] = htonl(m->addr32[k]);
-
- /* mask off address bits that won't ever be used */
- for (j = 0; j < 4; j++)
- n->addr32[j] = n->addr32[j] & m->addr32[j];
}
if (idx == blu) {
blu++;
@@ -156,7 +187,7 @@
return (0);
parse_error:
if (debug > 0)
- printf("sdl_add: parse error, \"%s\"\n", addrs[i]);
+ printf("sdl_add: parse error, \"%s\"\n", addr);
misc_error:
sdl_free(&blacklists[idx]);
if (idx != blu) {
@@ -181,11 +212,15 @@
if (idx != -1) {
if (debug > 0)
printf("clearing list %s\n", sdname);
+ /* Must preserve tag. */
free(blacklists[idx].string);
- free(blacklists[idx].addrs);
+ free(blacklists[idx].v4.addrs);
+ free(blacklists[idx].v6.addrs);
blacklists[idx].string = NULL;
- blacklists[idx].addrs = NULL;
- blacklists[idx].naddrs = 0;
+ blacklists[idx].v4.addrs = NULL;
+ blacklists[idx].v6.addrs = NULL;
+ blacklists[idx].v4.naddrs = 0;
+ blacklists[idx].v6.naddrs = 0;
}
}
@@ -194,74 +229,86 @@
* otherwise return 0. It is assumed that address a has been
* pre-masked out, we only need to mask b.
*/
-int
-match_addr(struct sdaddr *a, struct sdaddr *m, struct sdaddr *b,
- sa_family_t af)
+static int
+match_addr_v4(struct in_addr *a, struct in_addr *m, struct in_addr *b)
{
- int match = 0;
-
- switch (af) {
- case AF_INET:
- if ((a->addr32[0]) ==
- (b->addr32[0] & m->addr32[0]))
- match++;
- break;
- case AF_INET6:
- if (((a->addr32[0]) ==
- (b->addr32[0] & m->addr32[0])) &&
- ((a->addr32[1]) ==
- (b->addr32[1] & m->addr32[1])) &&
- ((a->addr32[2]) ==
- (b->addr32[2] & m->addr32[2])) &&
- ((a->addr32[3]) ==
- (b->addr32[3] & m->addr32[3])))
- match++;
- break;
- }
- return (match);
+ if (a->s_addr == (b->s_addr & m->s_addr))
+ return (1);
+ return (0);
}
-
/*
- * Given an address and address family
- * return list of pointers to matching nodes. or NULL if none.
+ * Return 1 if the addresses a (with mask m) matches address b
+ * otherwise return 0. It is assumed that address a has been
+ * pre-masked out, we only need to mask b.
*/
-struct sdlist **
-sdl_lookup(struct sdlist *head, int af, void * src)
+static int
+match_addr_v6(struct sdaddr_v6 *a, struct sdaddr_v6 *m, struct sdaddr_v6 *b)
{
+ if (((a->addr32[0]) == (b->addr32[0] & m->addr32[0])) &&
+ ((a->addr32[1]) == (b->addr32[1] & m->addr32[1])) &&
+ ((a->addr32[2]) == (b->addr32[2] & m->addr32[2])) &&
+ ((a->addr32[3]) == (b->addr32[3] & m->addr32[3])))
+ return (1);
+ return (0);
+}
+
+#define grow_sdlist(sd, c, l) do { \
+ if (c == l) { \
+ struct sdlist **tmp; \
+ \
+ tmp = reallocarray(sd, l + 128, sizeof(struct sdlist *)); \
+ if (tmp == NULL) { \
+ /* \
+ * XXX out of memory - return what we have \
+ */ \
+ return (sdnew); \
+ } \
+ sd = tmp; \
+ l += 128; \
+ } \
+} while (0)
+
+static struct sdlist **
+sdl_lookup_v4(struct sdlist *sdl, struct in_addr *src)
+{
+ struct sdentry_v4 *entry;
+ int i, matches = 0;
+ int sdnewlen = 0;
+ struct sdlist **sdnew = NULL;
+
+ while (sdl->tag != NULL) {
+ for (i = 0; i < sdl->v4.naddrs; i++) {
+ entry = &sdl->v4.addrs[i];
+ if (match_addr_v4(&entry->sda, &entry->sdm, src)) {
+ grow_sdlist(sdnew, matches, sdnewlen);
+ sdnew[matches] = sdl;
+ matches++;
+ sdnew[matches] = NULL;
+ break;
+ }
+ }
+ sdl++;
+ }
+ return (sdnew);
+}
+
+static struct sdlist **
+sdl_lookup_v6(struct sdlist *sdl, struct sdaddr_v6 *src)
+{
+ struct sdentry_v6 *entry;
int i, matches = 0;
- struct sdlist *sdl;
- struct sdentry *sda;
- struct sdaddr *source = (struct sdaddr *) src;
int sdnewlen = 0;
struct sdlist **sdnew = NULL;
- if (head == NULL)
- return (NULL);
- else
- sdl = head;
while (sdl->tag != NULL) {
- for (i = 0; i < sdl->naddrs; i++) {
- sda = sdl->addrs + i;
- if (match_addr(&sda->sda, &sda->sdm, source, af)) {
- if (matches == sdnewlen) {
- struct sdlist **tmp;
-
- tmp = reallocarray(sdnew,
- sdnewlen + 128,
- sizeof(struct sdlist *));
- if (tmp == NULL)
- /*
- * XXX out of memory -
- * return what we have
- */
- return (sdnew);
- sdnew = tmp;
- sdnewlen += 128;
- }
- sdnew[matches]= sdl;
+ for (i = 0; i < sdl->v6.naddrs; i++) {
+ entry = &sdl->v6.addrs[i];
+ if (match_addr_v6(&entry->sda, &entry->sdm, src)) {
+ grow_sdlist(sdnew, matches, sdnewlen);
+ sdnew[matches] = sdl;
matches++;
- sdnew[matches]=NULL;
+ sdnew[matches] = NULL;
break;
}
}
@@ -270,12 +317,33 @@
return (sdnew);
}
+/*
+ * Given an address and address family
+ * return list of pointers to matching nodes. or NULL if none.
+ */
+struct sdlist **
+sdl_lookup(struct sdlist *head, int af, void *src)
+{
+ if (head == NULL)
+ return (NULL);
+
+ switch (af) {
+ case AF_INET:
+ return (sdl_lookup_v4(head, src));
+ case AF_INET6:
+ return (sdl_lookup_v6(head, src));
+ default:
+ return (NULL);
+ }
+}
+
static void
sdl_free(struct sdlist *sdl)
{
free(sdl->tag);
free(sdl->string);
- free(sdl->addrs);
+ free(sdl->v4.addrs);
+ free(sdl->v6.addrs);
sdl_clear(sdl);
}
@@ -284,7 +352,8 @@
{
sdl->tag = NULL;
sdl->string = NULL;
- sdl->addrs = NULL;
- sdl->naddrs = 0;
+ sdl->v4.addrs = NULL;
+ sdl->v4.naddrs = 0;
+ sdl->v6.addrs = NULL;
+ sdl->v6.naddrs = 0;
}
-
Index: libexec/spamd/sdl.h
===================================================================
RCS file: /cvs/src/libexec/spamd/sdl.h,v
retrieving revision 1.6
diff -u -r1.6 sdl.h
--- libexec/spamd/sdl.h 3 Nov 2007 19:16:07 -0000 1.6
+++ libexec/spamd/sdl.h 9 Jan 2015 13:38:08 -0000
@@ -22,40 +22,46 @@
#include <sys/types.h>
#include <sys/socket.h>
-/* spamd source list */
-struct sdlist {
- char *tag; /* sdlist source name */
- char *string; /* Format (451) string with no smtp code or \r\n */
- struct sdentry *addrs;
- size_t naddrs;
+/* spamd netblock (black) list entry (ipv4) */
+struct sdentry_v4 {
+ struct in_addr sda;
+ struct in_addr sdm;
};
-/* yeah. Stolen from pf */
-struct sdaddr {
+struct sdentries_v4 {
+ struct sdentry_v4 *addrs;
+ u_int naddrs;
+};
+
+struct sdaddr_v6 {
union {
- struct in_addr v4;
- struct in6_addr v6;
- u_int8_t addr8[16];
- u_int16_t addr16[8];
+ struct in6_addr addr;
u_int32_t addr32[4];
} _sda; /* 128-bit address */
-#define v4 _sda.v4
-#define v6 _sda.v6
-#define addr8 _sda.addr8
-#define addr16 _sda.addr16
-#define addr32 _sda.addr32
+#define addr32 _sda.addr32
};
-/* spamd netblock (black) list */
-struct sdentry {
- struct sdaddr sda;
- struct sdaddr sdm;
+/* spamd netblock (black) list entry (ipv6) */
+struct sdentry_v6 {
+ struct sdaddr_v6 sda;
+ struct sdaddr_v6 sdm;
};
+struct sdentries_v6 {
+ struct sdentry_v6 *addrs;
+ u_int naddrs;
+};
+
+/* spamd source list */
+struct sdlist {
+ char *tag; /* sdlist source name */
+ char *string; /* Format (451) string with no smtp code or \r\n */
+ struct sdentries_v4 v4;
+ struct sdentries_v6 v6;
+};
-extern int sdl_add(char *, char *, char **, int);
-extern void sdl_del(char *);
-extern struct sdlist **sdl_lookup(struct sdlist *head,
- int af, void * src);
+int sdl_add(char *, char *, char **, u_int, char **, u_int);
+void sdl_del(char *);
+struct sdlist **sdl_lookup(struct sdlist *head, int af, void * src);
#endif /* _SDL_H_ */
Index: libexec/spamd/spamd.c
===================================================================
RCS file: /cvs/src/libexec/spamd/spamd.c,v
retrieving revision 1.118
diff -u -r1.118 spamd.c
--- libexec/spamd/spamd.c 30 Dec 2014 23:27:23 -0000 1.118
+++ libexec/spamd/spamd.c 9 Jan 2015 13:38:08 -0000
@@ -29,6 +29,7 @@
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
+#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
@@ -184,11 +185,12 @@
int
parse_configline(char *line)
{
- char *cp, prev, *name, *msg;
- static char **av = NULL;
- static size_t ac = 0;
- size_t au = 0;
+ char *cp, prev, *name, *msg, *tmp;
+ char **v4 = NULL, **v6 = NULL;
+ const char *errstr;
+ u_int nv4 = 0, nv6 = 0;
int mdone = 0;
+ sa_family_t af;
name = line;
@@ -219,11 +221,16 @@
if (*cp == ';') {
mdone = 1;
*cp = '\0';
- } else
+ } else {
+ if (debug > 0)
+ printf("bad message: %s\n",
msg);
goto parse_error;
+ }
}
break;
case '\0':
+ if (debug > 0)
+ printf("bad message: %s\n", msg);
goto parse_error;
default:
prev = '\0';
@@ -231,35 +238,89 @@
}
}
- do {
- if (ac == au) {
- char **tmp;
+ while ((tmp = strsep(&cp, ";")) != NULL) {
+ char **av;
+ u_int au, ac;
- tmp = reallocarray(av, ac + 2048, sizeof(char *));
- if (tmp == NULL) {
- free(av);
- av = NULL;
- ac = 0;
- return (-1);
+ if (*tmp == '\0')
+ continue;
+
+ if (strncmp(tmp, "inet", 4) != 0)
+ goto parse_error;
+ switch (tmp[4]) {
+ case '\0':
+ af = AF_INET;
+ break;
+ case '6':
+ if (tmp[5] == '\0') {
+ af = AF_INET6;
+ break;
}
- av = tmp;
- ac += 2048;
+ /* FALLTHROUGH */
+ default:
+ if (debug > 0)
+ printf("unsupported address family: %s\n", tmp);
+ goto parse_error;
}
- } while ((av[au++] = strsep(&cp, ";")) != NULL);
- /* toss empty last entry to allow for trailing ; */
- while (au > 0 && (av[au - 1] == NULL || av[au - 1][0] == '\0'))
- au--;
+ tmp = strsep(&cp, ";");
+ if (tmp == NULL) {
+ if (debug > 0)
+ printf("missing address count\n");
+ goto parse_error;
+ }
+ ac = strtonum(tmp, 0, UINT_MAX, &errstr);
+ if (errstr != NULL) {
+ if (debug > 0)
+ printf("count \"%s\" is %s\n", tmp, errstr);
+ goto parse_error;
+ }
- if (au < 1)
+ av = reallocarray(NULL, ac, sizeof(char *));
+ for (au = 0; au < ac; au++) {
+ tmp = strsep(&cp, ";");
+ if (tmp == NULL) {
+ if (debug > 0)
+ printf("expected %u addrs, got %u\n",
+ ac, au + 1);
+ free(av);
+ goto parse_error;
+ }
+ if (*tmp == '\0')
+ continue;
+ av[au] = tmp;
+ }
+ if (af == AF_INET) {
+ if (debug > 0)
+ printf("duplicate inet\n");
+ if (v4 != NULL)
+ goto parse_error;
+ v4 = av;
+ nv4 = ac;
+ } else {
+ if (debug > 0)
+ printf("duplicate inet6\n");
+ if (v6 != NULL)
+ goto parse_error;
+ v6 = av;
+ nv6 = ac;
+ }
+ }
+ if (nv4 == 0 && nv6 == 0) {
+ if (debug > 0)
+ printf("no addresses\n");
goto parse_error;
- else
- sdl_add(name, msg, av, au);
+ }
+ sdl_add(name, msg, v4, nv4, v6, nv6);
+ free(v4);
+ free(v6);
return (0);
parse_error:
if (debug > 0)
- printf("bogus config line - need
'tag;message;a/m;a/m;a/m...'\n");
+ printf("bogus config line - need
'tag;message;af;count;a/m;a/m;a/m...'\n");
+ free(v4);
+ free(v6);
return (-1);
}
Index: libexec/spamd-setup/spamd-setup.c
===================================================================
RCS file: /cvs/src/libexec/spamd-setup/spamd-setup.c,v
retrieving revision 1.39
diff -u -r1.39 spamd-setup.c
--- libexec/spamd-setup/spamd-setup.c 9 Oct 2014 02:43:43 -0000 1.39
+++ libexec/spamd-setup/spamd-setup.c 8 Jan 2015 21:27:00 -0000
@@ -60,13 +60,12 @@
struct bl *bl;
size_t blc, bls;
u_int8_t black;
- int count;
};
u_int32_t imask(u_int8_t);
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 *, int *, int *, u_int32_t,
+struct cidr *range2cidrlist(struct cidr *, u_int *, u_int *, u_int32_t,
u_int32_t);
void cidr2range(struct cidr, u_int32_t *, u_int32_t *);
char *atop(u_int32_t);
@@ -78,8 +77,8 @@
void do_message(FILE *, char *);
struct bl *add_blacklist(struct bl *, size_t *, size_t *, gzFile, int);
int cmpbl(const void *, const void *);
-struct cidr *collapse_blacklist(struct bl *, size_t);
-int configure_spamd(u_short, char *, char *, struct cidr *);
+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 getlist(char **, char *, struct blacklist *, struct blacklist
*);
__dead void usage(void);
@@ -131,7 +130,7 @@
}
struct cidr *
-range2cidrlist(struct cidr *list, int *cli, int *cls, u_int32_t start,
+range2cidrlist(struct cidr *list, u_int *cli, u_int *cls, u_int32_t start,
u_int32_t end)
{
u_int8_t maxsize, diff;
@@ -536,9 +535,10 @@
* printable form to pfctl or spamd.
*/
struct cidr *
-collapse_blacklist(struct bl *bl, size_t blc)
+collapse_blacklist(struct bl *bl, size_t blc, u_int *clc)
{
- int bs = 0, ws = 0, state=0, cli, cls, i;
+ int bs = 0, ws = 0, state=0;
+ u_int cli, cls, i;
u_int32_t bstart = 0;
struct cidr *cl;
int laststate;
@@ -579,12 +579,13 @@
laststate = state;
}
cl[cli].addr = 0;
+ *clc = cli;
return (cl);
}
int
configure_spamd(u_short dport, char *name, char *message,
- struct cidr *blacklists)
+ struct cidr *blacklists, u_int count)
{
int lport = IPPORT_RESERVED - 1, s;
struct sockaddr_in sin;
@@ -605,8 +606,9 @@
close(s);
return (-1);
}
- fprintf(sdc, "%s", name);
+ 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);
@@ -757,14 +759,15 @@
send_blacklist(struct blacklist *blist, in_port_t port)
{
struct cidr *cidrs;
+ u_int clc;
if (blist->blc > 0) {
- cidrs = collapse_blacklist(blist->bl, blist->blc);
+ cidrs = collapse_blacklist(blist->bl, blist->blc, &clc);
if (cidrs == NULL)
errx(1, "malloc failed");
if (!dryrun) {
if (configure_spamd(port, blist->name,
- blist->message, cidrs) == -1)
+ blist->message, cidrs, clc) == -1)
err(1, "Can't connect to spamd on port %d",
port);
if (!greyonly && configure_pf(cidrs) == -1)