summaryrefslogtreecommitdiff
path: root/libexec/spamd/sdl.c
diff options
context:
space:
mode:
Diffstat (limited to 'libexec/spamd/sdl.c')
-rw-r--r--libexec/spamd/sdl.c166
1 files changed, 130 insertions, 36 deletions
diff --git a/libexec/spamd/sdl.c b/libexec/spamd/sdl.c
index 2fbf36eac03..b403fda2338 100644
--- a/libexec/spamd/sdl.c
+++ b/libexec/spamd/sdl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sdl.c,v 1.22 2015/05/18 16:04:21 reyk Exp $ */
+/* $OpenBSD: sdl.c,v 1.23 2017/10/17 13:52:10 millert Exp $ */
/*
* Copyright (c) 2003-2007 Bob Beck. All rights reserved.
@@ -45,6 +45,63 @@ extern int debug;
struct sdlist *blacklists = NULL;
int blc = 0, blu = 0;
+static int
+compar_v4(const void *va, const void *vb)
+{
+ const struct sdentry_v4 *a = va;
+ const struct sdentry_v4 *b = vb;
+ struct in_addr aa;
+ struct in_addr bb;
+
+ /* The mask has already been applied. */
+ aa.s_addr = ntohl(a->sda.s_addr);
+ bb.s_addr = ntohl(b->sda.s_addr);
+
+ if (aa.s_addr > bb.s_addr)
+ return (1);
+ if (aa.s_addr < bb.s_addr)
+ return (-1);
+ return (0);
+}
+
+static int
+compar_v6(const void *va, const void *vb)
+{
+ const struct sdentry_v6 *a = va;
+ const struct sdentry_v6 *b = vb;
+ struct sdaddr_v6 aa;
+ struct sdaddr_v6 bb;
+
+ /* The mask has already been applied. */
+ aa.addr32[0] = ntohl(a->sda.addr32[0]);
+ aa.addr32[1] = ntohl(a->sda.addr32[1]);
+ aa.addr32[2] = ntohl(a->sda.addr32[2]);
+ aa.addr32[3] = ntohl(a->sda.addr32[3]);
+
+ bb.addr32[0] = ntohl(b->sda.addr32[0]);
+ bb.addr32[1] = ntohl(b->sda.addr32[1]);
+ bb.addr32[2] = ntohl(b->sda.addr32[2]);
+ bb.addr32[3] = ntohl(b->sda.addr32[3]);
+
+ if (aa.addr32[0] > bb.addr32[0])
+ return (1);
+ if (aa.addr32[0] < bb.addr32[0])
+ return (-1);
+ if (aa.addr32[1] > bb.addr32[1])
+ return (1);
+ if (aa.addr32[1] < bb.addr32[1])
+ return (-1);
+ if (aa.addr32[2] > bb.addr32[2])
+ return (1);
+ if (aa.addr32[2] < bb.addr32[2])
+ return (-1);
+ if (aa.addr32[3] > bb.addr32[3])
+ return (1);
+ if (aa.addr32[3] < bb.addr32[3])
+ return (-1);
+ return (0);
+}
+
int
sdl_add(char *sdname, char *sdstring, char **v4, u_int nv4, char **v6, u_int nv6)
{
@@ -131,6 +188,9 @@ sdl_add(char *sdname, char *sdstring, char **v4, u_int nv4, char **v6, u_int nv6
/* mask off address bits that won't ever be used */
n->s_addr = n->s_addr & m->s_addr;
}
+ /* spamd-setup output is sorted in host byte order */
+ mergesort(blacklists[idx].v4.addrs, nv4,
+ sizeof(struct sdentry_v4), compar_v4);
}
if (nv6 != 0) {
blacklists[idx].v6.naddrs = nv6;
@@ -179,6 +239,9 @@ sdl_add(char *sdname, char *sdstring, char **v4, u_int nv4, char **v6, u_int nv6
for (j = 0; j < 4; j++)
n->addr32[j] = n->addr32[j] & m->addr32[j];
}
+ /* spamd-setup output is sorted in host byte order */
+ mergesort(blacklists[idx].v6.addrs, nv6,
+ sizeof(struct sdentry_v6), compar_v6);
}
if (idx == blu) {
blu++;
@@ -225,31 +288,68 @@ sdl_del(char *sdname)
}
/*
- * 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.
+ * Return 0 if the addresss a (with mask m) matches address key
+ * otherwise return 1 if a > key or -1 if a < key. It is assumed
+ * that address a has been pre-masked out, we only need to mask key.
*/
static int
-match_addr_v4(struct in_addr *a, struct in_addr *m, struct in_addr *b)
+match_addr_v4(const void *vkey, const void *ventry)
{
- if (a->s_addr == (b->s_addr & m->s_addr))
+ const struct in_addr *k = vkey;
+ const struct in_addr *a = &((const struct sdentry_v4 *)ventry)->sda;
+ const struct in_addr *m = &((const struct sdentry_v4 *)ventry)->sdm;
+ struct in_addr kk;
+ struct in_addr aa;
+
+ kk.s_addr = ntohl(k->s_addr & m->s_addr);
+ aa.s_addr = ntohl(a->s_addr);
+ if (kk.s_addr > aa.s_addr)
return (1);
+ if (kk.s_addr < aa.s_addr)
+ return (-1);
return (0);
}
/*
- * 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.
+ * Return 0 if the addresss a (with mask m) matches address key
+ * otherwise return 1 if a > key or -1 if a < key. It is assumed
+ * that address a has been pre-masked out, we only need to mask key.
*/
static int
-match_addr_v6(struct sdaddr_v6 *a, struct sdaddr_v6 *m, struct sdaddr_v6 *b)
+match_addr_v6(const void *vkey, const void *ventry)
{
- 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])))
+ const struct sdaddr_v6 *k = vkey;
+ const struct sdaddr_v6 *a = &((const struct sdentry_v6 *)ventry)->sda;
+ const struct sdaddr_v6 *m = &((const struct sdentry_v6 *)ventry)->sdm;
+ struct sdaddr_v6 kk;
+ struct sdaddr_v6 aa;
+
+ kk.addr32[0] = ntohl(k->addr32[0] & m->addr32[0]);
+ kk.addr32[1] = ntohl(k->addr32[1] & m->addr32[1]);
+ kk.addr32[2] = ntohl(k->addr32[2] & m->addr32[2]);
+ kk.addr32[3] = ntohl(k->addr32[3] & m->addr32[3]);
+
+ aa.addr32[0] = ntohl(a->addr32[0]);
+ aa.addr32[1] = ntohl(a->addr32[1]);
+ aa.addr32[2] = ntohl(a->addr32[2]);
+ aa.addr32[3] = ntohl(a->addr32[3]);
+
+ if (kk.addr32[0] > aa.addr32[0])
+ return (1);
+ if (kk.addr32[0] < aa.addr32[0])
+ return (-1);
+ if (kk.addr32[1] > aa.addr32[1])
return (1);
+ if (kk.addr32[1] < aa.addr32[1])
+ return (-1);
+ if (kk.addr32[2] > aa.addr32[2])
+ return (1);
+ if (kk.addr32[2] < aa.addr32[2])
+ return (-1);
+ if (kk.addr32[3] > aa.addr32[3])
+ return (1);
+ if (kk.addr32[3] < aa.addr32[3])
+ return (-1);
return (0);
}
@@ -272,21 +372,18 @@ match_addr_v6(struct sdaddr_v6 *a, struct sdaddr_v6 *m, struct sdaddr_v6 *b)
static struct sdlist **
sdl_lookup_v4(struct sdlist *sdl, struct in_addr *src)
{
- struct sdentry_v4 *entry;
- int i, matches = 0;
+ int 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;
- }
+ if (bsearch(src, sdl->v4.addrs, sdl->v4.naddrs,
+ sizeof(struct sdentry_v4), match_addr_v4) != NULL) {
+ grow_sdlist(sdnew, matches, sdnewlen);
+ sdnew[matches] = sdl;
+ matches++;
+ sdnew[matches] = NULL;
+ break;
}
sdl++;
}
@@ -296,21 +393,18 @@ sdl_lookup_v4(struct sdlist *sdl, struct in_addr *src)
static struct sdlist **
sdl_lookup_v6(struct sdlist *sdl, struct sdaddr_v6 *src)
{
- struct sdentry_v6 *entry;
- int i, matches = 0;
+ int matches = 0;
int sdnewlen = 0;
struct sdlist **sdnew = NULL;
while (sdl->tag != NULL) {
- 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;
- break;
- }
+ if (bsearch(src, sdl->v6.addrs, sdl->v6.naddrs,
+ sizeof(struct sdentry_v6), match_addr_v6) != NULL) {
+ grow_sdlist(sdnew, matches, sdnewlen);
+ sdnew[matches] = sdl;
+ matches++;
+ sdnew[matches] = NULL;
+ break;
}
sdl++;
}