Module Name: src
Committed By: rmind
Date: Mon Jan 2 21:49:51 UTC 2017
Modified Files:
src/sys/modules/npf: Makefile
src/sys/net/npf: files.npf npf_ctl.c npf_impl.h npf_os.c npf_tableset.c
npf_worker.c
Added Files:
src/sys/net/npf: npf_ifaddr.c
Log Message:
NPF: implement dynamic handling of interface addresses (the kernel part).
To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 src/sys/modules/npf/Makefile
cvs rdiff -u -r1.19 -r1.20 src/sys/net/npf/files.npf
cvs rdiff -u -r1.45 -r1.46 src/sys/net/npf/npf_ctl.c
cvs rdiff -u -r0 -r1.1 src/sys/net/npf/npf_ifaddr.c
cvs rdiff -u -r1.65 -r1.66 src/sys/net/npf/npf_impl.h
cvs rdiff -u -r1.2 -r1.3 src/sys/net/npf/npf_os.c \
src/sys/net/npf/npf_worker.c
cvs rdiff -u -r1.25 -r1.26 src/sys/net/npf/npf_tableset.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/modules/npf/Makefile
diff -u src/sys/modules/npf/Makefile:1.20 src/sys/modules/npf/Makefile:1.21
--- src/sys/modules/npf/Makefile:1.20 Wed Dec 28 13:50:55 2016
+++ src/sys/modules/npf/Makefile Mon Jan 2 21:49:51 2017
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.20 2016/12/28 13:50:55 christos Exp $
+# $NetBSD: Makefile,v 1.21 2017/01/02 21:49:51 rmind Exp $
#
# Public Domain.
#
@@ -13,7 +13,7 @@ SRCS= npf.c npf_alg.c npf_conf.c npf_ct
SRCS+= npf_bpf.c npf_if.c npf_inet.c npf_mbuf.c npf_nat.c
SRCS+= npf_ruleset.c npf_conn.c npf_conndb.c npf_rproc.c
SRCS+= npf_state.c npf_state_tcp.c npf_tableset.c
-SRCS+= lpm.c npf_sendpkt.c npf_worker.c npf_os.c
+SRCS+= lpm.c npf_sendpkt.c npf_worker.c npf_ifaddr.c npf_os.c
CPPFLAGS+= -DINET6
Index: src/sys/net/npf/files.npf
diff -u src/sys/net/npf/files.npf:1.19 src/sys/net/npf/files.npf:1.20
--- src/sys/net/npf/files.npf:1.19 Mon Dec 26 23:05:06 2016
+++ src/sys/net/npf/files.npf Mon Jan 2 21:49:51 2017
@@ -1,4 +1,4 @@
-# $NetBSD: files.npf,v 1.19 2016/12/26 23:05:06 christos Exp $
+# $NetBSD: files.npf,v 1.20 2017/01/02 21:49:51 rmind Exp $
#
# Public Domain.
#
@@ -11,7 +11,6 @@ defpseudo npf: ifnet
# Core
file net/npf/npf.c npf
-file net/npf/npf_os.c npf
file net/npf/npf_conf.c npf
file net/npf/npf_ctl.c npf
file net/npf/npf_handler.c npf
@@ -31,6 +30,9 @@ file net/npf/npf_alg.c npf
file net/npf/npf_sendpkt.c npf
file net/npf/npf_worker.c npf
+file net/npf/npf_os.c npf
+file net/npf/npf_ifaddr.c npf
+
# LPM
file net/npf/lpm.c npf
Index: src/sys/net/npf/npf_ctl.c
diff -u src/sys/net/npf/npf_ctl.c:1.45 src/sys/net/npf/npf_ctl.c:1.46
--- src/sys/net/npf/npf_ctl.c:1.45 Mon Dec 26 23:05:06 2016
+++ src/sys/net/npf/npf_ctl.c Mon Jan 2 21:49:51 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_ctl.c,v 1.45 2016/12/26 23:05:06 christos Exp $ */
+/* $NetBSD: npf_ctl.c,v 1.46 2017/01/02 21:49:51 rmind Exp $ */
/*-
* Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
#ifdef _KERNEL
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.45 2016/12/26 23:05:06 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.46 2017/01/02 21:49:51 rmind Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@@ -108,7 +108,7 @@ npf_mk_table_entries(npf_table_t *t, pro
}
static int __noinline
-npf_mk_tables(npf_tableset_t *tblset, prop_array_t tables,
+npf_mk_tables(npf_t *npf, npf_tableset_t *tblset, prop_array_t tables,
prop_dictionary_t errdict)
{
prop_object_iterator_t it;
@@ -160,9 +160,6 @@ npf_mk_tables(npf_tableset_t *tblset, pr
error = EINVAL;
break;
}
- if (type == NPF_TABLE_HASH) {
- size = 1024; /* XXX */
- }
/* Create and insert the table. */
t = npf_table_create(name, (u_int)tid, type, blob, size);
@@ -558,7 +555,7 @@ npfctl_load(npf_t *npf, u_long cmd, void
goto fail;
}
tblset = npf_tableset_create(nitems);
- error = npf_mk_tables(tblset, tables, errdict);
+ error = npf_mk_tables(npf, tblset, tables, errdict);
if (error) {
goto fail;
}
Index: src/sys/net/npf/npf_impl.h
diff -u src/sys/net/npf/npf_impl.h:1.65 src/sys/net/npf/npf_impl.h:1.66
--- src/sys/net/npf/npf_impl.h:1.65 Wed Dec 28 21:55:04 2016
+++ src/sys/net/npf/npf_impl.h Mon Jan 2 21:49:51 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_impl.h,v 1.65 2016/12/28 21:55:04 christos Exp $ */
+/* $NetBSD: npf_impl.h,v 1.66 2017/01/02 21:49:51 rmind Exp $ */
/*-
* Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
@@ -247,6 +247,10 @@ void npf_ifmap_flush(npf_t *);
u_int npf_ifmap_getid(npf_t *, const ifnet_t *);
const char * npf_ifmap_getname(npf_t *, const u_int);
+void npf_ifaddr_init(npf_t *);
+void npf_ifaddr_sync(npf_t *, ifnet_t *);
+void npf_ifaddr_flush(npf_t *, ifnet_t *);
+
/* Packet filter hooks. */
int npf_pfil_register(bool);
void npf_pfil_unregister(bool);
@@ -297,12 +301,14 @@ void npf_tableset_destroy(npf_tableset_
int npf_tableset_insert(npf_tableset_t *, npf_table_t *);
npf_table_t * npf_tableset_getbyname(npf_tableset_t *, const char *);
npf_table_t * npf_tableset_getbyid(npf_tableset_t *, u_int);
+npf_table_t * npf_tableset_swap(npf_tableset_t *, npf_table_t *);
void npf_tableset_reload(npf_t *, npf_tableset_t *, npf_tableset_t *);
int npf_tableset_export(npf_t *, const npf_tableset_t *, prop_array_t);
npf_table_t * npf_table_create(const char *, u_int, int, void *, size_t);
void npf_table_destroy(npf_table_t *);
+u_int npf_table_getid(npf_table_t *);
int npf_table_check(npf_tableset_t *, const char *, u_int, int);
int npf_table_insert(npf_table_t *, const int,
const npf_addr_t *, const npf_netmask_t);
Index: src/sys/net/npf/npf_os.c
diff -u src/sys/net/npf/npf_os.c:1.2 src/sys/net/npf/npf_os.c:1.3
--- src/sys/net/npf/npf_os.c:1.2 Mon Dec 26 23:59:47 2016
+++ src/sys/net/npf/npf_os.c Mon Jan 2 21:49:51 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_os.c,v 1.2 2016/12/26 23:59:47 rmind Exp $ */
+/* $NetBSD: npf_os.c,v 1.3 2017/01/02 21:49:51 rmind Exp $ */
/*-
* Copyright (c) 2009-2016 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
#ifdef _KERNEL
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_os.c,v 1.2 2016/12/26 23:59:47 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_os.c,v 1.3 2017/01/02 21:49:51 rmind Exp $");
#ifdef _KERNEL_OPT
#include "pf.h"
@@ -150,6 +150,7 @@ npf_init(void)
npf = npf_create(0, NULL, &kern_ifops);
npf_setkernctx(npf);
npf_pfil_register(true);
+ npf_ifaddr_init(npf);
#ifdef _MODULE
devmajor_t bmajor = NODEVMAJOR, cmajor = NODEVMAJOR;
@@ -196,7 +197,6 @@ npfattach(int nunits)
static int
npf_dev_open(dev_t dev, int flag, int mode, lwp_t *l)
{
-
/* Available only for super-user. */
if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_FIREWALL,
KAUTH_REQ_NETWORK_FIREWALL_FW, NULL, NULL, NULL)) {
@@ -354,13 +354,37 @@ npf_ifhook(void *arg, unsigned long cmd,
switch (cmd) {
case PFIL_IFNET_ATTACH:
npf_ifmap_attach(npf, ifp);
+ npf_ifaddr_sync(npf, ifp);
break;
case PFIL_IFNET_DETACH:
npf_ifmap_detach(npf, ifp);
+ npf_ifaddr_flush(npf, ifp);
break;
}
}
+static void
+npf_ifaddrhook(void *arg, u_long cmd, void *arg2)
+{
+ npf_t *npf = npf_getkernctx();
+ struct ifaddr *ifa = arg2;
+
+ switch (cmd) {
+ case SIOCSIFADDR:
+ case SIOCAIFADDR:
+ case SIOCDIFADDR:
+#ifdef INET6
+ case SIOCSIFADDR_IN6:
+ case SIOCAIFADDR_IN6:
+ case SIOCDIFADDR_IN6:
+#endif
+ break;
+ default:
+ return;
+ }
+ npf_ifaddr_sync(npf, ifa->ifa_ifp);
+}
+
/*
* npf_pfil_register: register pfil(9) hooks.
*/
@@ -380,7 +404,13 @@ npf_pfil_register(bool init)
error = ENOENT;
goto out;
}
- error = pfil_add_ihook(npf_ifhook, NULL, PFIL_IFNET, npf_ph_if);
+
+ error = pfil_add_ihook(npf_ifhook, NULL,
+ PFIL_IFNET, npf_ph_if);
+ KASSERT(error == 0);
+
+ error = pfil_add_ihook(npf_ifaddrhook, NULL,
+ PFIL_IFADDR, npf_ph_if);
KASSERT(error == 0);
}
if (init) {
@@ -432,7 +462,10 @@ npf_pfil_unregister(bool fini)
KERNEL_LOCK(1, NULL);
if (fini && npf_ph_if) {
- (void)pfil_remove_ihook(npf_ifhook, NULL, PFIL_IFNET, npf_ph_if);
+ (void)pfil_remove_ihook(npf_ifhook, NULL,
+ PFIL_IFNET, npf_ph_if);
+ (void)pfil_remove_ihook(npf_ifaddrhook, NULL,
+ PFIL_IFADDR, npf_ph_if);
}
if (npf_ph_inet) {
(void)pfil_remove_hook(npfkern_packet_handler, npf,
Index: src/sys/net/npf/npf_worker.c
diff -u src/sys/net/npf/npf_worker.c:1.2 src/sys/net/npf/npf_worker.c:1.3
--- src/sys/net/npf/npf_worker.c:1.2 Mon Dec 26 23:05:06 2016
+++ src/sys/net/npf/npf_worker.c Mon Jan 2 21:49:51 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_worker.c,v 1.2 2016/12/26 23:05:06 christos Exp $ */
+/* $NetBSD: npf_worker.c,v 1.3 2017/01/02 21:49:51 rmind Exp $ */
/*-
* Copyright (c) 2010-2015 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
#ifdef _KERNEL
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_worker.c,v 1.2 2016/12/26 23:05:06 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_worker.c,v 1.3 2017/01/02 21:49:51 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -73,9 +73,8 @@ npf_worker_sysinit(unsigned nworkers)
mutex_init(&wrk->worker_lock, MUTEX_DEFAULT, IPL_SOFTNET);
cv_init(&wrk->worker_cv, "npfgccv");
- if (kthread_create(PRI_NONE, KTHREAD_MPSAFE |
- KTHREAD_MUSTJOIN, NULL, npf_worker, wrk, &wrk->worker_lwp,
- "npfgc-%u", i)) {
+ if (kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN,
+ NULL, npf_worker, wrk, &wrk->worker_lwp, "npfgc-%u", i)) {
npf_worker_sysfini();
return ENOMEM;
}
Index: src/sys/net/npf/npf_tableset.c
diff -u src/sys/net/npf/npf_tableset.c:1.25 src/sys/net/npf/npf_tableset.c:1.26
--- src/sys/net/npf/npf_tableset.c:1.25 Mon Dec 26 23:05:06 2016
+++ src/sys/net/npf/npf_tableset.c Mon Jan 2 21:49:51 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_tableset.c,v 1.25 2016/12/26 23:05:06 christos Exp $ */
+/* $NetBSD: npf_tableset.c,v 1.26 2017/01/02 21:49:51 rmind Exp $ */
/*-
* Copyright (c) 2009-2016 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
#ifdef _KERNEL
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.25 2016/12/26 23:05:06 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.26 2017/01/02 21:49:51 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -183,6 +183,21 @@ npf_tableset_insert(npf_tableset_t *ts,
return error;
}
+npf_table_t *
+npf_tableset_swap(npf_tableset_t *ts, npf_table_t *newt)
+{
+ const u_int tid = newt->t_id;
+ npf_table_t *oldt = ts->ts_map[tid];
+
+ KASSERT(tid < ts->ts_nitems);
+ KASSERT(oldt->t_id == newt->t_id);
+
+ newt->t_refcnt = oldt->t_refcnt;
+ oldt->t_refcnt = 0;
+
+ return atomic_swap_ptr(&ts->ts_map[tid], newt);
+}
+
/*
* npf_tableset_getbyname: look for a table in the set given the name.
*/
@@ -354,7 +369,8 @@ npf_table_create(const char *name, u_int
LIST_INIT(&t->t_list);
break;
case NPF_TABLE_HASH:
- t->t_hashl = hashinit(1024, HASH_LIST, true, &t->t_hashmask);
+ size = MIN(size, 128);
+ t->t_hashl = hashinit(size, HASH_LIST, true, &t->t_hashmask);
if (t->t_hashl == NULL) {
goto out;
}
@@ -409,6 +425,12 @@ npf_table_destroy(npf_table_t *t)
kmem_free(t, sizeof(npf_table_t));
}
+u_int
+npf_table_getid(npf_table_t *t)
+{
+ return t->t_id;
+}
+
/*
* npf_table_check: validate the name, ID and type.
*/
Added files:
Index: src/sys/net/npf/npf_ifaddr.c
diff -u /dev/null src/sys/net/npf/npf_ifaddr.c:1.1
--- /dev/null Mon Jan 2 21:49:51 2017
+++ src/sys/net/npf/npf_ifaddr.c Mon Jan 2 21:49:51 2017
@@ -0,0 +1,179 @@
+/* $NetBSD: npf_ifaddr.c,v 1.1 2017/01/02 21:49:51 rmind Exp $ */
+
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Mindaugas Rasiukevicius.
+ *
+ * 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.
+ */
+
+/*
+ * NPF network interface handling module.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: npf_ifaddr.c,v 1.1 2017/01/02 21:49:51 rmind Exp $");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/kmem.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet6/in6_var.h>
+
+#include "npf_impl.h"
+
+void
+npf_ifaddr_init(npf_t *npf)
+{
+ ifnet_t *ifp;
+
+ KERNEL_LOCK(1, NULL);
+ IFNET_LOCK();
+ IFNET_WRITER_FOREACH(ifp) {
+ npf_ifaddr_sync(npf, ifp);
+ }
+ IFNET_UNLOCK();
+ KERNEL_UNLOCK_ONE(NULL);
+}
+
+static npf_table_t *
+lookup_ifnet_table(npf_t *npf, ifnet_t *ifp)
+{
+ const npf_ifops_t *ifops = npf->ifops;
+ char tname[NPF_TABLE_MAXNAMELEN];
+ npf_tableset_t *ts;
+ const char *ifname;
+ npf_table_t *t;
+ u_int tid;
+
+ /* Get the interface name and prefix it. */
+ ifname = ifops->getname(ifp);
+ snprintf(tname, sizeof(tname), ".ifnet-%s", ifname);
+
+ KERNEL_LOCK(1, NULL);
+ npf_config_enter(npf);
+ ts = npf_config_tableset(npf);
+
+ /*
+ * Check whether this interface is of any interest to us.
+ */
+ t = npf_tableset_getbyname(ts, tname);
+ if (!t) {
+ goto out;
+ }
+ tid = npf_table_getid(t);
+
+ /* Create a new NPF table for the interface. */
+ t = npf_table_create(tname, tid, NPF_TABLE_HASH, NULL, 16);
+ if (!t) {
+ goto out;
+ }
+ return t;
+out:
+ npf_config_exit(npf);
+ KERNEL_UNLOCK_ONE(NULL);
+ return NULL;
+}
+
+static void
+replace_ifnet_table(npf_t *npf, npf_table_t *newt)
+{
+ npf_tableset_t *ts = npf_config_tableset(npf);
+ npf_table_t *oldt;
+
+ KERNEL_UNLOCK_ONE(NULL);
+
+ /*
+ * Finally, swap the tables and issue a sync barrier.
+ */
+ oldt = npf_tableset_swap(ts, newt);
+ npf_config_sync(npf);
+ npf_config_exit(npf);
+
+ /* At this point, it is safe to destroy the old table. */
+ npf_table_destroy(oldt);
+}
+
+void
+npf_ifaddr_sync(npf_t *npf, ifnet_t *ifp)
+{
+ npf_table_t *t;
+ struct ifaddr *ifa;
+
+ /*
+ * First, check whether this interface is of any interest to us.
+ *
+ * => Acquires npf-config-lock and kernel-lock on success.
+ */
+ t = lookup_ifnet_table(npf, ifp);
+ if (!t)
+ return;
+
+ /*
+ * Populate the table with the interface addresses.
+ * Note: currently, this list is protected by the kernel-lock.
+ */
+ IFADDR_FOREACH(ifa, ifp) {
+ struct sockaddr *sa = ifa->ifa_addr;
+ const void *p = NULL;
+ int alen = 0;
+
+ if (sa->sa_family == AF_INET) {
+ const struct sockaddr_in *sin4 = satosin(sa);
+ alen = sizeof(struct in_addr);
+ p = &sin4->sin_addr;
+ }
+ if (sa->sa_family == AF_INET6) {
+ const struct sockaddr_in6 *sin6 = satosin6(sa);
+ alen = sizeof(struct in6_addr);
+ p = &sin6->sin6_addr;
+ }
+ if (alen) {
+ npf_addr_t addr;
+ memcpy(&addr, p, alen);
+ npf_table_insert(t, alen, &addr, NPF_NO_NETMASK);
+ }
+ }
+
+ /* Publish the new table. */
+ replace_ifnet_table(npf, t);
+}
+
+void
+npf_ifaddr_flush(npf_t *npf, ifnet_t *ifp)
+{
+ npf_table_t *t;
+
+ /*
+ * Flush: just load an empty table.
+ */
+ t = lookup_ifnet_table(npf, ifp);
+ if (!t) {
+ return;
+ }
+ replace_ifnet_table(npf, t);
+}