Module Name: src
Committed By: christos
Date: Tue Jan 27 19:40:37 UTC 2015
Modified Files:
src/external/bsd/blacklist/bin: Makefile blacklistctl.c blacklistd.8
blacklistd.c conf.c conf.h internal.c internal.h run.c run.h
state.c state.h support.c
src/external/bsd/blacklist/etc: blacklistd.conf
src/external/bsd/blacklist/libexec: blacklistd-helper
Added Files:
src/external/bsd/blacklist/bin: blacklistd.conf.5
Log Message:
- separate man page for blacklistd and blacklistd.conf, requested by wiz@
- allow separate configurations for local and remote addresses, implementing
effectively whitelists, requested by dh@
- allow the mask of the filter to be specified, requested by dh@
- the db file format has been changed to accommodate these changes, and
needs to be removed.
To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 src/external/bsd/blacklist/bin/Makefile
cvs rdiff -u -r1.15 -r1.16 src/external/bsd/blacklist/bin/blacklistctl.c \
src/external/bsd/blacklist/bin/conf.c
cvs rdiff -u -r1.8 -r1.9 src/external/bsd/blacklist/bin/blacklistd.8
cvs rdiff -u -r1.29 -r1.30 src/external/bsd/blacklist/bin/blacklistd.c
cvs rdiff -u -r0 -r1.1 src/external/bsd/blacklist/bin/blacklistd.conf.5
cvs rdiff -u -r1.5 -r1.6 src/external/bsd/blacklist/bin/conf.h \
src/external/bsd/blacklist/bin/support.c
cvs rdiff -u -r1.4 -r1.5 src/external/bsd/blacklist/bin/internal.c \
src/external/bsd/blacklist/bin/run.h \
src/external/bsd/blacklist/bin/state.h
cvs rdiff -u -r1.11 -r1.12 src/external/bsd/blacklist/bin/internal.h \
src/external/bsd/blacklist/bin/run.c
cvs rdiff -u -r1.14 -r1.15 src/external/bsd/blacklist/bin/state.c
cvs rdiff -u -r1.2 -r1.3 src/external/bsd/blacklist/etc/blacklistd.conf
cvs rdiff -u -r1.1 -r1.2 src/external/bsd/blacklist/libexec/blacklistd-helper
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/external/bsd/blacklist/bin/Makefile
diff -u src/external/bsd/blacklist/bin/Makefile:1.10 src/external/bsd/blacklist/bin/Makefile:1.11
--- src/external/bsd/blacklist/bin/Makefile:1.10 Thu Jan 22 12:49:41 2015
+++ src/external/bsd/blacklist/bin/Makefile Tue Jan 27 14:40:36 2015
@@ -1,11 +1,10 @@
-# $NetBSD: Makefile,v 1.10 2015/01/22 17:49:41 christos Exp $
+# $NetBSD: Makefile,v 1.11 2015/01/27 19:40:36 christos Exp $
BINDIR=/sbin
PROGS=blacklistd blacklistctl
-MAN.blacklistd=blacklistd.8
+MAN.blacklistd=blacklistd.8 blacklistd.conf.5
MAN.blacklistctl=blacklistctl.8
-MLINKS=blacklistd.8 blacklistd.conf.5
SRCS.blacklistd = blacklistd.c conf.c run.c state.c support.c internal.c
SRCS.blacklistctl = blacklistctl.c conf.c state.c support.c internal.c
DBG=-g
Index: src/external/bsd/blacklist/bin/blacklistctl.c
diff -u src/external/bsd/blacklist/bin/blacklistctl.c:1.15 src/external/bsd/blacklist/bin/blacklistctl.c:1.16
--- src/external/bsd/blacklist/bin/blacklistctl.c:1.15 Sun Jan 25 21:31:52 2015
+++ src/external/bsd/blacklist/bin/blacklistctl.c Tue Jan 27 14:40:36 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: blacklistctl.c,v 1.15 2015/01/26 02:31:52 christos Exp $ */
+/* $NetBSD: blacklistctl.c,v 1.16 2015/01/27 19:40:36 christos Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
#endif
#include <sys/cdefs.h>
-__RCSID("$NetBSD: blacklistctl.c,v 1.15 2015/01/26 02:31:52 christos Exp $");
+__RCSID("$NetBSD: blacklistctl.c,v 1.16 2015/01/27 19:40:36 christos Exp $");
#include <stdio.h>
#include <time.h>
@@ -70,7 +70,6 @@ main(int argc, char *argv[])
const char *dbname = _PATH_BLSTATE;
DB *db;
struct conf c;
- struct sockaddr_storage ss;
struct dbinfo dbi;
unsigned int i;
struct timespec ts;
@@ -118,9 +117,9 @@ main(int argc, char *argv[])
clock_gettime(CLOCK_REALTIME, &ts);
wide = wide ? 8 * 4 + 7 : 4 * 3 + 3;
if (!noheader)
- printf("%*.*s:port\tid\tnfail\t%s\n", wide, wide,
+ printf("%*.*s/ma:port\tid\tnfail\t%s\n", wide, wide,
"address", remain ? "remaining time" : "last access");
- for (i = 1; state_iterate(db, &ss, &c, &dbi, i) != 0; i = 0) {
+ for (i = 1; state_iterate(db, &c, &dbi, i) != 0; i = 0) {
char buf[BUFSIZ];
if (!all) {
if (blocked) {
@@ -131,8 +130,8 @@ main(int argc, char *argv[])
continue;
}
}
- sockaddr_snprintf(buf, sizeof(buf), "%a", (void *)&ss);
- printf("%*.*s:%d\t", wide, wide, buf, c.c_port);
+ sockaddr_snprintf(buf, sizeof(buf), "%a", (void *)&c.c_ss);
+ printf("%*.*s/%d:%d\t", wide, wide, buf, c.c_lmask, c.c_port);
if (remain)
fmtydhms(buf, sizeof(buf),
c.c_duration - (ts.tv_sec - dbi.last));
Index: src/external/bsd/blacklist/bin/conf.c
diff -u src/external/bsd/blacklist/bin/conf.c:1.15 src/external/bsd/blacklist/bin/conf.c:1.16
--- src/external/bsd/blacklist/bin/conf.c:1.15 Sun Jan 25 16:06:04 2015
+++ src/external/bsd/blacklist/bin/conf.c Tue Jan 27 14:40:36 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: conf.c,v 1.15 2015/01/25 21:06:04 christos Exp $ */
+/* $NetBSD: conf.c,v 1.16 2015/01/27 19:40:36 christos Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
#endif
#include <sys/cdefs.h>
-__RCSID("$NetBSD: conf.c,v 1.15 2015/01/25 21:06:04 christos Exp $");
+__RCSID("$NetBSD: conf.c,v 1.16 2015/01/27 19:40:36 christos Exp $");
#include <stdio.h>
#include <string.h>
@@ -82,7 +82,6 @@ advance(char **p)
*p = ep;
}
-
static int
getnum(const char *f, size_t l, void *r, const char *p)
{
@@ -103,13 +102,47 @@ getnum(const char *f, size_t l, void *r,
}
static int
-getsecs(const char *f, size_t l, void *r, const char *p)
+getnfail(const char *f, size_t l, bool local, struct conf *c, const char *p)
+{
+ if (strcmp(p, "*") == 0) {
+ c->c_nfail = -1;
+ return 0;
+ }
+ if (strcmp(p, "=") == 0) {
+ if (local)
+ goto out;
+ c->c_nfail = -2;
+ return 0;
+ }
+ if (getnum(NULL, 0, &c->c_nfail, p) == 0)
+ return 0;
+
+ (*lfun)(LOG_ERR, "%s: %s, %zu: Bad nfail [%s]", __func__, f, l, p);
+ return -1;
+out:
+ (*lfun)(LOG_ERR, "%s: %s, %zu: `=' nfail not allowed in local config",
+ __func__, f, l);
+ return -1;
+}
+
+static int
+getsecs(const char *f, size_t l, bool local, struct conf *c, const char *p)
{
int e;
char *ep;
intmax_t tot, im;
tot = 0;
+ if (strcmp(p, "*") == 0) {
+ c->c_duration = -1;
+ return 0;
+ }
+ if (strcmp(p, "=") == 0) {
+ if (local)
+ goto out;
+ c->c_duration = -2;
+ return 0;
+ }
again:
im = strtoi(p, &ep, 0, 0, INT_MAX, &e);
@@ -137,7 +170,7 @@ again:
tot = im;
if (e == 0) {
- *(int *)r = (int)tot;
+ c->c_duration = (int)tot;
return 0;
}
@@ -145,10 +178,13 @@ again:
return -1;
(*lfun)(LOG_ERR, "%s: %s, %zu: Bad number [%s]", __func__, f, l, p);
return -1;
+out:
+ (*lfun)(LOG_ERR, "%s: %s, %zu: `=' duration not allowed in local"
+ " config", __func__, f, l);
+ return -1;
}
-
static int
getport(const char *f, size_t l, void *r, const char *p)
{
@@ -172,16 +208,69 @@ getport(const char *f, size_t l, void *r
}
static int
-gethostport(const char *f, size_t l, void *v, const char *p)
+getmask(const char *f, size_t l, bool local __unused, const char **p, int def)
+{
+ char *d;
+ int e;
+ intmax_t im;
+ const char *s = *p;
+
+ if ((d = strchr(s, ':')) != NULL) {
+ *d++ = '\0';
+ *p = d;
+ }
+ if ((d = strchr(s, '/')) == NULL)
+ return def;
+
+ *d++ = '\0';
+ if (strcmp(d, "=") == 0) {
+ if (local)
+ goto out;
+ return -2;
+ }
+ if (strcmp(d, "*") == 0)
+ return def;
+
+ im = strtoi(d, NULL, 0, 0, def, &e);
+ if (e == 0)
+ return (int)im;
+
+ (*lfun)(LOG_ERR, "%s: %s, %zu: Bad mask [%s]", __func__, f, l, d);
+ return -1;
+out:
+ (*lfun)(LOG_ERR, "%s: %s, %zu: `=' name not allowed in local"
+ " config", __func__, f, l);
+ return -1;
+}
+
+static int
+gethostport(const char *f, size_t l, bool local, struct conf *c, const char *p)
{
char *d; // XXX: Ok to write to string.
in_port_t *port = NULL;
- struct conf *c = v;
+ const char *pstr;
- if ((d = strstr(p, "]:")) != NULL) {
- struct sockaddr_in6 *sin6 = (void *)&c->c_ss;
+ if (strcmp(p, "*") == 0) {
+ c->c_port = -1;
+ c->c_lmask = -1;
+ return 0;
+ }
+
+ if ((d = strchr(p, ']')) != NULL) {
*d++ = '\0';
+ pstr = d;
p++;
+ } else
+ pstr = p;
+
+ if ((c->c_lmask = getmask(f, l, local, &pstr, 256)) == -1)
+ goto out;
+
+ if (c->c_lmask == 256)
+ c->c_lmask = -1;
+
+ if (d) {
+ struct sockaddr_in6 *sin6 = (void *)&c->c_ss;
if (debug)
(*lfun)(LOG_DEBUG, "%s: host6 %s", __func__, p);
if (strcmp(p, "*") != 0) {
@@ -193,15 +282,20 @@ gethostport(const char *f, size_t l, voi
#endif
port = &sin6->sin6_port;
}
- p = ++d;
- } else if ((d = strrchr(p, ':')) != NULL) {
+ } else if (pstr != p || strchr(p, '.') || conf_is_interface(p)) {
+ if (pstr == p)
+ pstr = "*";
struct sockaddr_in *sin = (void *)&c->c_ss;
struct sockaddr_if *sif = (void *)&c->c_ss;
- *d++ = '\0';
if (debug)
(*lfun)(LOG_DEBUG, "%s: host4 %s", __func__, p);
if (strcmp(p, "*") != 0) {
if (conf_is_interface(p)) {
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s: interface %s",
+ __func__, p);
+ if (c->c_lmask != -1)
+ goto out1;
sif->sif_family = AF_MAX;
strlcpy(sif->sif_name, p,
sizeof(sif->sif_name));
@@ -215,38 +309,46 @@ gethostport(const char *f, size_t l, voi
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
sin->sin_len = sizeof(*sin);
#endif
- port = &sif->sif_port;
+ port = &sin->sin_port;
} else
goto out;
}
- p = d;
}
- if (strcmp(p, "*") == 0)
+ if (strcmp(pstr, "*") == 0)
c->c_port = -1;
- else if (getport(f, l, &c->c_port, p) == -1)
+ else if (getport(f, l, &c->c_port, pstr) == -1)
return -1;
if (port && c->c_port != -1)
*port = htons((in_port_t)c->c_port);
return 0;
out:
- (*lfun)(LOG_ERR, "%s: %s, %zu: Bad address [%s]", __func__, f, l, p);
+ (*lfun)(LOG_ERR, "%s: %s, %zu: Bad address [%s]", __func__, f, l, pstr);
+ return -1;
+out1:
+ (*lfun)(LOG_ERR, "%s: %s, %zu: Can't specify mask %d with "
+ "interface [%s]", __func__, f, l, c->c_lmask, p);
return -1;
}
static int
-getproto(const char *f, size_t l, void *r, const char *p)
+getproto(const char *f, size_t l, bool local __unused, struct conf *c,
+ const char *p)
{
+ if (strcmp(p, "*") == 0) {
+ c->c_proto = -1;
+ return 0;
+ }
if (strcmp(p, "stream") == 0) {
- *(int *)r = IPPROTO_TCP;
+ c->c_proto = IPPROTO_TCP;
return 0;
}
if (strcmp(p, "dgram") == 0) {
- *(int *)r = IPPROTO_UDP;
+ c->c_proto = IPPROTO_UDP;
return 0;
}
- if (getnum(NULL, 0, r, p) == 0)
+ if (getnum(NULL, 0, &c->c_proto, p) == 0)
return 0;
(*lfun)(LOG_ERR, "%s: %s, %zu: Bad protocol [%s]", __func__, f, l, p);
@@ -254,13 +356,19 @@ getproto(const char *f, size_t l, void *
}
static int
-getfamily(const char *f, size_t l, void *r, const char *p)
+getfamily(const char *f, size_t l, bool local __unused, struct conf *c,
+ const char *p)
{
+ if (strcmp(p, "*") == 0) {
+ c->c_family = -1;
+ return 0;
+ }
+
if (strncmp(p, "tcp", 3) == 0 || strncmp(p, "udp", 3) == 0) {
- *(int *)r = p[3] == '6' ? AF_INET6 : AF_INET;
+ c->c_family = p[3] == '6' ? AF_INET6 : AF_INET;
return 0;
}
- if (getnum(NULL, 0, r, p) == 0)
+ if (getnum(NULL, 0, &c->c_family, p) == 0)
return 0;
(*lfun)(LOG_ERR, "%s: %s, %zu: Bad family [%s]", __func__, f, l, p);
@@ -268,51 +376,70 @@ getfamily(const char *f, size_t l, void
}
static int
-getuid(const char *f, size_t l, void *r, const char *p)
+getuid(const char *f, size_t l, bool local __unused, struct conf *c,
+ const char *p)
{
struct passwd *pw;
+ if (strcmp(p, "*") == 0) {
+ c->c_uid = -1;
+ return 0;
+ }
+
if ((pw = getpwnam(p)) != NULL) {
- *(int *)r = (int)pw->pw_uid;
+ c->c_uid = (int)pw->pw_uid;
return 0;
}
- if (getnum(NULL, 0, r, p) == 0)
+ if (getnum(NULL, 0, &c->c_uid, p) == 0)
return 0;
(*lfun)(LOG_ERR, "%s: %s, %zu: Bad user [%s]", __func__, f, l, p);
return -1;
}
+
static int
-getname(const char *f __unused, size_t l __unused, void *r, const char *p)
+getname(const char *f, size_t l, bool local, struct conf *c,
+ const char *p)
{
- snprintf(r, CONFNAMESZ, "%s%s", *p == '-' ? rulename : "", p);
+ if ((c->c_rmask = getmask(f, l, local, &p, 256)) == -1)
+ return -1;
+ if (c->c_rmask == 256)
+ c->c_rmask = local ? -1 : -2;
+
+ if (strcmp(p, "*") == 0) {
+ strlcpy(c->c_name, rulename, CONFNAMESZ);
+ return 0;
+ }
+ if (strcmp(p, "=") == 0) {
+ if (local)
+ goto out;
+ c->c_name[0] = '\0';
+ return 0;
+ }
+
+ snprintf(c->c_name, CONFNAMESZ, "%s%s", *p == '-' ? rulename : "", p);
return 0;
+out:
+ (*lfun)(LOG_ERR, "%s: %s, %zu: `=' name not allowed in local"
+ " config", __func__, f, l);
+ return -1;
}
static int
-getvalue(const char *f, size_t l, void *r, char **p,
- int (*fun)(const char *, size_t, void *, const char *))
+getvalue(const char *f, size_t l, bool local, void *r, char **p,
+ int (*fun)(const char *, size_t, bool, struct conf *, const char *))
{
char *ep = *p;
advance(p);
- if (strcmp(ep, "*") == 0) {
- if (fun == gethostport)
- ((struct conf *)r)->c_port = -1;
- else if (fun == getname)
- strlcpy(r, rulename, CONFNAMESZ);
- else
- *(int *)r = -1;
- return 0;
- }
- return (*fun)(f, l, r, ep);
+ return (*fun)(f, l, local, r, ep);
}
static int
-conf_parseline(const char *f, size_t l, char *p, struct conf *c)
+conf_parseline(const char *f, size_t l, char *p, struct conf *c, bool local)
{
int e;
@@ -320,19 +447,19 @@ conf_parseline(const char *f, size_t l,
p++;
memset(c, 0, sizeof(*c));
- e = getvalue(f, l, c, &p, gethostport);
+ e = getvalue(f, l, local, c, &p, gethostport);
if (e) return -1;
- e = getvalue(f, l, &c->c_proto, &p, getproto);
+ e = getvalue(f, l, local, c, &p, getproto);
if (e) return -1;
- e = getvalue(f, l, &c->c_family, &p, getfamily);
+ e = getvalue(f, l, local, c, &p, getfamily);
if (e) return -1;
- e = getvalue(f, l, &c->c_uid, &p, getuid);
+ e = getvalue(f, l, local, c, &p, getuid);
if (e) return -1;
- e = getvalue(f, l, &c->c_name, &p, getname);
+ e = getvalue(f, l, local, c, &p, getname);
if (e) return -1;
- e = getvalue(f, l, &c->c_nfail, &p, getnum);
+ e = getvalue(f, l, local, c, &p, getnfail);
if (e) return -1;
- e = getvalue(f, l, &c->c_duration, &p, getsecs);
+ e = getvalue(f, l, local, c, &p, getsecs);
if (e) return -1;
return 0;
@@ -349,9 +476,11 @@ conf_sort(const void *v1, const void *v2
else if ((a)->f < (b)->f) return 1
CMP(c1, c2, c_ss.ss_family);
+ CMP(c1, c2, c_lmask);
CMP(c1, c2, c_port);
CMP(c1, c2, c_proto);
CMP(c1, c2, c_family);
+ CMP(c1, c2, c_rmask);
CMP(c1, c2, c_uid);
#undef CMP
return 0;
@@ -362,21 +491,180 @@ conf_is_interface(const char *name)
{
const struct ifaddrs *ifa;
- for (ifa = ifas; ifas; ifa = ifa->ifa_next)
+ for (ifa = ifas; ifa; ifa = ifa->ifa_next)
if (strcmp(ifa->ifa_name, name) == 0)
return 1;
return 0;
}
+#define MASK(m) ((uint32_t)~((1 << (32 - (m))) - 1))
+
+static int
+conf_amask_eq(const void *v1, const void *v2, size_t len, int mask)
+{
+ const uint32_t *a1 = v1;
+ const uint32_t *a2 = v2;
+ uint32_t m;
+
+ len >>= 2;
+ switch (mask) {
+ case -1:
+ return memcmp(v1, v2, len) == 0;
+ case -2:
+
+ (*lfun)(LOG_CRIT, "%s: Internal error: bad mask %d", __func__,
+ mask);
+ abort();
+ default:
+ break;
+ }
+
+ for (size_t i = 0; i < len; i++) {
+ if (mask > 32) {
+ m = (uint32_t)~0;
+ mask -= 32;
+ } else if (mask) {
+ m = MASK(mask);
+ mask = 0;
+ } else
+ return 1;
+ if ((a1[i] & m) != (a2[i] & m))
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Apply the mask to the given address
+ */
+static void
+conf_apply_mask(void *v, size_t len, int mask)
+{
+ uint32_t *a = v;
+ uint32_t m;
+
+ switch (mask) {
+ case -1:
+ return;
+ case -2:
+ (*lfun)(LOG_CRIT, "%s: Internal error: bad mask %d", __func__,
+ mask);
+ abort();
+ default:
+ break;
+ }
+ len >>= 2;
+
+ for (size_t i = 0; i < len; i++) {
+ if (mask > 32) {
+ m = (uint32_t)~0;
+ mask -= 32;
+ } else if (mask) {
+ m = MASK(mask);
+ mask = 0;
+ }
+ a[i] &= m;
+ }
+}
+
+/*
+ * apply the mask and the port to the address given
+ */
+static void
+conf_addr_set(struct conf *c, const struct sockaddr_storage *ss)
+{
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ in_port_t *port;
+ void *addr;
+ size_t alen;
+
+ c->c_lmask = c->c_rmask;
+ c->c_ss = *ss;
+
+ if (c->c_ss.ss_family != c->c_family) {
+ (*lfun)(LOG_CRIT, "%s: Internal error: mismatched family "
+ "%u != %u", __func__, c->c_ss.ss_family, c->c_family);
+ abort();
+ }
+
+ switch (c->c_ss.ss_family) {
+ case AF_INET:
+ sin = (void *)&c->c_ss;
+ port = &sin->sin_port;
+ addr = &sin->sin_addr;
+ alen = sizeof(sin->sin_addr);
+ break;
+ case AF_INET6:
+ sin6 = (void *)&c->c_ss;
+ port = &sin6->sin6_port;
+ addr = &sin6->sin6_addr;
+ alen = sizeof(sin6->sin6_addr);
+ break;
+ default:
+ (*lfun)(LOG_CRIT, "%s: Internal error: bad family %u",
+ __func__, c->c_ss.ss_family);
+ abort();
+ }
+
+ *port = htons(c->c_port);
+ conf_apply_mask(addr, alen, c->c_lmask);
+ if (c->c_lmask == -1)
+ c->c_lmask = (int)(alen * 8);
+ if (debug) {
+ char buf[128];
+ sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (void *)&c->c_ss);
+ (*lfun)(LOG_DEBUG, "Applied address %s", buf);
+ }
+}
+
+/*
+ * Compared two addresses for equality applying the mask
+ */
+static int
+conf_inet_eq(const void *v1, const void *v2, int mask)
+{
+ const struct sockaddr *sa1 = v1;
+ const struct sockaddr *sa2 = v2;
+ size_t size;
+
+ if (sa1->sa_family != sa2->sa_family)
+ return 0;
+
+ switch (sa1->sa_family) {
+ case AF_INET: {
+ const struct sockaddr_in *s1 = v1;
+ const struct sockaddr_in *s2 = v2;
+ size = sizeof(s1->sin_addr);
+ v1 = &s1->sin_addr;
+ v2 = &s2->sin_addr;
+ break;
+ }
+
+ case AF_INET6: {
+ const struct sockaddr_in6 *s1 = v1;
+ const struct sockaddr_in6 *s2 = v2;
+ size = sizeof(s1->sin6_addr);
+ v1 = &s1->sin6_addr;
+ v2 = &s2->sin6_addr;
+ break;
+ }
+
+ default:
+ (*lfun)(LOG_CRIT, "%s: Internal error: bad family %u",
+ __func__, sa1->sa_family);
+ abort();
+ }
+
+ return conf_amask_eq(v1, v2, size, mask);
+}
+
static int
conf_addr_in_interface(const struct sockaddr_storage *s1,
- const struct sockaddr_storage *s2)
+ const struct sockaddr_storage *s2, int mask)
{
const char *name = SIF_NAME(s2);
const struct ifaddrs *ifa;
- socklen_t slen;
- const struct sockaddr_in *sin = (const void *)s1;
- const struct sockaddr_in6 *sin6 = (const void *)s1;
for (ifa = ifas; ifa; ifa = ifa->ifa_next) {
if ((ifa->ifa_flags & IFF_UP) == 0)
@@ -388,24 +676,17 @@ conf_addr_in_interface(const struct sock
if (s1->ss_family != ifa->ifa_addr->sa_family)
continue;
- const void *v = ifa->ifa_addr;
- const void *p1, *p2;
+ bool eq;
switch (s1->ss_family) {
case AF_INET:
- p1 = &sin->sin_addr;
- p2 = &((const struct sockaddr_in *)v)->sin_addr;
- slen = sizeof(sin->sin_addr);
- break;
case AF_INET6:
- p1 = &sin6->sin6_addr;
- p2 = &((const struct sockaddr_in6 *)v)->sin6_addr;
- slen = sizeof(sin6->sin6_addr);
+ eq = conf_inet_eq(ifa->ifa_addr, s1, mask);
break;
default:
(*lfun)(LOG_ERR, "Bad family %u", s1->ss_family);
continue;
}
- if (memcmp(p1, p2, slen) == 0)
+ if (eq)
return 1;
}
return 0;
@@ -413,20 +694,20 @@ conf_addr_in_interface(const struct sock
static int
conf_addr_eq(const struct sockaddr_storage *s1,
- const struct sockaddr_storage *s2)
+ const struct sockaddr_storage *s2, int mask)
{
switch (s2->ss_family) {
case 0:
return 1;
case AF_MAX:
- return conf_addr_in_interface(s1, s2);
+ return conf_addr_in_interface(s1, s2, mask);
+ case AF_INET:
+ case AF_INET6:
+ return conf_inet_eq(s1, s2, mask);
default:
- if (memcmp(s1, s2, sizeof(*s2))) {
- if (debug > 1)
- (*lfun)(LOG_DEBUG, "%s: c_ss fail", __func__);
- return 0;
- }
- return 1;
+ (*lfun)(LOG_CRIT, "%s: Internal error: bad family %u",
+ __func__, s1->ss_family);
+ abort();
}
}
@@ -434,14 +715,14 @@ static int
conf_eq(const struct conf *c1, const struct conf *c2)
{
- if (!conf_addr_eq(&c1->c_ss, &c2->c_ss))
+ if (!conf_addr_eq(&c1->c_ss, &c2->c_ss, c2->c_lmask))
return 0;
#define CMP(a, b, f) \
if ((a)->f != (b)->f && (b)->f != -1) { \
if (debug > 1) \
- (*lfun)(LOG_DEBUG, "%s: %s fail", __func__, \
- __STRING(f)); \
+ (*lfun)(LOG_DEBUG, "%s: %s fail %d != %d", __func__, \
+ __STRING(f), (a)->f, (b)->f); \
return 0; \
}
CMP(c1, c2, c_port);
@@ -455,14 +736,19 @@ conf_eq(const struct conf *c1, const str
static const char *
conf_num(char *b, size_t l, int n)
{
- if (n == -1)
+ switch (n) {
+ case -1:
return "*";
- snprintf(b, l, "%d", n);
- return b;
+ case -2:
+ return "=";
+ default:
+ snprintf(b, l, "%d", n);
+ return b;
+ }
}
static const char *
-conf_name(const char *n) {
+fmtname(const char *n) {
size_t l = strlen(rulename);
if (l == 0)
return "*";
@@ -471,73 +757,285 @@ conf_name(const char *n) {
return n + l;
else
return "*";
- } else
+ } else if (!*n)
+ return "=";
+ else
return n;
}
+static void
+fmtport(char *b, size_t l, int port)
+{
+ char buf[128];
+
+ if (port == -1)
+ return;
+
+ if (b[0] == '\0' || strcmp(b, "*") == 0)
+ snprintf(b, l, "%d", port);
+ else {
+ snprintf(buf, sizeof(buf), ":%d", port);
+ strlcat(b, buf, l);
+ }
+}
+
+static const char *
+fmtmask(char *b, size_t l, int fam, int mask)
+{
+ char buf[128];
+
+ switch (mask) {
+ case -1:
+ return "";
+ case -2:
+ if (strcmp(b, "=") == 0)
+ return "";
+ else {
+ strlcat(b, "/=", l);
+ return b;
+ }
+ default:
+ break;
+ }
+
+ switch (fam) {
+ case AF_INET:
+ if (mask == 32)
+ return "";
+ break;
+ case AF_INET6:
+ if (mask == 128)
+ return "";
+ break;
+ default:
+ break;
+ }
+
+ snprintf(buf, sizeof(buf), "/%d", mask);
+ strlcat(b, buf, l);
+ return b;
+}
+
+static const char *
+conf_namemask(char *b, size_t l, const struct conf *c)
+{
+ strlcpy(b, fmtname(c->c_name), l);
+ fmtmask(b, l, c->c_family, c->c_rmask);
+ return b;
+}
+
const char *
conf_print(char *buf, size_t len, const char *pref, const char *delim,
const struct conf *c)
{
- char hb[128], b[5][64];
+ char ha[128], hb[32], b[5][64];
int sp;
#define N(n, v) conf_num(b[n], sizeof(b[n]), (v))
switch (c->c_ss.ss_family) {
case 0:
- if (c->c_port == -1)
- snprintf(hb, sizeof(hb), "*");
- else
- snprintf(hb, sizeof(hb), "%d", c->c_port);
+ snprintf(ha, sizeof(ha), "*");
break;
case AF_MAX:
- if (c->c_port == -1)
- snprintf(hb, sizeof(hb), "%s:*", SIF_NAME(&c->c_ss));
- else
- snprintf(hb, sizeof(hb), "%s:%d", SIF_NAME(&c->c_ss),
- c->c_port);
+ snprintf(ha, sizeof(ha), "%s", SIF_NAME(&c->c_ss));
break;
default:
- if (c->c_port == -1)
- sockaddr_snprintf(hb, sizeof(hb), "%a:*",
- (const void *)&c->c_ss);
- else
- sockaddr_snprintf(hb, sizeof(hb), "%a:%p",
- (const void *)&c->c_ss);
+ sockaddr_snprintf(ha, sizeof(ha), "%a", (const void *)&c->c_ss);
break;
}
+
+ fmtmask(ha, sizeof(ha), c->c_family, c->c_lmask);
+ fmtport(ha, sizeof(ha), c->c_port);
sp = *delim == '\t' ? 20 : -1;
+ hb[0] = '\0';
if (*delim)
snprintf(buf, len, "%s%*.*s%s%s%s" "%s%s%s%s"
"%s%s" "%s%s%s",
- pref, sp, sp, hb, delim, N(0, c->c_proto), delim,
+ pref, sp, sp, ha, delim, N(0, c->c_proto), delim,
N(1, c->c_family), delim, N(2, c->c_uid), delim,
- conf_name(c->c_name), delim,
+ conf_namemask(hb, sizeof(hb), c), delim,
N(3, c->c_nfail), delim, N(4, c->c_duration));
else
snprintf(buf, len, "%starget=%s, proto=%s, family=%s, "
"uid=%s, name=%s, nfail=%s, duration=%s", pref,
- hb, N(0, c->c_proto), N(1, c->c_family), N(2, c->c_uid),
- conf_name(c->c_name), N(3, c->c_nfail),
- N(4, c->c_duration));
+ ha, N(0, c->c_proto), N(1, c->c_family), N(2, c->c_uid),
+ conf_namemask(hb, sizeof(hb), c),
+ N(3, c->c_nfail), N(4, c->c_duration));
return buf;
}
+/*
+ * Apply the local config match to the result
+ */
+static void
+conf_apply(struct conf *c, const struct conf *sc)
+{
+ char buf[BUFSIZ];
+
+ if (debug) {
+ (*lfun)(LOG_DEBUG, "%s: %s", __func__,
+ conf_print(buf, sizeof(buf), "merge:\t", "", sc));
+ (*lfun)(LOG_DEBUG, "%s: %s", __func__,
+ conf_print(buf, sizeof(buf), "to:\t", "", c));
+ }
+ memcpy(c->c_name, sc->c_name, CONFNAMESZ);
+ c->c_rmask = sc->c_rmask;
+ c->c_nfail = sc->c_nfail;
+ c->c_duration = sc->c_duration;
+
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s: %s", __func__,
+ conf_print(buf, sizeof(buf), "result:\t", "", c));
+}
+
+/*
+ * Merge a remote configuration to the result
+ */
+static void
+conf_merge(struct conf *c, const struct conf *sc)
+{
+ char buf[BUFSIZ];
+
+ if (debug) {
+ (*lfun)(LOG_DEBUG, "%s: %s", __func__,
+ conf_print(buf, sizeof(buf), "merge:\t", "", sc));
+ (*lfun)(LOG_DEBUG, "%s: %s", __func__,
+ conf_print(buf, sizeof(buf), "to:\t", "", c));
+ }
+
+ if (sc->c_name[0])
+ memcpy(c->c_name, sc->c_name, CONFNAMESZ);
+ if (sc->c_rmask != -2)
+ c->c_lmask = c->c_rmask = sc->c_rmask;
+ if (sc->c_nfail != -2)
+ c->c_nfail = sc->c_nfail;
+ if (sc->c_duration != -2)
+ c->c_duration = sc->c_duration;
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s: %s", __func__,
+ conf_print(buf, sizeof(buf), "result:\t", "", c));
+}
+
+static void
+confset_init(struct confset *cs)
+{
+ cs->cs_c = NULL;
+ cs->cs_n = 0;
+ cs->cs_m = 0;
+}
+
+static int
+confset_grow(struct confset *cs)
+{
+ void *tc;
+
+ cs->cs_m += 10;
+ tc = realloc(cs->cs_c, cs->cs_m * sizeof(*cs->cs_c));
+ if (tc == NULL) {
+ (*lfun)(LOG_ERR, "%s: Can't grow confset (%m)", __func__);
+ return -1;
+ }
+ cs->cs_c = tc;
+ return 0;
+}
+
+static struct conf *
+confset_get(struct confset *cs)
+{
+ return &cs->cs_c[cs->cs_n];
+}
+
+static bool
+confset_full(const struct confset *cs)
+{
+ return cs->cs_n == cs->cs_m;
+}
+
+static void
+confset_sort(struct confset *cs)
+{
+ qsort(cs->cs_c, cs->cs_n, sizeof(*cs->cs_c), conf_sort);
+}
+
+static void
+confset_add(struct confset *cs)
+{
+ cs->cs_n++;
+}
+
+static void
+confset_free(struct confset *cs)
+{
+ free(cs->cs_c);
+ confset_init(cs);
+}
+
+static void
+confset_replace(struct confset *dc, struct confset *sc)
+{
+ struct confset tc;
+ tc = *dc;
+ *dc = *sc;
+ confset_init(sc);
+ confset_free(&tc);
+}
+
+static void
+confset_list(const struct confset *cs, const char *msg, const char *where)
+{
+ char buf[BUFSIZ];
+
+ (*lfun)(LOG_DEBUG, "[%s]", msg);
+ (*lfun)(LOG_DEBUG, "%20.20s\ttype\tproto\towner\tname\tnfail\tduration",
+ where);
+ for (size_t i = 0; i < cs->cs_n; i++)
+ (*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf), "", "\t",
+ &cs->cs_c[i]));
+}
+
+/*
+ * Match a configuration against the given list and apply the function
+ * to it, returning the matched entry number.
+ */
+static size_t
+confset_match(const struct confset *cs, struct conf *c,
+ void (*fun)(struct conf *, const struct conf *))
+{
+ char buf[BUFSIZ];
+ size_t i;
+
+ for (i = 0; i < cs->cs_n; i++) {
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf),
+ "check:\t", "", &cs->cs_c[i]));
+ if (conf_eq(c, &cs->cs_c[i])) {
+ if (debug)
+ (*lfun)(LOG_DEBUG, "%s",
+ conf_print(buf, sizeof(buf),
+ "found:\t", "", &cs->cs_c[i]));
+ (*fun)(c, &cs->cs_c[i]);
+ break;
+ }
+ }
+ return i;
+}
+
const struct conf *
-conf_find(int fd, uid_t uid, struct conf *cr)
+conf_find(int fd, uid_t uid, const struct sockaddr_storage *rss,
+ struct conf *cr)
{
int proto;
socklen_t slen;
- struct sockaddr_storage ss;
+ struct sockaddr_storage lss;
size_t i;
char buf[BUFSIZ];
memset(cr, 0, sizeof(*cr));
- slen = sizeof(ss);
- memset(&ss, 0, slen);
- if (getsockname(fd, (void *)&ss, &slen) == -1) {
+ slen = sizeof(lss);
+ memset(&lss, 0, slen);
+ if (getsockname(fd, (void *)&lss, &slen) == -1) {
(*lfun)(LOG_ERR, "getsockname failed (%m)");
return NULL;
}
@@ -549,7 +1047,7 @@ conf_find(int fd, uid_t uid, struct conf
}
if (debug) {
- sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (void *)&ss);
+ sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (void *)&lss);
(*lfun)(LOG_DEBUG, "listening socket: %s", buf);
}
@@ -565,21 +1063,24 @@ conf_find(int fd, uid_t uid, struct conf
return NULL;
}
- switch (ss.ss_family) {
+ switch (lss.ss_family) {
case AF_INET:
- cr->c_port = ntohs(((struct sockaddr_in *)&ss)->sin_port);
+ cr->c_port = ntohs(((struct sockaddr_in *)&lss)->sin_port);
break;
case AF_INET6:
- cr->c_port = ntohs(((struct sockaddr_in6 *)&ss)->sin6_port);
+ cr->c_port = ntohs(((struct sockaddr_in6 *)&lss)->sin6_port);
break;
default:
- (*lfun)(LOG_ERR, "unsupported family %d", ss.ss_family);
+ (*lfun)(LOG_ERR, "unsupported family %d", lss.ss_family);
return NULL;
}
- cr->c_ss = ss;
+ cr->c_ss = lss;
+ cr->c_lmask = -1;
cr->c_uid = (int)uid;
- cr->c_family = ss.ss_family;
+ cr->c_family = lss.ss_family;
+ cr->c_name[0] = '\0';
+ cr->c_rmask = -1;
cr->c_nfail = -1;
cr->c_duration = -1;
@@ -587,34 +1088,29 @@ conf_find(int fd, uid_t uid, struct conf
(*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf),
"look:\t", "", cr));
- for (i = 0; i < nconf; i++) {
+ /* match the local config */
+ i = confset_match(&lconf, cr, conf_apply);
+ if (i == lconf.cs_n) {
if (debug)
- (*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf),
- "check:\t", "", &conf[i]));
- if (conf_eq(cr, &conf[i])) {
- if (debug)
- (*lfun)(LOG_DEBUG, "%s",
- conf_print(buf, sizeof(buf),
- "found:\t", "", &conf[i]));
- cr->c_ss = conf[i].c_ss;
- memcpy(cr->c_name, conf[i].c_name, CONFNAMESZ);
- cr->c_nfail = conf[i].c_nfail;
- cr->c_duration = conf[i].c_duration;
- return cr;
- }
+ (*lfun)(LOG_DEBUG, "not found");
+ return NULL;
}
- if (debug)
- (*lfun)(LOG_DEBUG, "not found");
- return NULL;
+
+ conf_addr_set(cr, rss);
+ /* match the remote config */
+ confset_match(&rconf, cr, conf_merge);
+
+ return cr;
}
+
void
conf_parse(const char *f)
{
FILE *fp;
char *line;
- size_t lineno, len, nc, mc;
- struct conf *c, *tc;
+ size_t lineno, len;
+ struct confset lc, rc, *cs;
if ((fp = fopen(f, "r")) == NULL) {
(*lfun)(LOG_ERR, "%s: Cannot open `%s' (%m)", __func__, f);
@@ -622,46 +1118,47 @@ conf_parse(const char *f)
}
lineno = 1;
- nc = mc = 0;
- c = NULL;
+
+ confset_init(&rc);
+ confset_init(&lc);
+ cs = &lc;
for (; (line = fparseln(fp, &len, &lineno, NULL, 0)) != NULL;
free(line))
{
-#ifdef __APPLE__
if (!*line)
continue;
- if (debug > 4)
- (*lfun)(LOG_DEBUG, "%s, %zu: [%s]", f, lineno, line);
-#endif
- if (nc == mc) {
- mc += 10;
- tc = realloc(c, mc * sizeof(*c));
- if (tc == NULL) {
- free(c);
+ if (strcmp(line, "[local]") == 0) {
+ cs = &lc;
+ continue;
+ }
+ if (strcmp(line, "[remote]") == 0) {
+ cs = &rc;
+ continue;
+ }
+
+ if (confset_full(cs)) {
+ if (confset_grow(cs) == -1) {
+ confset_free(&lc);
+ confset_free(&rc);
fclose(fp);
return;
}
- c = tc;
}
- if (conf_parseline(f, lineno, line, &c[nc]) == -1)
+ if (conf_parseline(f, lineno, line, confset_get(cs),
+ cs == &lc) == -1)
continue;
- nc++;
+ confset_add(cs);
}
+
fclose(fp);
- qsort(c, nc, sizeof(*c), conf_sort);
+ confset_sort(&lc);
+ confset_sort(&rc);
- tc = conf;
- nconf = nc;
- conf = c;
- free(tc);
+ confset_replace(&rconf, &rc);
+ confset_replace(&lconf, &lc);
if (debug) {
- char buf[BUFSIZ];
- (*lfun)(LOG_DEBUG,
- "%20.20s\ttype\tproto\towner\tname\tnfail\tduration",
- "target");
- for (nc = 0; nc < nconf; nc++)
- (*lfun)(LOG_DEBUG, "%s",
- conf_print(buf, sizeof(buf), "", "\t", &c[nc]));
+ confset_list(&lconf, "local", "target");
+ confset_list(&rconf, "remote", "source");
}
}
Index: src/external/bsd/blacklist/bin/blacklistd.8
diff -u src/external/bsd/blacklist/bin/blacklistd.8:1.8 src/external/bsd/blacklist/bin/blacklistd.8:1.9
--- src/external/bsd/blacklist/bin/blacklistd.8:1.8 Sun Jan 25 18:07:16 2015
+++ src/external/bsd/blacklist/bin/blacklistd.8 Tue Jan 27 14:40:36 2015
@@ -1,4 +1,4 @@
-.\" $NetBSD: blacklistd.8,v 1.8 2015/01/25 23:07:16 wiz Exp $
+.\" $NetBSD: blacklistd.8,v 1.9 2015/01/27 19:40:36 christos Exp $
.\"
.\" Copyright (c) 2015 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -32,7 +32,6 @@
.Os
.Sh NAME
.Nm blacklistd ,
-.Nm blacklistd.conf
.Nd block and release ports on demand to avoid DoS abuse
.Sh SYNOPSIS
.Nm
@@ -40,8 +39,9 @@
.Op Fl C Ar controlprog
.Op Fl c Ar configfile
.Op Fl D Ar dbfile
-.Op Fl r Ar rulename
.Op Fl P Ar sockpathsfile
+.Op Fl r Ar rulename
+.Op Fl s Ar sockpath
.Op Fl t Ar timeout
.Sh DESCRIPTION
.Nm
@@ -51,7 +51,10 @@ that listens to a sockets at paths speci
.Ar sockpathsfile
for notifications from other daemons about successful or failed connection
attempts.
-If no such file is specified, then it only listens to the default socket
+If no such file is specified, then it only listens to the socket path
+specified by
+.Ar sockspath
+or if that is not specified to
.Pa /var/run/blsock .
Each notification contains an (action, port, protocol, address, owner) tuple
that identifies the remote connection and the action.
@@ -69,7 +72,7 @@ control script
.Ar controlprog
is invoked with arguments:
.Bd -literal -offset indent
-control add <rulename> <proto> <port> <address>
+control add <rulename> <proto> <address> <mask> <port>
.Ed
.Pp
and should invoke a packet filter command to block the connection
@@ -87,7 +90,7 @@ If the action is
.Dq remove
Then the same control script is invoked as:
.Bd -literal -offset indent
-control rem <rulename> <proto> <port> <address> <id>
+control add <rulename> <proto> <address> <mask> <port>
.Ed
.Pp
where
@@ -116,31 +119,6 @@ seconds (default
.Dv 15 )
and removes entries and block rules using the control program as necessary.
.Pp
-The configuration file contains one tuple per line, and is similar to
-.Xr inetd.conf 5 .
-There must be an entry for each field of the configuration file, with
-entries for each field separated by a tab or a space.
-Comments are denoted by a
-.Dq #
-at the beginning of a line.
-There must be an entry for each field; entries can be numeric or symbolic,
-where appropriate
-.Dv ( service ,
-.Dv user )
-and can be
-.Dq *
-for all fields.
-The fields of the configuration file are as follows:
-.Bd -literal -offset indent
-[address|interface:]service
-socket-type
-protocol
-user
-rulename
-nfail
-duration
-.Ed
-.Pp
Normally,
.Nm
disassociates itself from the terminal and writes messages to
Index: src/external/bsd/blacklist/bin/blacklistd.c
diff -u src/external/bsd/blacklist/bin/blacklistd.c:1.29 src/external/bsd/blacklist/bin/blacklistd.c:1.30
--- src/external/bsd/blacklist/bin/blacklistd.c:1.29 Sun Jan 25 15:59:39 2015
+++ src/external/bsd/blacklist/bin/blacklistd.c Tue Jan 27 14:40:36 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: blacklistd.c,v 1.29 2015/01/25 20:59:39 christos Exp $ */
+/* $NetBSD: blacklistd.c,v 1.30 2015/01/27 19:40:36 christos Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
#include "config.h"
#endif
#include <sys/cdefs.h>
-__RCSID("$NetBSD: blacklistd.c,v 1.29 2015/01/25 20:59:39 christos Exp $");
+__RCSID("$NetBSD: blacklistd.c,v 1.30 2015/01/27 19:40:36 christos Exp $");
#include <sys/types.h>
#include <sys/socket.h>
@@ -71,7 +71,7 @@ __RCSID("$NetBSD: blacklistd.c,v 1.29 20
static const char *configfile = _PATH_BLCONF;
static DB *state;
static const char *dbfile = _PATH_BLSTATE;
-static sig_atomic_t rconf;
+static sig_atomic_t readconf;
static sig_atomic_t done;
static int vflag;
@@ -90,7 +90,7 @@ sigusr2(int n __unused)
static void
sighup(int n __unused)
{
- rconf++;
+ readconf++;
}
static void
@@ -106,7 +106,7 @@ usage(int c)
warnx("Unknown option `%c'", (char)c);
fprintf(stderr, "Usage: %s [-vdf] [-c <config>] [-r <rulename>] "
"[-P <sockpathsfile>] [-C <controlprog>] [-D <dbfile>] "
- "[-t <timeout>]\n", getprogname());
+ "[-s <sockpath>] [-t <timeout>]\n", getprogname());
exit(EXIT_FAILURE);
}
@@ -193,13 +193,13 @@ process(bl_t bl)
(unsigned long)bi->bi_gid);
}
- if (conf_find(bi->bi_fd, bi->bi_uid, &c) == NULL) {
+ if (conf_find(bi->bi_fd, bi->bi_uid, &rss, &c) == NULL) {
(*lfun)(LOG_DEBUG, "no rule matched");
goto out;
}
- if (state_get(state, &rss, &c, &dbi) == -1)
+ if (state_get(state, &c, &dbi) == -1)
goto out;
if (debug) {
@@ -224,15 +224,14 @@ process(bl_t bl)
(*lfun)(LOG_ERR, "rule exists %s", dbi.id);
}
if (c.c_nfail != -1 && dbi.count >= c.c_nfail) {
- int res = run_change("add", &c, &rss,
- dbi.id, sizeof(dbi.id));
+ int res = run_change("add", &c, dbi.id, sizeof(dbi.id));
if (res == -1)
goto out;
sockaddr_snprintf(rbuf, sizeof(rbuf), "%a",
(void *)&rss);
(*lfun)(LOG_INFO,
- "blocked %s at port %d for %d seconds",
- rbuf, c.c_port, c.c_duration);
+ "blocked %s/%d:%d for %d seconds",
+ rbuf, c.c_lmask, c.c_port, c.c_duration);
}
break;
@@ -244,7 +243,7 @@ process(bl_t bl)
default:
(*lfun)(LOG_ERR, "unknown message %d", bi->bi_type);
}
- if (state_put(state, &rss, &c, &dbi) == -1)
+ if (state_put(state, &c, &dbi) == -1)
goto out;
out:
close(bi->bi_fd);
@@ -280,7 +279,7 @@ update(void)
return;
}
- for (n = 0, f = 1; state_iterate(state, &ss, &c, &dbi, f) == 1;
+ for (n = 0, f = 1; state_iterate(state, &c, &dbi, f) == 1;
f = 0, n++)
{
time_t when = c.c_duration + dbi.last;
@@ -297,13 +296,13 @@ update(void)
if (c.c_duration == -1 || when >= ts.tv_sec)
continue;
if (dbi.id[0]) {
- run_change("rem", &c, &ss, dbi.id, 0);
+ run_change("rem", &c, dbi.id, 0);
sockaddr_snprintf(buf, sizeof(buf), "%a", (void *)&ss);
syslog(LOG_INFO,
- "released %s at port %d after %d seconds",
- buf, c.c_port, c.c_duration);
+ "released %s/%d:%d after %d seconds",
+ buf, c.c_lmask, c.c_port, c.c_duration);
}
- state_del(state, &ss, &c);
+ state_del(state, &c);
}
}
@@ -334,15 +333,16 @@ int
main(int argc, char *argv[])
{
int c, tout, flags, reset;
- const char *spath;
+ const char *spath, *blsock;
setprogname(argv[0]);
spath = NULL;
+ blsock = _PATH_BLSOCK;
reset = 0;
tout = 0;
flags = O_RDWR|O_EXCL|O_CLOEXEC;
- while ((c = getopt(argc, argv, "C:c:D:dfr:P:t:v")) != -1) {
+ while ((c = getopt(argc, argv, "C:c:D:dfr:P:s:t:v")) != -1) {
switch (c) {
case 'C':
controlprog = optarg;
@@ -359,11 +359,14 @@ main(int argc, char *argv[])
case 'f':
reset++;
break;
+ case 'P':
+ spath = optarg;
+ break;
case 'r':
rulename = optarg;
break;
- case 'P':
- spath = optarg;
+ case 's':
+ blsock = optarg;
break;
case 't':
tout = atoi(optarg) * 1000;
@@ -401,8 +404,10 @@ main(int argc, char *argv[])
update_interfaces();
conf_parse(configfile);
if (reset) {
- for (size_t i = 0; i < nconf; i++)
- run_flush(&conf[i]);
+ for (size_t i = 0; i < rconf.cs_n; i++)
+ run_flush(&rconf.cs_c[i]);
+ for (size_t i = 0; i < lconf.cs_n; i++)
+ run_flush(&lconf.cs_c[i]);
flags |= O_TRUNC;
}
@@ -412,7 +417,7 @@ main(int argc, char *argv[])
size_t maxfd = 0;
if (spath == NULL)
- addfd(&pfd, &bl, &nfd, &maxfd, _PATH_BLSOCK);
+ addfd(&pfd, &bl, &nfd, &maxfd, blsock);
else {
FILE *fp = fopen(spath, "r");
char *line;
@@ -438,8 +443,8 @@ main(int argc, char *argv[])
}
for (size_t t = 0; !done; t++) {
- if (rconf) {
- rconf = 0;
+ if (readconf) {
+ readconf = 0;
conf_parse(configfile);
}
switch (poll(pfd, (nfds_t)nfd, tout)) {
Index: src/external/bsd/blacklist/bin/conf.h
diff -u src/external/bsd/blacklist/bin/conf.h:1.5 src/external/bsd/blacklist/bin/conf.h:1.6
--- src/external/bsd/blacklist/bin/conf.h:1.5 Wed Jan 21 14:24:03 2015
+++ src/external/bsd/blacklist/bin/conf.h Tue Jan 27 14:40:36 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: conf.h,v 1.5 2015/01/21 19:24:03 christos Exp $ */
+/* $NetBSD: conf.h,v 1.6 2015/01/27 19:40:36 christos Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -31,24 +31,35 @@
#ifndef _CONF_H
#define _CONF_H
+#include <sys/socket.h>
+
struct conf {
struct sockaddr_storage c_ss;
+ int c_lmask;
int c_port;
int c_proto;
int c_family;
int c_uid;
int c_nfail;
char c_name[128];
+ int c_rmask;
int c_duration;
};
+struct confset {
+ struct conf *cs_c;
+ size_t cs_n;
+ size_t cs_m;
+};
+
#define CONFNAMESZ sizeof(((struct conf *)0)->c_name)
__BEGIN_DECLS
const char *conf_print(char *, size_t, const char *, const char *,
const struct conf *);
void conf_parse(const char *);
-const struct conf *conf_find(int, uid_t, struct conf *);
+const struct conf *conf_find(int, uid_t, const struct sockaddr_storage *,
+ struct conf *);
__END_DECLS
#endif /* _CONF_H */
Index: src/external/bsd/blacklist/bin/support.c
diff -u src/external/bsd/blacklist/bin/support.c:1.5 src/external/bsd/blacklist/bin/support.c:1.6
--- src/external/bsd/blacklist/bin/support.c:1.5 Sat Jan 24 01:05:08 2015
+++ src/external/bsd/blacklist/bin/support.c Tue Jan 27 14:40:37 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: support.c,v 1.5 2015/01/24 06:05:08 christos Exp $ */
+/* $NetBSD: support.c,v 1.6 2015/01/27 19:40:37 christos Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
#endif
#include <sys/cdefs.h>
-__RCSID("$NetBSD: support.c,v 1.5 2015/01/24 06:05:08 christos Exp $");
+__RCSID("$NetBSD: support.c,v 1.6 2015/01/27 19:40:37 christos Exp $");
#include <time.h>
#include <string.h>
@@ -70,7 +70,7 @@ vdlog(int level __unused, const char *fm
{
char buf[BUFSIZ];
- fprintf(stderr, "%s: ", getprogname());
+// fprintf(stderr, "%s: ", getprogname());
vfprintf(stderr, expandm(buf, sizeof(buf), fmt), ap);
fprintf(stderr, "\n");
}
Index: src/external/bsd/blacklist/bin/internal.c
diff -u src/external/bsd/blacklist/bin/internal.c:1.4 src/external/bsd/blacklist/bin/internal.c:1.5
--- src/external/bsd/blacklist/bin/internal.c:1.4 Sun Jan 25 15:59:39 2015
+++ src/external/bsd/blacklist/bin/internal.c Tue Jan 27 14:40:37 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: internal.c,v 1.4 2015/01/25 20:59:39 christos Exp $ */
+/* $NetBSD: internal.c,v 1.5 2015/01/27 19:40:37 christos Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -33,16 +33,16 @@
#endif
#include <sys/cdefs.h>
-__RCSID("$NetBSD: internal.c,v 1.4 2015/01/25 20:59:39 christos Exp $");
+__RCSID("$NetBSD: internal.c,v 1.5 2015/01/27 19:40:37 christos Exp $");
#include <stdio.h>
#include <syslog.h>
+#include "conf.h"
#include "internal.h"
int debug;
const char *rulename = "blacklistd";
const char *controlprog = _PATH_BLCONTROL;
-struct conf *conf;
+struct confset lconf, rconf;
struct ifaddrs *ifas;
-size_t nconf;
void (*lfun)(int, const char *, ...) = syslog;
Index: src/external/bsd/blacklist/bin/run.h
diff -u src/external/bsd/blacklist/bin/run.h:1.4 src/external/bsd/blacklist/bin/run.h:1.5
--- src/external/bsd/blacklist/bin/run.h:1.4 Wed Jan 21 23:13:04 2015
+++ src/external/bsd/blacklist/bin/run.h Tue Jan 27 14:40:37 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: run.h,v 1.4 2015/01/22 04:13:04 christos Exp $ */
+/* $NetBSD: run.h,v 1.5 2015/01/27 19:40:37 christos Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -35,8 +35,7 @@ __BEGIN_DECLS
struct conf;
void run_flush(const struct conf *);
struct sockaddr_storage;
-int run_change(const char *, const struct conf *,
- const struct sockaddr_storage *, char *, size_t);
+int run_change(const char *, const struct conf *, char *, size_t);
__END_DECLS
#endif /* _RUN_H */
Index: src/external/bsd/blacklist/bin/state.h
diff -u src/external/bsd/blacklist/bin/state.h:1.4 src/external/bsd/blacklist/bin/state.h:1.5
--- src/external/bsd/blacklist/bin/state.h:1.4 Sat Jan 24 02:46:20 2015
+++ src/external/bsd/blacklist/bin/state.h Tue Jan 27 14:40:37 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: state.h,v 1.4 2015/01/24 07:46:20 christos Exp $ */
+/* $NetBSD: state.h,v 1.5 2015/01/27 19:40:37 christos Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -52,13 +52,10 @@ struct conf;
DB *state_open(const char *, int, mode_t);
int state_close(DB *);
-int state_get(DB *, const struct sockaddr_storage *, const struct conf *,
- struct dbinfo *);
-int state_put(DB *, const struct sockaddr_storage *, const struct conf *,
- const struct dbinfo *);
-int state_del(DB *, const struct sockaddr_storage *, const struct conf *);
-int state_iterate(DB *, struct sockaddr_storage *, struct conf *,
- struct dbinfo *, unsigned int);
+int state_get(DB *, const struct conf *, struct dbinfo *);
+int state_put(DB *, const struct conf *, const struct dbinfo *);
+int state_del(DB *, const struct conf *);
+int state_iterate(DB *, struct conf *, struct dbinfo *, unsigned int);
int state_sync(DB *);
__END_DECLS
Index: src/external/bsd/blacklist/bin/internal.h
diff -u src/external/bsd/blacklist/bin/internal.h:1.11 src/external/bsd/blacklist/bin/internal.h:1.12
--- src/external/bsd/blacklist/bin/internal.h:1.11 Sun Jan 25 15:59:39 2015
+++ src/external/bsd/blacklist/bin/internal.h Tue Jan 27 14:40:37 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: internal.h,v 1.11 2015/01/25 20:59:39 christos Exp $ */
+/* $NetBSD: internal.h,v 1.12 2015/01/27 19:40:37 christos Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -41,13 +41,13 @@
#define _PATH_BLSTATE "/var/db/blacklistd.db"
#endif
-extern struct conf *conf;
-extern size_t nconf;
+extern struct confset rconf, lconf;
extern int debug;
extern const char *rulename;
extern const char *controlprog;
extern struct ifaddrs *ifas;
-void (*lfun)(int, const char *, ...);
+void (*lfun)(int, const char *, ...)
+ __attribute__((__format__(__printf__, 2, 3)));
#endif /* _INTERNAL_H */
Index: src/external/bsd/blacklist/bin/run.c
diff -u src/external/bsd/blacklist/bin/run.c:1.11 src/external/bsd/blacklist/bin/run.c:1.12
--- src/external/bsd/blacklist/bin/run.c:1.11 Thu Jan 22 12:49:41 2015
+++ src/external/bsd/blacklist/bin/run.c Tue Jan 27 14:40:37 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: run.c,v 1.11 2015/01/22 17:49:41 christos Exp $ */
+/* $NetBSD: run.c,v 1.12 2015/01/27 19:40:37 christos Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
#endif
#include <sys/cdefs.h>
-__RCSID("$NetBSD: run.c,v 1.11 2015/01/22 17:49:41 christos Exp $");
+__RCSID("$NetBSD: run.c,v 1.12 2015/01/27 19:40:37 christos Exp $");
#include <stdio.h>
#ifdef HAVE_UTIL_H
@@ -109,11 +109,10 @@ run_flush(const struct conf *c)
}
int
-run_change(const char *how, const struct conf *c,
- const struct sockaddr_storage *ss, char *id, size_t len)
+run_change(const char *how, const struct conf *c, char *id, size_t len)
{
const char *prname;
- char poname[64], adname[128], *rv;
+ char poname[64], adname[128], maskname[32], *rv;
size_t off;
switch (c->c_proto) {
@@ -129,9 +128,10 @@ run_change(const char *how, const struct
}
snprintf(poname, sizeof(poname), "%d", c->c_port);
- sockaddr_snprintf(adname, sizeof(adname), "%a", (const void *)ss);
+ snprintf(maskname, sizeof(maskname), "%d", c->c_lmask);
+ sockaddr_snprintf(adname, sizeof(adname), "%a", (const void *)&c->c_ss);
- rv = run(how, c->c_name, prname, adname, poname, id, NULL);
+ rv = run(how, c->c_name, prname, adname, maskname, poname, id, NULL);
if (rv == NULL)
return -1;
if (len != 0) {
Index: src/external/bsd/blacklist/bin/state.c
diff -u src/external/bsd/blacklist/bin/state.c:1.14 src/external/bsd/blacklist/bin/state.c:1.15
--- src/external/bsd/blacklist/bin/state.c:1.14 Sun Jan 25 15:50:30 2015
+++ src/external/bsd/blacklist/bin/state.c Tue Jan 27 14:40:37 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: state.c,v 1.14 2015/01/25 20:50:30 christos Exp $ */
+/* $NetBSD: state.c,v 1.15 2015/01/27 19:40:37 christos Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
#endif
#include <sys/cdefs.h>
-__RCSID("$NetBSD: state.c,v 1.14 2015/01/25 20:50:30 christos Exp $");
+__RCSID("$NetBSD: state.c,v 1.15 2015/01/27 19:40:37 christos Exp $");
#include <sys/types.h>
#include <sys/socket.h>
@@ -88,13 +88,18 @@ state_open(const char *dbname, int flags
return db;
}
-struct dbkey {
- struct conf c;
- struct sockaddr_storage ss;
-};
+static int
+state_sizecheck(const DBT *t)
+{
+ if (sizeof(struct conf) == t->size)
+ return 0;
+ (*lfun)(LOG_ERR, "Key size mismatch %zu != %zu", sizeof(struct conf),
+ t->size);
+ return -1;
+}
static void
-dumpkey(const struct dbkey *k)
+dumpkey(const struct conf *k)
{
char buf[10240];
size_t z;
@@ -112,46 +117,17 @@ dumpkey(const struct dbkey *k)
(*lfun)(LOG_DEBUG, "%s", buf);
}
-static void
-makekey(struct dbkey *k, const struct sockaddr_storage *ss,
- const struct conf *c)
-{
- in_port_t port;
-
- memset(k, 0, sizeof(*k));
- port = htons((in_port_t)c->c_port);
- k->c = *c;
- k->ss = *ss;
- switch (k->ss.ss_family) {
- case AF_INET6:
- ((struct sockaddr_in6 *)&k->ss)->sin6_port = port;
- break;
- case AF_INET:
- ((struct sockaddr_in *)&k->ss)->sin_port = port;
- break;
- default:
- (*lfun)(LOG_ERR, "%s: bad family %d", __func__,
- k->ss.ss_family);
- break;
- }
- if (debug > 1)
- dumpkey(k);
-}
-
int
-state_del(DB *db, const struct sockaddr_storage *ss, const struct conf *c)
+state_del(DB *db, const struct conf *c)
{
- struct dbkey key;
int rv;
DBT k;
if (db == NULL)
return -1;
- makekey(&key, ss, c);
-
- k.data = &key;
- k.size = sizeof(key);
+ k.data = __UNCONST(c);
+ k.size = sizeof(*c);
switch (rv = (*db->del)(db, &k, 0)) {
case 0:
@@ -168,20 +144,16 @@ state_del(DB *db, const struct sockaddr_
}
int
-state_get(DB *db, const struct sockaddr_storage *ss, const struct conf *c,
- struct dbinfo *dbi)
+state_get(DB *db, const struct conf *c, struct dbinfo *dbi)
{
- struct dbkey key;
int rv;
DBT k, v;
if (db == NULL)
return -1;
- makekey(&key, ss, c);
-
- k.data = &key;
- k.size = sizeof(key);
+ k.data = __UNCONST(c);
+ k.size = sizeof(*c);
switch (rv = (*db->get)(db, &k, &v, 0)) {
case 0:
@@ -200,20 +172,16 @@ state_get(DB *db, const struct sockaddr_
}
int
-state_put(DB *db, const struct sockaddr_storage *ss, const struct conf *c,
- const struct dbinfo *dbi)
+state_put(DB *db, const struct conf *c, const struct dbinfo *dbi)
{
- struct dbkey key;
int rv;
DBT k, v;
if (db == NULL)
return -1;
- makekey(&key, ss, c);
-
- k.data = &key;
- k.size = sizeof(key);
+ k.data = __UNCONST(c);
+ k.size = sizeof(*c);
v.data = __UNCONST(dbi);
v.size = sizeof(*dbi);
@@ -234,10 +202,8 @@ state_put(DB *db, const struct sockaddr_
}
int
-state_iterate(DB *db, struct sockaddr_storage *ss, struct conf *c,
- struct dbinfo *dbi, unsigned int first)
+state_iterate(DB *db, struct conf *c, struct dbinfo *dbi, unsigned int first)
{
- struct dbkey *kp;
int rv;
DBT k, v;
@@ -248,11 +214,11 @@ state_iterate(DB *db, struct sockaddr_st
switch (rv = (*db->seq)(db, &k, &v, first)) {
case 0:
- kp = k.data;
- *ss = kp->ss;
- *c = kp->c;
+ if (state_sizecheck(&k) == -1)
+ return -1;
+ memcpy(c, k.data, sizeof(*c));
if (debug > 2)
- dumpkey(kp);
+ dumpkey(c);
memcpy(dbi, v.data, sizeof(*dbi));
if (debug > 1)
(*lfun)(LOG_DEBUG, "%s: returns %d", __func__, rv);
Index: src/external/bsd/blacklist/etc/blacklistd.conf
diff -u src/external/bsd/blacklist/etc/blacklistd.conf:1.2 src/external/bsd/blacklist/etc/blacklistd.conf:1.3
--- src/external/bsd/blacklist/etc/blacklistd.conf:1.2 Fri Jan 23 17:34:00 2015
+++ src/external/bsd/blacklist/etc/blacklistd.conf Tue Jan 27 14:40:37 2015
@@ -1,12 +1,18 @@
# Blacklist rule
-# Port type protocol owner name nfail disable
-ssh stream tcp * * 3 6h
-ssh stream tcp6 * * 3 6h
-ftp stream tcp * * 3 6h
-ftp stream tcp6 * * 3 6h
-domain stream tcp named * 3 12h
-domain dgram udp named * 3 12h
-domain stream tcp6 named * 3 12h
-domain dgram udp6 named * 3 12h
-6161 stream tcp6 christos * 2 10m
-* * * * * 3 60
+# adr/mask:port type proto owner name nfail disable
+[local]
+ssh stream tcp * * 3 6h
+ssh stream tcp6 * * 3 6h
+ftp stream tcp * * 3 6h
+ftp stream tcp6 * * 3 6h
+domain stream tcp named * 3 12h
+domain dgram udp named * 3 12h
+domain stream tcp6 named * 3 12h
+domain dgram udp6 named * 3 12h
+6161 stream tcp6 christos * 2 10m
+* * * * * 3 60
+
+# adr/mask:port type proto owner name nfail disable
+bge0 stream tcp * =/24 = =
+129.168.0.0/16 * * * = * *
+default stream tcp * = = =
Index: src/external/bsd/blacklist/libexec/blacklistd-helper
diff -u src/external/bsd/blacklist/libexec/blacklistd-helper:1.1 src/external/bsd/blacklist/libexec/blacklistd-helper:1.2
--- src/external/bsd/blacklist/libexec/blacklistd-helper:1.1 Thu Jan 22 12:49:41 2015
+++ src/external/bsd/blacklist/libexec/blacklistd-helper Tue Jan 27 14:40:37 2015
@@ -1,19 +1,33 @@
#!/bin/sh
echo "run $@" 1>&2
-
+set -x
# $1 command
# $2 rulename
# $3 protocol
-# $4 address to
-# $5 port
-# $6 id
+# $4 address
+# $5 mask
+# $6 proto
+# $7 id
case "$1" in
add)
- exec /sbin/npfctl rule $2 add block in final proto $3 from $4 to any port $5
+ # GRR!
+# case $4 in
+# *:*)
+# case $5 in
+# 128) addr=$4;;
+# *) addr=$4/$5;;
+# esac;;
+# *)
+# case $5 in
+# 32) addr=$4;;
+# *) addr=$4/$5;;
+# esac;;
+# esac
+ exec /sbin/npfctl rule $2 add block in final proto $3 from $4/$5 to any port $6
;;
rem)
- exec /sbin/npfctl rule $2 rem-id $6
+ exec /sbin/npfctl rule $2 rem-id $7
;;
flush)
exec /sbin/npfctl rule $2 flush
Added files:
Index: src/external/bsd/blacklist/bin/blacklistd.conf.5
diff -u /dev/null src/external/bsd/blacklist/bin/blacklistd.conf.5:1.1
--- /dev/null Tue Jan 27 14:40:37 2015
+++ src/external/bsd/blacklist/bin/blacklistd.conf.5 Tue Jan 27 14:40:36 2015
@@ -0,0 +1,222 @@
+.\" $NetBSD: blacklistd.conf.5,v 1.1 2015/01/27 19:40:36 christos Exp $
+.\"
+.\" Copyright (c) 2015 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Christos Zoulas.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd January 25, 2015
+.Dt BLACKLISTD.CONF 5
+.Os
+.Sh NAME
+.Nm blacklistd.conf
+.Nd configuration file format for blacklistd
+.Sh DESCRIPTION
+The
+.Nm
+files contains configuration lines for
+.Xr blacklistd 8 .
+It contains one entry per line, and is similar to
+.Xr inetd.conf 5 .
+There must be an entry for each field of the configuration file, with
+entries for each field separated by a tab or a space.
+Comments are denoted by a
+.Dq #
+at the beginning of a line.
+.Pp
+There are two kinds of configuration lines,
+.Va local
+and
+.Va remote .
+By default, configuration lines are
+.Va local ,
+i.e. the address specified refers to the addresses on the local machine.
+To switch to between
+.Va local
+and
+.Va remote
+configuration lines you can specify the stanzas:
+.Dq [local]
+and
+.Dq [remote] .
+.Pp
+On
+.Va local
+and
+.Va remote
+lines
+.Dq *
+means use the default, or wildcard match.
+In addition, for
+.Va remote
+lines
+.Dq =
+means use the values from the matched
+.Va local
+configuration line.
+.Pp
+The first four fields,
+.Va location ,
+.Va type ,
+.Va proto ,
+and
+.Va owner
+are used to match the
+.Va local
+or
+.Va remote
+addresses whereas, the last 3 fields
+.Va name ,
+.Va nfail ,
+and
+.Va disable
+are used to modify the filtering action.
+.Pp
+The first field denotes the
+.Va location
+as an address, mask, and port.
+The syntax for the
+.Va location
+is:
+.Bd -literal -offset indent:
+ [<address>|<interface>][/<mask>][:<port>]
+.Ed
+.Pp
+The
+.Dv address
+can be an IPv4 address in numeric format, an IPv6 address
+in numeric format and enclosed by square brackets, or an interface name.
+Mask modifiers are not allowed on interfaces because interfaces
+have multiple address in different protocols where the mask has a different
+size.
+.Pp
+The
+.Dv mask
+is always numeric, but the
+.Dv port
+can be either numeric or symbolic.
+.Pp
+The second field is the socket
+.Va type :
+.Dv stream ,
+.Dv dgram ,
+or numeric.
+The third field is the
+.Va prococol :
+.Dv tcp ,
+.Dv udp ,
+.Dv tcp6 ,
+.Dv udp6 ,
+or numeric.
+The fourth file is the effective user (
+.Va owner )
+of the daemon process reporting the event,
+either as a username or a userid.
+.Pp
+The rest of the fields are controlling the behavior of the filter.
+.Pp
+The
+.Va name
+field, is the name of the packet filter rule to be used.
+If the
+.Va name
+starts with a
+.Dq - ,
+then the default rulename is prepended to the given name.
+If the
+.Dv name
+contains a
+.Dq / ,
+the remaining portion of the name is interpreted as the mask to be
+applied to the address specified in the rule, so one can block whole
+subnets for a single rule violation.
+.Pp
+The
+.Va nfail
+field contains the number of failed attempts before access is blocked,
+defaulting to
+.Dq *
+meaning never, and the last field
+.Va disable
+specifies the amount of time since the last access that the blocking
+rule should be active, defaulting to
+.Dq *
+meaning forever.
+The default unit for
+.Va disable
+is seconds, but one can specify suffixes for different units, such as
+.Dq m
+for minutes
+.Dq h
+for hours and
+.Dq d
+for days.
+.Pp
+Matching is done first by checking the
+.Va local
+rules one by one, from the most specific to the least specific.
+If a match is found, then the
+.Va remote
+rules are applied, and if a match is found the
+.Va name ,
+.Va nfail ,
+and
+.Va disable
+fields can be altered by the
+.Va remote
+rule that matched.
+.Pp
+The
+.Va remote
+rules can be used for whitelisting specific addresses, changing the mask
+size, or the rule that the packet filter uses, the number of failed attempts,
+or the blocked duration.
+.Sh FILES
+.Bl -tag -width /etc/blacklistd.conf -compact
+.It Pa /etc/blacklistd.conf
+Configuration file.
+.El
+.Sh EXAMPLES
+.Bd -literal -offset
+# Block ssh, after 3 attempts for 6 hours on the bnx0 interface
+[local]
+# location type proto owner name nfail duration
+bnx0:ssh * * * * 3 6h
+[remote]
+# Never block 1.2.3.4
+1.2.3.4:ssh * * * * * *
+# For addresses coming from 8.8.0.0/16 block class C networks instead
+# individual hosts, but keep the rest of the blocking parameters the same.
+8.8.0.0/16:ssh * * * /24 = =
+.Ed
+.Sh SEE ALSO
+.Xr blacklistd 8 ,
+.Xr blacklistctl 8
+.Sh HISTORY
+.Nm
+appeared in
+.Nx 8 .
+.Sh AUTHORS
+.An Christos Zoulas