summaryrefslogtreecommitdiffstats
path: root/sys/contrib/pf/net/pf_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/pf/net/pf_table.c')
-rw-r--r--sys/contrib/pf/net/pf_table.c200
1 files changed, 175 insertions, 25 deletions
diff --git a/sys/contrib/pf/net/pf_table.c b/sys/contrib/pf/net/pf_table.c
index a79ed37..033616e 100644
--- a/sys/contrib/pf/net/pf_table.c
+++ b/sys/contrib/pf/net/pf_table.c
@@ -1,4 +1,5 @@
-/* $OpenBSD: pf_table.c,v 1.68 2006/05/02 10:08:45 dhartmei Exp $ */
+/* $FreeBSD$ */
+/* $OpenBSD: pf_table.c,v 1.62 2004/12/07 18:02:04 mcbride Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@@ -30,16 +31,27 @@
*
*/
+#ifdef __FreeBSD__
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#endif
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
+#ifdef __FreeBSD__
+#include <sys/malloc.h>
+#endif
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
+#ifndef __FreeBSD__
#include <netinet/ip_ipsp.h>
+#endif
+
#include <net/pfvar.h>
#define ACCEPT_FLAGS(oklist) \
@@ -49,6 +61,43 @@
return (EINVAL); \
} while (0)
+#ifdef __FreeBSD__
+static inline int
+_copyin(const void *uaddr, void *kaddr, size_t len)
+{
+ int r;
+
+ PF_UNLOCK();
+ r = copyin(uaddr, kaddr, len);
+ PF_LOCK();
+
+ return (r);
+}
+
+static inline int
+_copyout(const void *uaddr, void *kaddr, size_t len)
+{
+ int r;
+
+ PF_UNLOCK();
+ r = copyout(uaddr, kaddr, len);
+ PF_LOCK();
+
+ return (r);
+}
+
+#define COPYIN(from, to, size) \
+ ((flags & PFR_FLAG_USERIOCTL) ? \
+ _copyin((from), (to), (size)) : \
+ (bcopy((from), (to), (size)), 0))
+
+#define COPYOUT(from, to, size) \
+ ((flags & PFR_FLAG_USERIOCTL) ? \
+ _copyout((from), (to), (size)) : \
+ (bcopy((from), (to), (size)), 0))
+
+#else
+
#define COPYIN(from, to, size) \
((flags & PFR_FLAG_USERIOCTL) ? \
copyin((from), (to), (size)) : \
@@ -59,6 +108,8 @@
copyout((from), (to), (size)) : \
(bcopy((from), (to), (size)), 0))
+#endif
+
#define FILLIN_SIN(sin, addr) \
do { \
(sin).sin_len = sizeof(sin); \
@@ -123,9 +174,15 @@ struct pfr_walktree {
#define senderr(e) do { rv = (e); goto _bad; } while (0)
+#ifdef __FreeBSD__
+uma_zone_t pfr_ktable_pl;
+uma_zone_t pfr_kentry_pl;
+uma_zone_t pfr_kentry_pl2;
+#else
struct pool pfr_ktable_pl;
struct pool pfr_kentry_pl;
struct pool pfr_kentry_pl2;
+#endif
struct sockaddr_in pfr_sin;
struct sockaddr_in6 pfr_sin6;
union sockaddr_union pfr_mask;
@@ -188,12 +245,14 @@ int pfr_ktable_cnt;
void
pfr_initialize(void)
{
+#ifndef __FreeBSD__
pool_init(&pfr_ktable_pl, sizeof(struct pfr_ktable), 0, 0, 0,
"pfrktable", &pool_allocator_oldnointr);
pool_init(&pfr_kentry_pl, sizeof(struct pfr_kentry), 0, 0, 0,
"pfrkentry", &pool_allocator_oldnointr);
pool_init(&pfr_kentry_pl2, sizeof(struct pfr_kentry), 0, 0, 0,
"pfrkentry2", NULL);
+#endif
pfr_sin.sin_len = sizeof(pfr_sin);
pfr_sin.sin_family = AF_INET;
@@ -221,6 +280,7 @@ pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
pfr_enqueue_addrs(kt, &workq, ndel, 0);
if (!(flags & PFR_FLAG_DUMMY)) {
+ s = 0;
if (flags & PFR_FLAG_ATOMIC)
s = splsoftnet();
pfr_remove_kentries(kt, &workq);
@@ -243,7 +303,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfr_kentryworkq workq;
struct pfr_kentry *p, *q;
struct pfr_addr ad;
- int i, rv, s, xadd = 0;
+ int i, rv, s = 0, xadd = 0;
long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
@@ -287,9 +347,10 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
xadd++;
}
}
- if (flags & PFR_FLAG_FEEDBACK)
+ if (flags & PFR_FLAG_FEEDBACK) {
if (COPYOUT(&ad, addr+i, sizeof(ad)))
senderr(EFAULT);
+ }
}
pfr_clean_node_mask(tmpkt, &workq);
if (!(flags & PFR_FLAG_DUMMY)) {
@@ -321,7 +382,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfr_kentryworkq workq;
struct pfr_kentry *p;
struct pfr_addr ad;
- int i, rv, s, xdel = 0, log = 1;
+ int i, rv, s = 0, xdel = 0, log = 1;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
@@ -404,19 +465,17 @@ _bad:
int
pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
- int *size2, int *nadd, int *ndel, int *nchange, int flags,
- u_int32_t ignore_pfrt_flags)
+ int *size2, int *nadd, int *ndel, int *nchange, int flags)
{
struct pfr_ktable *kt, *tmpkt;
struct pfr_kentryworkq addq, delq, changeq;
struct pfr_kentry *p, *q;
struct pfr_addr ad;
- int i, rv, s, xadd = 0, xdel = 0, xchange = 0;
+ int i, rv, s = 0, xadd = 0, xdel = 0, xchange = 0;
long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
- if (pfr_validate_table(tbl, ignore_pfrt_flags, flags &
- PFR_FLAG_USERIOCTL))
+ if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -578,9 +637,18 @@ pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
w.pfrw_addr = addr;
w.pfrw_free = kt->pfrkt_cnt;
w.pfrw_flags = flags;
+#ifdef __FreeBSD__
+ rv = kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#else
rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#endif
if (!rv)
+#ifdef __FreeBSD__
+ rv = kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree,
+ &w);
+#else
rv = rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
+#endif
if (rv)
return (rv);
@@ -600,7 +668,7 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
struct pfr_ktable *kt;
struct pfr_walktree w;
struct pfr_kentryworkq workq;
- int rv, s;
+ int rv, s = 0;
long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC); /* XXX PFR_FLAG_CLSTATS disabled */
@@ -621,9 +689,18 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
w.pfrw_flags = flags;
if (flags & PFR_FLAG_ATOMIC)
s = splsoftnet();
+#ifdef __FreeBSD__
+ rv = kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#else
rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#endif
if (!rv)
+#ifdef __FreeBSD__
+ rv = kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree,
+ &w);
+#else
rv = rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
+#endif
if (!rv && (flags & PFR_FLAG_CLSTATS)) {
pfr_enqueue_addrs(kt, &workq, NULL, 0);
pfr_clstats_kentries(&workq, tzero, 0);
@@ -650,7 +727,7 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfr_kentryworkq workq;
struct pfr_kentry *p;
struct pfr_addr ad;
- int i, rv, s, xzero = 0;
+ int i, rv, s = 0, xzero = 0;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
if (pfr_validate_table(tbl, 0, 0))
@@ -738,10 +815,20 @@ pfr_enqueue_addrs(struct pfr_ktable *kt, struct pfr_kentryworkq *workq,
w.pfrw_op = sweep ? PFRW_SWEEP : PFRW_ENQUEUE;
w.pfrw_workq = workq;
if (kt->pfrkt_ip4 != NULL)
+#ifdef __FreeBSD__
+ if (kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree,
+ &w))
+#else
if (rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w))
+#endif
printf("pfr_enqueue_addrs: IPv4 walktree failed.\n");
if (kt->pfrkt_ip6 != NULL)
+#ifdef __FreeBSD__
+ if (kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree,
+ &w))
+#else
if (rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w))
+#endif
printf("pfr_enqueue_addrs: IPv6 walktree failed.\n");
if (naddr != NULL)
*naddr = w.pfrw_cnt;
@@ -754,9 +841,17 @@ pfr_mark_addrs(struct pfr_ktable *kt)
bzero(&w, sizeof(w));
w.pfrw_op = PFRW_MARK;
+#ifdef __FreeBSD__
+ if (kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w))
+#else
if (rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w))
+#endif
printf("pfr_mark_addrs: IPv4 walktree failed.\n");
+#ifdef __FreeBSD__
+ if (kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, &w))
+#else
if (rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w))
+#endif
printf("pfr_mark_addrs: IPv6 walktree failed.\n");
}
@@ -765,7 +860,7 @@ struct pfr_kentry *
pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact)
{
union sockaddr_union sa, mask;
- struct radix_node_head *head;
+ struct radix_node_head *head = NULL; /* make the compiler happy */
struct pfr_kentry *ke;
int s;
@@ -780,7 +875,13 @@ pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact)
if (ADDR_NETWORK(ad)) {
pfr_prepare_network(&mask, ad->pfra_af, ad->pfra_net);
s = splsoftnet(); /* rn_lookup makes use of globals */
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 500100)
+ RADIX_NODE_HEAD_LOCK(head);
+#endif
ke = (struct pfr_kentry *)rn_lookup(&sa, &mask, head);
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 500100)
+ RADIX_NODE_HEAD_UNLOCK(head);
+#endif
splx(s);
if (ke && KENTRY_RNF_ROOT(ke))
ke = NULL;
@@ -968,7 +1069,7 @@ pfr_route_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
{
union sockaddr_union mask;
struct radix_node *rn;
- struct radix_node_head *head;
+ struct radix_node_head *head = NULL; /* make the compiler happy */
int s;
bzero(ke->pfrke_node, sizeof(ke->pfrke_node));
@@ -978,11 +1079,17 @@ pfr_route_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
head = kt->pfrkt_ip6;
s = splsoftnet();
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 500100)
+ RADIX_NODE_HEAD_LOCK(head);
+#endif
if (KENTRY_NETWORK(ke)) {
pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net);
rn = rn_addroute(&ke->pfrke_sa, &mask, head, ke->pfrke_node);
} else
rn = rn_addroute(&ke->pfrke_sa, NULL, head, ke->pfrke_node);
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 500100)
+ RADIX_NODE_HEAD_UNLOCK(head);
+#endif
splx(s);
return (rn == NULL ? -1 : 0);
@@ -993,7 +1100,7 @@ pfr_unroute_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
{
union sockaddr_union mask;
struct radix_node *rn;
- struct radix_node_head *head;
+ struct radix_node_head *head = NULL; /* make the compiler happy */
int s;
if (ke->pfrke_af == AF_INET)
@@ -1002,11 +1109,25 @@ pfr_unroute_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
head = kt->pfrkt_ip6;
s = splsoftnet();
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 500100)
+ RADIX_NODE_HEAD_LOCK(head);
+#endif
if (KENTRY_NETWORK(ke)) {
pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net);
+#ifdef __FreeBSD__
+ rn = rn_delete(&ke->pfrke_sa, &mask, head);
+#else
rn = rn_delete(&ke->pfrke_sa, &mask, head, NULL);
+#endif
} else
+#ifdef __FreeBSD__
+ rn = rn_delete(&ke->pfrke_sa, NULL, head);
+#else
rn = rn_delete(&ke->pfrke_sa, NULL, head, NULL);
+#endif
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 500100)
+ RADIX_NODE_HEAD_UNLOCK(head);
+#endif
splx(s);
if (rn == NULL) {
@@ -1115,7 +1236,7 @@ pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
{
struct pfr_ktableworkq workq;
struct pfr_ktable *p;
- int s, xdel = 0;
+ int s = 0, xdel = 0;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ALLRSETS);
if (pfr_fix_anchor(filter->pfrt_anchor))
@@ -1152,7 +1273,7 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
{
struct pfr_ktableworkq addq, changeq;
struct pfr_ktable *p, *q, *r, key;
- int i, rv, s, xadd = 0;
+ int i, rv, s = 0, xadd = 0;
long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
@@ -1232,7 +1353,7 @@ pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
{
struct pfr_ktableworkq workq;
struct pfr_ktable *p, *q, key;
- int i, s, xdel = 0;
+ int i, s = 0, xdel = 0;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
SLIST_INIT(&workq);
@@ -1306,7 +1427,7 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
{
struct pfr_ktable *p;
struct pfr_ktableworkq workq;
- int s, n, nn;
+ int s = 0, n, nn;
long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC|PFR_FLAG_ALLRSETS);
@@ -1331,7 +1452,8 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
if (!(flags & PFR_FLAG_ATOMIC))
s = splsoftnet();
if (COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl))) {
- splx(s);
+ if (!(flags & PFR_FLAG_ATOMIC))
+ splx(s);
return (EFAULT);
}
if (!(flags & PFR_FLAG_ATOMIC))
@@ -1356,7 +1478,7 @@ pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
{
struct pfr_ktableworkq workq;
struct pfr_ktable *p, key;
- int i, s, xzero = 0;
+ int i, s = 0, xzero = 0;
long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ADDRSTOO);
@@ -1390,7 +1512,7 @@ pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
{
struct pfr_ktableworkq workq;
struct pfr_ktable *p, *q, key;
- int i, s, xchange = 0, xdel = 0;
+ int i, s = 0, xchange = 0, xdel = 0;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
if ((setflag & ~PFR_TFLAG_USRMASK) ||
@@ -1609,7 +1731,7 @@ pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
struct pfr_ktable *p, *q;
struct pfr_ktableworkq workq;
struct pf_ruleset *rs;
- int s, xadd = 0, xchange = 0;
+ int s = 0, xadd = 0, xchange = 0;
long tzero = time_second;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
@@ -1927,10 +2049,21 @@ pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr)
pfr_clean_node_mask(kt, &addrq);
pfr_destroy_kentries(&addrq);
}
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 500100)
+ if (kt->pfrkt_ip4 != NULL) {
+ RADIX_NODE_HEAD_DESTROY(kt->pfrkt_ip4);
+ free((caddr_t)kt->pfrkt_ip4, M_RTABLE);
+ }
+ if (kt->pfrkt_ip6 != NULL) {
+ RADIX_NODE_HEAD_DESTROY(kt->pfrkt_ip6);
+ free((caddr_t)kt->pfrkt_ip6, M_RTABLE);
+ }
+#else
if (kt->pfrkt_ip4 != NULL)
free((caddr_t)kt->pfrkt_ip4, M_RTABLE);
if (kt->pfrkt_ip6 != NULL)
free((caddr_t)kt->pfrkt_ip6, M_RTABLE);
+#endif
if (kt->pfrkt_shadow != NULL)
pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr);
if (kt->pfrkt_rs != NULL) {
@@ -2049,7 +2182,7 @@ pfr_attach_table(struct pf_ruleset *rs, char *name)
bzero(&tbl, sizeof(tbl));
strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name));
if (ac != NULL)
- strlcpy(tbl.pfrt_anchor, ac->path, sizeof(tbl.pfrt_anchor));
+ strlcpy(tbl.pfrt_anchor, ac->name, sizeof(tbl.pfrt_anchor));
kt = pfr_lookup_table(&tbl);
if (kt == NULL) {
kt = pfr_create_ktable(&tbl, time_second, 1);
@@ -2085,12 +2218,13 @@ pfr_detach_table(struct pfr_ktable *kt)
pfr_setflags_ktable(kt, kt->pfrkt_flags&~PFR_TFLAG_REFERENCED);
}
+
int
pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter,
struct pf_addr **raddr, struct pf_addr **rmask, sa_family_t af)
{
- struct pfr_kentry *ke, *ke2;
- struct pf_addr *addr;
+ struct pfr_kentry *ke, *ke2 = NULL;
+ struct pf_addr *addr = NULL;
union sockaddr_union mask;
int idx = -1, use_counter = 0;
@@ -2180,12 +2314,20 @@ pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
switch (af) {
#ifdef INET
case AF_INET:
+#ifdef __FreeBSD__
+ kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#else
rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#endif
return (w.pfrw_kentry);
#endif /* INET */
#ifdef INET6
case AF_INET6:
+#ifdef __FreeBSD__
+ kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
+#else
rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
+#endif
return (w.pfrw_kentry);
#endif /* INET6 */
default:
@@ -2207,8 +2349,16 @@ pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn)
dyn->pfid_acnt4 = 0;
dyn->pfid_acnt6 = 0;
if (!dyn->pfid_af || dyn->pfid_af == AF_INET)
+#ifdef __FreeBSD__
+ kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#else
rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#endif
if (!dyn->pfid_af || dyn->pfid_af == AF_INET6)
+#ifdef __FreeBSD__
+ kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
+#else
rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
+#endif
splx(s);
}
OpenPOWER on IntegriCloud