summaryrefslogtreecommitdiffstats
path: root/sys/contrib/pf
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/pf')
-rw-r--r--sys/contrib/pf/net/if_pflog.c169
-rw-r--r--sys/contrib/pf/net/if_pflog.h8
-rw-r--r--sys/contrib/pf/net/if_pfsync.c1225
-rw-r--r--sys/contrib/pf/net/if_pfsync.h242
-rw-r--r--sys/contrib/pf/net/pf.c3091
-rw-r--r--sys/contrib/pf/net/pf_ioctl.c2134
-rw-r--r--sys/contrib/pf/net/pf_norm.c252
-rw-r--r--sys/contrib/pf/net/pf_osfp.c46
-rw-r--r--sys/contrib/pf/net/pf_table.c552
-rw-r--r--sys/contrib/pf/net/pfvar.h467
-rw-r--r--sys/contrib/pf/netinet/in4_cksum.c168
11 files changed, 4488 insertions, 3866 deletions
diff --git a/sys/contrib/pf/net/if_pflog.c b/sys/contrib/pf/net/if_pflog.c
index 3b93226..13f6a6c 100644
--- a/sys/contrib/pf/net/if_pflog.c
+++ b/sys/contrib/pf/net/if_pflog.c
@@ -1,4 +1,5 @@
-/* $OpenBSD: if_pflog.c,v 1.11 2003/12/31 11:18:25 cedric Exp $ */
+/* $FreeBSD$ */
+/* $OpenBSD: if_pflog.c,v 1.9 2003/05/14 08:42:00 canacar Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -33,14 +34,33 @@
* PURPOSE.
*/
+#ifdef __FreeBSD__
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#endif
+
+#ifndef __FreeBSD__
#include "bpfilter.h"
#include "pflog.h"
+#elif __FreeBSD__ >= 5
+#include "opt_bpf.h"
+#include "opt_pf.h"
+#define NBPFILTER DEV_BPF
+#define NPFLOG DEV_PFLOG
+#endif
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
+#ifdef __FreeBSD__
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/sockio.h>
+#else
#include <sys/ioctl.h>
+#endif
#include <net/if.h>
#include <net/if_types.h>
@@ -54,6 +74,10 @@
#include <netinet/ip.h>
#endif
+#ifdef __FreeBSD__
+#include <machine/in_cksum.h>
+#endif
+
#ifdef INET6
#ifndef INET
#include <netinet/in.h>
@@ -64,6 +88,10 @@
#include <net/pfvar.h>
#include <net/if_pflog.h>
+#ifdef __FreeBSD__
+#define PFLOGNAME "pflog"
+#endif
+
#define PFLOGMTU (32768 + MHLEN + MLEN)
#ifdef PFLOGDEBUG
@@ -72,17 +100,87 @@
#define DPRINTF(x)
#endif
+#ifndef __FreeBSD__
struct pflog_softc pflogif[NPFLOG];
+#endif
+#ifdef __FreeBSD__
+static void pflog_clone_destroy(struct ifnet *);
+static int pflog_clone_create(struct if_clone *, int);
+#else
void pflogattach(int);
+#endif
int pflogoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);
int pflogioctl(struct ifnet *, u_long, caddr_t);
void pflogrtrequest(int, struct rtentry *, struct sockaddr *);
void pflogstart(struct ifnet *);
+#ifndef __FreeBSD__
extern int ifqmaxlen;
+#endif
+
+#ifdef __FreeBSD__
+static MALLOC_DEFINE(M_PFLOG, PFLOGNAME, "Packet Filter Logging Interface");
+static LIST_HEAD(pflog_list, pflog_softc) pflog_list;
+struct if_clone pflog_cloner = IF_CLONE_INITIALIZER(PFLOGNAME,
+ pflog_clone_create, pflog_clone_destroy, 1, IF_MAXUNIT);
+
+static void
+pflog_clone_destroy(struct ifnet *ifp)
+{
+ struct pflog_softc *sc;
+
+ sc = ifp->if_softc;
+
+ /*
+ * Does we really need this?
+ */
+ IF_DRAIN(&ifp->if_snd);
+
+ bpfdetach(ifp);
+ if_detach(ifp);
+ LIST_REMOVE(sc, sc_next);
+ free(sc, M_PFLOG);
+}
+
+static int
+pflog_clone_create(struct if_clone *ifc, int unit)
+{
+ struct pflog_softc *sc;
+
+ MALLOC(sc, struct pflog_softc *, sizeof(*sc), M_PFLOG, M_WAITOK|M_ZERO);
+
+#if (__FreeBSD_version < 501113)
+ sc->sc_if.if_name = PFLOGNAME;
+ sc->sc_if.if_unit = unit;
+#else
+ if_initname(&sc->sc_if, ifc->ifc_name, unit);
+#endif
+ sc->sc_if.if_mtu = PFLOGMTU;
+ sc->sc_if.if_ioctl = pflogioctl;
+ sc->sc_if.if_output = pflogoutput;
+ sc->sc_if.if_start = pflogstart;
+ sc->sc_if.if_type = IFT_PFLOG;
+ sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen;
+ sc->sc_if.if_hdrlen = PFLOG_HDRLEN;
+ sc->sc_if.if_softc = sc;
+ /*
+ * We would get a message like
+ * "in6_ifattach: pflog0 is not multicast capable, IPv6 not enabled".
+ * We need a patch to in6_ifattach() to exclude interface type
+ * IFT_PFLOG.
+ */
+ if_attach(&sc->sc_if);
+
+ LIST_INSERT_HEAD(&pflog_list, sc, sc_next);
+#if NBPFILTER > 0
+ bpfattach(&sc->sc_if, DLT_PFLOG, PFLOG_HDRLEN);
+#endif
+ return (0);
+}
+#else /* !__FreeBSD__ */
void
pflogattach(int npflog)
{
@@ -111,6 +209,7 @@ pflogattach(int npflog)
#endif
}
}
+#endif /* __FreeBSD__ */
/*
* Start output on the pflog interface.
@@ -123,10 +222,16 @@ pflogstart(struct ifnet *ifp)
for (;;) {
s = splimp();
+#ifdef __FreeBSD__
+ IF_LOCK(&ifp->if_snd);
+ _IF_DROP(&ifp->if_snd);
+ _IF_DEQUEUE(&ifp->if_snd, m);
+ IF_UNLOCK(&ifp->if_snd);
+#else
IF_DROP(&ifp->if_snd);
IF_DEQUEUE(&ifp->if_snd, m);
+#endif
splx(s);
-
if (m == NULL)
return;
else
@@ -172,7 +277,7 @@ pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
int
-pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
+pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir,
u_int8_t reason, struct pf_rule *rm, struct pf_rule *am,
struct pf_ruleset *ruleset)
{
@@ -181,23 +286,29 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
struct pfloghdr hdr;
struct mbuf m1;
- if (kif == NULL || m == NULL || rm == NULL)
+ if (ifp == NULL || m == NULL || rm == NULL)
return (-1);
- bzero(&hdr, sizeof(hdr));
hdr.length = PFLOG_REAL_HDRLEN;
hdr.af = af;
hdr.action = rm->action;
hdr.reason = reason;
- memcpy(hdr.ifname, kif->pfik_name, sizeof(hdr.ifname));
+#if defined(__FreeBSD__) && (__FreeBSD_version < 501113)
+ snprintf(hdr.ifname, IFNAMSIZ, "%s%d", ifp->if_name, ifp->if_unit);
+#else
+ memcpy(hdr.ifname, ifp->if_xname, sizeof(hdr.ifname));
+#endif
if (am == NULL) {
hdr.rulenr = htonl(rm->nr);
hdr.subrulenr = -1;
+ bzero(hdr.ruleset, sizeof(hdr.ruleset));
} else {
hdr.rulenr = htonl(am->nr);
hdr.subrulenr = htonl(rm->nr);
- if (ruleset != NULL)
+ if (ruleset == NULL)
+ bzero(hdr.ruleset, sizeof(hdr.ruleset));
+ else
memcpy(hdr.ruleset, ruleset->name,
sizeof(hdr.ruleset));
@@ -219,7 +330,12 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
m1.m_len = PFLOG_HDRLEN;
m1.m_data = (char *) &hdr;
+#ifdef __FreeBSD__
+ KASSERT((!LIST_EMPTY(&pflog_list)), ("pflog: no interface"));
+ ifn = &LIST_FIRST(&pflog_list)->sc_if;
+#else
ifn = &(pflogif[0].sc_if);
+#endif
if (ifn->if_bpf)
bpf_mtap(ifn->if_bpf, &m1);
@@ -227,3 +343,42 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
return (0);
}
+
+#ifdef __FreeBSD__
+static int
+pflog_modevent(module_t mod, int type, void *data)
+{
+ int error = 0;
+
+ switch (type) {
+ case MOD_LOAD:
+ LIST_INIT(&pflog_list);
+ if_clone_attach(&pflog_cloner);
+ break;
+
+ case MOD_UNLOAD:
+ if_clone_detach(&pflog_cloner);
+ while (!LIST_EMPTY(&pflog_list))
+ pflog_clone_destroy(
+ &LIST_FIRST(&pflog_list)->sc_if);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+static moduledata_t pflog_mod = {
+ "pflog",
+ pflog_modevent,
+ 0
+};
+
+#define PFLOG_MODVER 1
+
+DECLARE_MODULE(pflog, pflog_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+MODULE_VERSION(pflog, PFLOG_MODVER);
+#endif /* __FreeBSD__ */
diff --git a/sys/contrib/pf/net/if_pflog.h b/sys/contrib/pf/net/if_pflog.h
index e4e603e..e598239 100644
--- a/sys/contrib/pf/net/if_pflog.h
+++ b/sys/contrib/pf/net/if_pflog.h
@@ -1,4 +1,5 @@
-/* $OpenBSD: if_pflog.h,v 1.10 2004/03/19 04:52:04 frantzen Exp $ */
+/* $FreeBSD$ */
+/* $OpenBSD: if_pflog.h,v 1.9 2003/07/15 20:27:27 dhartmei Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -29,6 +30,9 @@
struct pflog_softc {
struct ifnet sc_if; /* the interface */
+#ifdef __FreeBSD__
+ LIST_ENTRY(pflog_softc) sc_next;
+#endif
};
/* XXX keep in sync with pfvar.h */
@@ -51,7 +55,7 @@ struct pfloghdr {
#define PFLOG_HDRLEN sizeof(struct pfloghdr)
/* minus pad, also used as a signature */
-#define PFLOG_REAL_HDRLEN offsetof(struct pfloghdr, pad)
+#define PFLOG_REAL_HDRLEN offsetof(struct pfloghdr, pad);
/* XXX remove later when old format logs are no longer needed */
struct old_pfloghdr {
diff --git a/sys/contrib/pf/net/if_pfsync.c b/sys/contrib/pf/net/if_pfsync.c
index e4840ff..06eb4b0 100644
--- a/sys/contrib/pf/net/if_pfsync.c
+++ b/sys/contrib/pf/net/if_pfsync.c
@@ -1,4 +1,5 @@
-/* $OpenBSD: if_pfsync.c,v 1.26 2004/03/28 18:14:20 mcbride Exp $ */
+/* $FreeBSD$ */
+/* $OpenBSD: if_pfsync.c,v 1.6 2003/06/21 09:07:01 djm Exp $ */
/*
* Copyright (c) 2002 Michael Shalayeff
@@ -26,17 +27,35 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifdef __FreeBSD__
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#endif
+
+#ifndef __FreeBSD__
#include "bpfilter.h"
#include "pfsync.h"
+#elif __FreeBSD__ >= 5
+#include "opt_bpf.h"
+#include "opt_pf.h"
+#define NBPFILTER DEV_BPF
+#define NPFSYNC DEV_PFSYNC
+#endif
#include <sys/param.h>
-#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/time.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
+#ifdef __FreeBSD__
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/sockio.h>
+#else
#include <sys/ioctl.h>
#include <sys/timeout.h>
+#endif
#include <net/if.h>
#include <net/if_types.h>
@@ -45,10 +64,7 @@
#ifdef INET
#include <netinet/in.h>
-#include <netinet/in_systm.h>
#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#include <netinet/ip_var.h>
#endif
#ifdef INET6
@@ -61,6 +77,10 @@
#include <net/pfvar.h>
#include <net/if_pfsync.h>
+#ifdef __FreeBSD__
+#define PFSYNCNAME "pfsync"
+#endif
+
#define PFSYNC_MINMTU \
(sizeof(struct pfsync_header) + sizeof(struct pf_state))
@@ -71,46 +91,105 @@ int pfsyncdebug;
#define DPRINTF(x)
#endif
-struct pfsync_softc pfsyncif;
-int pfsync_sync_ok;
-struct pfsyncstats pfsyncstats;
+#ifndef __FreeBSD__
+struct pfsync_softc pfsyncif;
+#endif
+#ifdef __FreeBSD__
+static void pfsync_clone_destroy(struct ifnet *);
+static int pfsync_clone_create(struct if_clone *, int);
+#else
void pfsyncattach(int);
-void pfsync_setmtu(struct pfsync_softc *, int);
-int pfsync_insert_net_state(struct pfsync_state *);
+#endif
+void pfsync_setmtu(struct pfsync_softc *sc, int);
int pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
- struct rtentry *);
+ struct rtentry *);
int pfsyncioctl(struct ifnet *, u_long, caddr_t);
void pfsyncstart(struct ifnet *);
-struct mbuf *pfsync_get_mbuf(struct pfsync_softc *, u_int8_t, void **);
-int pfsync_request_update(struct pfsync_state_upd *, struct in_addr *);
-int pfsync_sendout(struct pfsync_softc *);
-void pfsync_timeout(void *);
-void pfsync_send_bus(struct pfsync_softc *, u_int8_t);
-void pfsync_bulk_update(void *);
-void pfsync_bulkfail(void *);
+struct mbuf *pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action);
+int pfsync_sendout(struct pfsync_softc *sc);
+void pfsync_timeout(void *v);
+#ifndef __FreeBSD__
extern int ifqmaxlen;
-extern struct timeval time;
-extern struct timeval mono_time;
-extern int hz;
+#endif
+
+#ifdef __FreeBSD__
+static MALLOC_DEFINE(M_PFSYNC, PFSYNCNAME, "Packet Filter State Sync. Interface");
+static LIST_HEAD(pfsync_list, pfsync_softc) pfsync_list;
+struct if_clone pfsync_cloner = IF_CLONE_INITIALIZER(PFSYNCNAME,
+ pfsync_clone_create, pfsync_clone_destroy, 1, IF_MAXUNIT);
+
+static void
+pfsync_clone_destroy(struct ifnet *ifp)
+{
+ struct pfsync_softc *sc;
+
+ sc = ifp->if_softc;
+ callout_stop(&sc->sc_tmo);
+
+ /*
+ * Does we really need this?
+ */
+ IF_DRAIN(&ifp->if_snd);
+
+#if NBPFILTER > 0
+ bpfdetach(ifp);
+#endif
+ if_detach(ifp);
+ LIST_REMOVE(sc, sc_next);
+ free(sc, M_PFSYNC);
+}
+
+static int
+pfsync_clone_create(struct if_clone *ifc, int unit)
+{
+ struct pfsync_softc *sc;
+
+ MALLOC(sc, struct pfsync_softc *, sizeof(*sc), M_PFSYNC,
+ M_WAITOK|M_ZERO);
+ sc->sc_count = 8;
+#if (__FreeBSD_version < 501113)
+ sc->sc_if.if_name = PFSYNCNAME;
+ sc->sc_if.if_unit = unit;
+#else
+ if_initname(&sc->sc_if, ifc->ifc_name, unit);
+#endif
+ sc->sc_if.if_ioctl = pfsyncioctl;
+ sc->sc_if.if_output = pfsyncoutput;
+ sc->sc_if.if_start = pfsyncstart;
+ sc->sc_if.if_type = IFT_PFSYNC;
+ sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen;
+ sc->sc_if.if_hdrlen = PFSYNC_HDRLEN;
+ sc->sc_if.if_baudrate = IF_Mbps(100);
+ sc->sc_if.if_softc = sc;
+ pfsync_setmtu(sc, MCLBYTES);
+ /*
+ * XXX
+ * The 2nd arg. 0 to callout_init(9) shoule be set to CALLOUT_MPSAFE
+ * if Gaint lock is removed from the network stack.
+ */
+ callout_init(&sc->sc_tmo, 0);
+ if_attach(&sc->sc_if);
+
+ LIST_INSERT_HEAD(&pfsync_list, sc, sc_next);
+#if NBPFILTER > 0
+ bpfattach(&sc->sc_if, DLT_PFSYNC, PFSYNC_HDRLEN);
+#endif
+
+ return (0);
+}
+#else /* !__FreeBSD__ */
void
pfsyncattach(int npfsync)
{
struct ifnet *ifp;
- pfsync_sync_ok = 1;
- bzero(&pfsyncif, sizeof(pfsyncif));
pfsyncif.sc_mbuf = NULL;
- pfsyncif.sc_mbuf_net = NULL;
- pfsyncif.sc_statep.s = NULL;
- pfsyncif.sc_statep_net.s = NULL;
- pfsyncif.sc_maxupdates = 128;
- pfsyncif.sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP;
- pfsyncif.sc_ureq_received = 0;
- pfsyncif.sc_ureq_sent = 0;
+ pfsyncif.sc_ptr = NULL;
+ pfsyncif.sc_count = 8;
ifp = &pfsyncif.sc_if;
strlcpy(ifp->if_xname, "pfsync0", sizeof ifp->if_xname);
ifp->if_softc = &pfsyncif;
@@ -120,10 +199,9 @@ pfsyncattach(int npfsync)
ifp->if_type = IFT_PFSYNC;
ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_hdrlen = PFSYNC_HDRLEN;
+ ifp->if_baudrate = IF_Mbps(100);
pfsync_setmtu(&pfsyncif, MCLBYTES);
timeout_set(&pfsyncif.sc_tmo, pfsync_timeout, &pfsyncif);
- timeout_set(&pfsyncif.sc_bulk_tmo, pfsync_bulk_update, &pfsyncif);
- timeout_set(&pfsyncif.sc_bulkfail_tmo, pfsync_bulkfail, &pfsyncif);
if_attach(ifp);
if_alloc_sadl(ifp);
@@ -131,6 +209,7 @@ pfsyncattach(int npfsync)
bpfattach(&pfsyncif.sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
#endif
}
+#endif
/*
* Start output on the pfsync interface.
@@ -143,8 +222,15 @@ pfsyncstart(struct ifnet *ifp)
for (;;) {
s = splimp();
+#ifdef __FreeBSD__
+ IF_LOCK(&ifp->if_snd);
+ _IF_DROP(&ifp->if_snd);
+ _IF_DEQUEUE(&ifp->if_snd, m);
+ IF_UNLOCK(&ifp->if_snd);
+#else
IF_DROP(&ifp->if_snd);
IF_DEQUEUE(&ifp->if_snd, m);
+#endif
splx(s);
if (m == NULL)
@@ -155,451 +241,6 @@ pfsyncstart(struct ifnet *ifp)
}
int
-pfsync_insert_net_state(struct pfsync_state *sp)
-{
- struct pf_state *st = NULL;
- struct pf_rule *r = NULL;
- struct pfi_kif *kif;
-
- if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) {
- printf("pfsync_insert_net_state: invalid creator id:"
- " %08x\n", ntohl(sp->creatorid));
- return (EINVAL);
- }
-
- kif = pfi_lookup_create(sp->ifname);
- if (kif == NULL) {
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync_insert_net_state: "
- "unknown interface: %s\n", sp->ifname);
- /* skip this state */
- return (0);
- }
-
- /*
- * Just use the default rule until we have infrastructure to find the
- * best matching rule.
- */
- r = &pf_default_rule;
-
- if (!r->max_states || r->states < r->max_states)
- st = pool_get(&pf_state_pl, PR_NOWAIT);
- if (st == NULL) {
- pfi_maybe_destroy(kif);
- return (ENOMEM);
- }
- bzero(st, sizeof(*st));
-
- st->rule.ptr = r;
- /* XXX get pointers to nat_rule and anchor */
-
- /* fill in the rest of the state entry */
- pf_state_host_ntoh(&sp->lan, &st->lan);
- pf_state_host_ntoh(&sp->gwy, &st->gwy);
- pf_state_host_ntoh(&sp->ext, &st->ext);
-
- pf_state_peer_ntoh(&sp->src, &st->src);
- pf_state_peer_ntoh(&sp->dst, &st->dst);
-
- bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr));
- st->creation = ntohl(sp->creation) + time.tv_sec;
- st->expire = ntohl(sp->expire) + time.tv_sec;
-
- st->af = sp->af;
- st->proto = sp->proto;
- st->direction = sp->direction;
- st->log = sp->log;
- st->timeout = sp->timeout;
- st->allow_opts = sp->allow_opts;
-
- bcopy(sp->id, &st->id, sizeof(st->id));
- st->creatorid = sp->creatorid;
- st->sync_flags = sp->sync_flags | PFSTATE_FROMSYNC;
-
-
- if (pf_insert_state(kif, st)) {
- pfi_maybe_destroy(kif);
- pool_put(&pf_state_pl, st);
- return (EINVAL);
- }
-
- return (0);
-}
-
-void
-pfsync_input(struct mbuf *m, ...)
-{
- struct ip *ip = mtod(m, struct ip *);
- struct pfsync_header *ph;
- struct pfsync_softc *sc = &pfsyncif;
- struct pf_state *st, key;
- struct pfsync_state *sp;
- struct pfsync_state_upd *up;
- struct pfsync_state_del *dp;
- struct pfsync_state_clr *cp;
- struct pfsync_state_upd_req *rup;
- struct pfsync_state_bus *bus;
- struct in_addr src;
- struct mbuf *mp;
- int iplen, action, error, i, s, count, offp;
-
- pfsyncstats.pfsyncs_ipackets++;
-
- /* verify that we have a sync interface configured */
- if (!sc->sc_sync_ifp || !pf_status.running)
- goto done;
-
- /* verify that the packet came in on the right interface */
- if (sc->sc_sync_ifp != m->m_pkthdr.rcvif) {
- pfsyncstats.pfsyncs_badif++;
- goto done;
- }
-
- /* verify that the IP TTL is 255. */
- if (ip->ip_ttl != PFSYNC_DFLTTL) {
- pfsyncstats.pfsyncs_badttl++;
- goto done;
- }
-
- iplen = ip->ip_hl << 2;
-
- if (m->m_pkthdr.len < iplen + sizeof(*ph)) {
- pfsyncstats.pfsyncs_hdrops++;
- goto done;
- }
-
- if (iplen + sizeof(*ph) > m->m_len) {
- if ((m = m_pullup(m, iplen + sizeof(*ph))) == NULL) {
- pfsyncstats.pfsyncs_hdrops++;
- goto done;
- }
- ip = mtod(m, struct ip *);
- }
- ph = (struct pfsync_header *)((char *)ip + iplen);
-
- /* verify the version */
- if (ph->version != PFSYNC_VERSION) {
- pfsyncstats.pfsyncs_badver++;
- goto done;
- }
-
- action = ph->action;
- count = ph->count;
-
- /* make sure it's a valid action code */
- if (action >= PFSYNC_ACT_MAX) {
- pfsyncstats.pfsyncs_badact++;
- goto done;
- }
-
- /* Cheaper to grab this now than having to mess with mbufs later */
- src = ip->ip_src;
-
- switch (action) {
- case PFSYNC_ACT_CLR: {
- struct pfi_kif *kif;
- u_int32_t creatorid;
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- sizeof(*cp), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
- }
- cp = (struct pfsync_state_clr *)(mp->m_data + offp);
- creatorid = cp->creatorid;
-
- s = splsoftnet();
- if (cp->ifname[0] == '\0') {
- RB_FOREACH(st, pf_state_tree_id, &tree_id) {
- if (st->creatorid == creatorid)
- st->timeout = PFTM_PURGE;
- }
- } else {
- kif = pfi_lookup_if(cp->ifname);
- if (kif == NULL) {
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync_input: PFSYNC_ACT_CLR "
- "bad interface: %s\n", cp->ifname);
- splx(s);
- goto done;
- }
- RB_FOREACH(st, pf_state_tree_lan_ext,
- &kif->pfik_lan_ext) {
- if (st->creatorid == creatorid)
- st->timeout = PFTM_PURGE;
- }
- }
- pf_purge_expired_states();
- splx(s);
-
- break;
- }
- case PFSYNC_ACT_INS:
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- count * sizeof(*sp), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
- }
-
- s = splsoftnet();
- for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
- i < count; i++, sp++) {
- /* check for invalid values */
- if (sp->timeout >= PFTM_MAX ||
- sp->src.state > PF_TCPS_PROXY_DST ||
- sp->dst.state > PF_TCPS_PROXY_DST ||
- sp->direction > PF_OUT ||
- (sp->af != AF_INET && sp->af != AF_INET6)) {
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync_insert: PFSYNC_ACT_INS: "
- "invalid value\n");
- pfsyncstats.pfsyncs_badstate++;
- continue;
- }
-
- if ((error = pfsync_insert_net_state(sp))) {
- if (error == ENOMEM) {
- splx(s);
- goto done;
- }
- continue;
- }
- }
- splx(s);
- break;
- case PFSYNC_ACT_UPD:
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- count * sizeof(*sp), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
- }
-
- s = splsoftnet();
- for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
- i < count; i++, sp++) {
- /* check for invalid values */
- if (sp->timeout >= PFTM_MAX ||
- sp->src.state > PF_TCPS_PROXY_DST ||
- sp->dst.state > PF_TCPS_PROXY_DST) {
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync_insert: PFSYNC_ACT_UPD: "
- "invalid value\n");
- pfsyncstats.pfsyncs_badstate++;
- continue;
- }
-
- bcopy(sp->id, &key.id, sizeof(key.id));
- key.creatorid = sp->creatorid;
-
- st = pf_find_state_byid(&key);
- if (st == NULL) {
- /* insert the update */
- if (pfsync_insert_net_state(sp))
- pfsyncstats.pfsyncs_badstate++;
- continue;
- }
- pf_state_peer_ntoh(&sp->src, &st->src);
- pf_state_peer_ntoh(&sp->dst, &st->dst);
- st->expire = ntohl(sp->expire) + time.tv_sec;
- st->timeout = sp->timeout;
-
- }
- splx(s);
- break;
- /*
- * It's not strictly necessary for us to support the "uncompressed"
- * delete action, but it's relatively simple and maintains consistency.
- */
- case PFSYNC_ACT_DEL:
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- count * sizeof(*sp), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
- }
-
- s = splsoftnet();
- for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
- i < count; i++, sp++) {
- bcopy(sp->id, &key.id, sizeof(key.id));
- key.creatorid = sp->creatorid;
-
- st = pf_find_state_byid(&key);
- if (st == NULL) {
- pfsyncstats.pfsyncs_badstate++;
- continue;
- }
- /*
- * XXX
- * pf_purge_expired_states() is expensive,
- * we really want to purge the state directly.
- */
- st->timeout = PFTM_PURGE;
- st->sync_flags |= PFSTATE_FROMSYNC;
- }
- pf_purge_expired_states();
- splx(s);
- break;
- case PFSYNC_ACT_UPD_C: {
- int update_requested = 0;
-
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- count * sizeof(*up), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
- }
-
- s = splsoftnet();
- for (i = 0, up = (struct pfsync_state_upd *)(mp->m_data + offp);
- i < count; i++, up++) {
- /* check for invalid values */
- if (up->timeout >= PFTM_MAX ||
- up->src.state > PF_TCPS_PROXY_DST ||
- up->dst.state > PF_TCPS_PROXY_DST) {
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync_insert: "
- "PFSYNC_ACT_UPD_C: "
- "invalid value\n");
- pfsyncstats.pfsyncs_badstate++;
- continue;
- }
-
- bcopy(up->id, &key.id, sizeof(key.id));
- key.creatorid = up->creatorid;
-
- st = pf_find_state_byid(&key);
- if (st == NULL) {
- /* We don't have this state. Ask for it. */
- pfsync_request_update(up, &src);
- update_requested = 1;
- pfsyncstats.pfsyncs_badstate++;
- continue;
- }
- pf_state_peer_ntoh(&up->src, &st->src);
- pf_state_peer_ntoh(&up->dst, &st->dst);
- st->expire = ntohl(up->expire) + time.tv_sec;
- st->timeout = up->timeout;
- }
- if (update_requested)
- pfsync_sendout(sc);
- splx(s);
- break;
- }
- case PFSYNC_ACT_DEL_C:
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- count * sizeof(*dp), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
- }
-
- s = splsoftnet();
- for (i = 0, dp = (struct pfsync_state_del *)(mp->m_data + offp);
- i < count; i++, dp++) {
- bcopy(dp->id, &key.id, sizeof(key.id));
- key.creatorid = dp->creatorid;
-
- st = pf_find_state_byid(&key);
- if (st == NULL) {
- pfsyncstats.pfsyncs_badstate++;
- continue;
- }
- /*
- * XXX
- * pf_purge_expired_states() is expensive,
- * we really want to purge the state directly.
- */
- st->timeout = PFTM_PURGE;
- st->sync_flags |= PFSTATE_FROMSYNC;
- }
- pf_purge_expired_states();
- splx(s);
- break;
- case PFSYNC_ACT_INS_F:
- case PFSYNC_ACT_DEL_F:
- /* not implemented */
- break;
- case PFSYNC_ACT_UREQ:
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- count * sizeof(*rup), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
- }
-
- s = splsoftnet();
- /* XXX send existing. pfsync_pack_state should handle this. */
- if (sc->sc_mbuf != NULL)
- pfsync_sendout(sc);
- for (i = 0,
- rup = (struct pfsync_state_upd_req *)(mp->m_data + offp);
- i < count; i++, rup++) {
- bcopy(rup->id, &key.id, sizeof(key.id));
- key.creatorid = rup->creatorid;
-
- if (key.id == 0 && key.creatorid == 0) {
- sc->sc_ureq_received = mono_time.tv_sec;
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: received "
- "bulk update request\n");
- pfsync_send_bus(sc, PFSYNC_BUS_START);
- timeout_add(&sc->sc_bulk_tmo, 1 * hz);
- } else {
- st = pf_find_state_byid(&key);
- if (st == NULL) {
- pfsyncstats.pfsyncs_badstate++;
- continue;
- }
- pfsync_pack_state(PFSYNC_ACT_UPD, st, 0);
- }
- }
- if (sc->sc_mbuf != NULL)
- pfsync_sendout(sc);
- splx(s);
- break;
- case PFSYNC_ACT_BUS:
- /* If we're not waiting for a bulk update, who cares. */
- if (sc->sc_ureq_sent == 0)
- break;
-
- if ((mp = m_pulldown(m, iplen + sizeof(*ph),
- sizeof(*bus), &offp)) == NULL) {
- pfsyncstats.pfsyncs_badlen++;
- return;
- }
- bus = (struct pfsync_state_bus *)(mp->m_data + offp);
- switch (bus->status) {
- case PFSYNC_BUS_START:
- timeout_add(&sc->sc_bulkfail_tmo,
- pf_pool_limits[PF_LIMIT_STATES].limit /
- (PFSYNC_BULKPACKETS * sc->sc_maxcount));
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: received bulk "
- "update start\n");
- break;
- case PFSYNC_BUS_END:
- if (mono_time.tv_sec - ntohl(bus->endtime) >=
- sc->sc_ureq_sent) {
- /* that's it, we're happy */
- sc->sc_ureq_sent = 0;
- sc->sc_bulk_tries = 0;
- timeout_del(&sc->sc_bulkfail_tmo);
- pfsync_sync_ok = 1;
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: received valid "
- "bulk update end\n");
- } else {
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: received invalid "
- "bulk update end: bad timestamp\n");
- }
- break;
- }
- break;
- }
-
-done:
- if (m)
- m_freem(m);
-}
-
-int
pfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
struct rtentry *rt)
{
@@ -611,13 +252,9 @@ pfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
int
pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct proc *p = curproc;
struct pfsync_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
- struct ip_moptions *imo = &sc->sc_imo;
- struct pfsyncreq pfsyncr;
- struct ifnet *sifp;
- int s, error;
+ int s;
switch (cmd) {
case SIOCSIFADDR:
@@ -640,84 +277,6 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
pfsync_setmtu(sc, ifr->ifr_mtu);
splx(s);
break;
- case SIOCGETPFSYNC:
- bzero(&pfsyncr, sizeof(pfsyncr));
- if (sc->sc_sync_ifp)
- strlcpy(pfsyncr.pfsyncr_syncif,
- sc->sc_sync_ifp->if_xname, IFNAMSIZ);
- pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates;
- if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr))))
- return (error);
- break;
- case SIOCSETPFSYNC:
- if ((error = suser(p, p->p_acflag)) != 0)
- return (error);
- if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr))))
- return (error);
-
- if (pfsyncr.pfsyncr_maxupdates > 255)
- return (EINVAL);
- sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates;
-
- if (pfsyncr.pfsyncr_syncif[0] == 0) {
- sc->sc_sync_ifp = NULL;
- if (sc->sc_mbuf_net != NULL) {
- /* Don't keep stale pfsync packets around. */
- s = splnet();
- m_freem(sc->sc_mbuf_net);
- sc->sc_mbuf_net = NULL;
- sc->sc_statep_net.s = NULL;
- splx(s);
- }
- break;
- }
- if ((sifp = ifunit(pfsyncr.pfsyncr_syncif)) == NULL)
- return (EINVAL);
- else if (sifp == sc->sc_sync_ifp)
- break;
-
- s = splnet();
- if (sifp->if_mtu < sc->sc_if.if_mtu ||
- (sc->sc_sync_ifp != NULL &&
- sifp->if_mtu < sc->sc_sync_ifp->if_mtu) ||
- sifp->if_mtu < MCLBYTES - sizeof(struct ip))
- pfsync_sendout(sc);
- sc->sc_sync_ifp = sifp;
-
- pfsync_setmtu(sc, sc->sc_if.if_mtu);
-
- if (imo->imo_num_memberships > 0) {
- in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
- imo->imo_multicast_ifp = NULL;
- }
-
- if (sc->sc_sync_ifp) {
- struct in_addr addr;
-
- addr.s_addr = INADDR_PFSYNC_GROUP;
- if ((imo->imo_membership[0] =
- in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) {
- splx(s);
- return (ENOBUFS);
- }
- imo->imo_num_memberships++;
- imo->imo_multicast_ifp = sc->sc_sync_ifp;
- imo->imo_multicast_ttl = PFSYNC_DFLTTL;
- imo->imo_multicast_loop = 0;
-
- /* Request a full state table update. */
- sc->sc_ureq_sent = mono_time.tv_sec;
- pfsync_sync_ok = 0;
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: requesting bulk update\n");
- timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
- pfsync_request_update(NULL, NULL);
- pfsync_sendout(sc);
- }
- splx(s);
-
- break;
-
default:
return (ENOTTY);
}
@@ -726,26 +285,24 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
void
-pfsync_setmtu(struct pfsync_softc *sc, int mtu_req)
-{
+pfsync_setmtu(sc, mtu)
+ struct pfsync_softc *sc;
int mtu;
-
- if (sc->sc_sync_ifp && sc->sc_sync_ifp->if_mtu < mtu_req)
- mtu = sc->sc_sync_ifp->if_mtu;
- else
- mtu = mtu_req;
-
- sc->sc_maxcount = (mtu - sizeof(struct pfsync_header)) /
- sizeof(struct pfsync_state);
- if (sc->sc_maxcount > 254)
- sc->sc_maxcount = 254;
+{
+ sc->sc_count = (mtu - sizeof(struct pfsync_header)) /
+ sizeof(struct pf_state);
sc->sc_if.if_mtu = sizeof(struct pfsync_header) +
- sc->sc_maxcount * sizeof(struct pfsync_state);
+ sc->sc_count * sizeof(struct pf_state);
}
struct mbuf *
-pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp)
+pfsync_get_mbuf(sc, action)
+ struct pfsync_softc *sc;
+ u_int8_t action;
{
+#ifndef __FreeBSD__
+ extern int hz;
+#endif
struct pfsync_header *h;
struct mbuf *m;
int len;
@@ -756,33 +313,7 @@ pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp)
return (NULL);
}
- switch (action) {
- case PFSYNC_ACT_CLR:
- len = sizeof(struct pfsync_header) +
- sizeof(struct pfsync_state_clr);
- break;
- case PFSYNC_ACT_UPD_C:
- len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd)) +
- sizeof(struct pfsync_header);
- break;
- case PFSYNC_ACT_DEL_C:
- len = (sc->sc_maxcount * sizeof(struct pfsync_state_del)) +
- sizeof(struct pfsync_header);
- break;
- case PFSYNC_ACT_UREQ:
- len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd_req)) +
- sizeof(struct pfsync_header);
- break;
- case PFSYNC_ACT_BUS:
- len = sizeof(struct pfsync_header) +
- sizeof(struct pfsync_state_bus);
- break;
- default:
- len = (sc->sc_maxcount * sizeof(struct pfsync_state)) +
- sizeof(struct pfsync_header);
- break;
- }
-
+ len = sc->sc_if.if_mtu;
if (len > MHLEN) {
MCLGET(m, M_DONTWAIT);
if ((m->m_flags & M_EXT) == 0) {
@@ -790,286 +321,146 @@ pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp)
sc->sc_if.if_oerrors++;
return (NULL);
}
- m->m_data += (MCLBYTES - len) &~ (sizeof(long) - 1);
- } else
- MH_ALIGN(m, len);
-
+ }
m->m_pkthdr.rcvif = NULL;
- m->m_pkthdr.len = m->m_len = sizeof(struct pfsync_header);
+ m->m_pkthdr.len = m->m_len = len;
+
h = mtod(m, struct pfsync_header *);
h->version = PFSYNC_VERSION;
h->af = 0;
h->count = 0;
h->action = action;
- *sp = (void *)((char *)h + PFSYNC_HDRLEN);
+ sc->sc_mbuf = m;
+ sc->sc_ptr = (struct pf_state *)((char *)h + PFSYNC_HDRLEN);
+#ifdef __FreeBSD__
+ callout_reset(&sc->sc_tmo, hz, pfsync_timeout,
+ LIST_FIRST(&pfsync_list));
+#else
timeout_add(&sc->sc_tmo, hz);
+#endif
+
return (m);
}
+/*
+ * XXX: This function should be called with PF_LOCK held as it references
+ * pf_state.
+ */
int
-pfsync_pack_state(u_int8_t action, struct pf_state *st, int compress)
+pfsync_pack_state(action, st)
+ u_int8_t action;
+ struct pf_state *st;
{
+#ifdef __FreeBSD__
+ struct pfsync_softc *sc = LIST_FIRST(&pfsync_list);
+#else
+ extern struct timeval time;
struct ifnet *ifp = &pfsyncif.sc_if;
struct pfsync_softc *sc = ifp->if_softc;
- struct pfsync_header *h, *h_net;
- struct pfsync_state *sp = NULL;
- struct pfsync_state_upd *up = NULL;
- struct pfsync_state_del *dp = NULL;
- struct pf_rule *r;
+#endif
+ struct pfsync_header *h;
+ struct pf_state *sp;
+ struct pf_rule *r = st->rule.ptr;
+ struct mbuf *m;
u_long secs;
- int s, ret = 0;
- u_int8_t i = 255, newaction = 0;
-
- /*
- * If a packet falls in the forest and there's nobody around to
- * hear, does it make a sound?
- */
- if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL) {
- /* Don't leave any stale pfsync packets hanging around. */
- if (sc->sc_mbuf != NULL) {
- m_freem(sc->sc_mbuf);
- sc->sc_mbuf = NULL;
- sc->sc_statep.s = NULL;
- }
- return (0);
- }
+ int s, ret;
if (action >= PFSYNC_ACT_MAX)
return (EINVAL);
+#ifdef __FreeBSD__
+ /*
+ * XXX
+ * If we need to check mutex owned, PF_LOCK should be
+ * declared in pflog.ko.
+ *
+ * PF_LOCK_ASSERT();
+ */
+ KASSERT((!LIST_EMPTY(&pfsync_list)), ("pfsync: no interface"));
+#endif
s = splnet();
- if (sc->sc_mbuf == NULL) {
- if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
- (void *)&sc->sc_statep.s)) == NULL) {
+ m = sc->sc_mbuf;
+ if (m == NULL) {
+ if ((m = pfsync_get_mbuf(sc, action)) == NULL) {
splx(s);
return (ENOMEM);
}
- h = mtod(sc->sc_mbuf, struct pfsync_header *);
+ h = mtod(m, struct pfsync_header *);
} else {
- h = mtod(sc->sc_mbuf, struct pfsync_header *);
+ h = mtod(m, struct pfsync_header *);
if (h->action != action) {
pfsync_sendout(sc);
- if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
- (void *)&sc->sc_statep.s)) == NULL) {
+ if ((m = pfsync_get_mbuf(sc, action)) == NULL) {
splx(s);
return (ENOMEM);
}
- h = mtod(sc->sc_mbuf, struct pfsync_header *);
- } else {
- /*
- * If it's an update, look in the packet to see if
- * we already have an update for the state.
- */
- if (action == PFSYNC_ACT_UPD && sc->sc_maxupdates) {
- struct pfsync_state *usp =
- (void *)((char *)h + PFSYNC_HDRLEN);
-
- for (i = 0; i < h->count; i++) {
- if (!memcmp(usp->id, &st->id,
- PFSYNC_ID_LEN) &&
- usp->creatorid == st->creatorid) {
- sp = usp;
- sp->updates++;
- break;
- }
- usp++;
- }
- }
+ h = mtod(m, struct pfsync_header *);
}
}
- secs = time.tv_sec;
+ sp = sc->sc_ptr++;
+ h->count++;
+ bzero(sp, sizeof(*sp));
- st->pfsync_time = mono_time.tv_sec;
- TAILQ_REMOVE(&state_updates, st, u.s.entry_updates);
- TAILQ_INSERT_TAIL(&state_updates, st, u.s.entry_updates);
-
- if (sp == NULL) {
- /* not a "duplicate" update */
- i = 255;
- sp = sc->sc_statep.s++;
- sc->sc_mbuf->m_pkthdr.len =
- sc->sc_mbuf->m_len += sizeof(struct pfsync_state);
- h->count++;
- bzero(sp, sizeof(*sp));
-
- bcopy(&st->id, sp->id, sizeof(sp->id));
- sp->creatorid = st->creatorid;
-
- strlcpy(sp->ifname, st->u.s.kif->pfik_name, sizeof(sp->ifname));
- pf_state_host_hton(&st->lan, &sp->lan);
- pf_state_host_hton(&st->gwy, &sp->gwy);
- pf_state_host_hton(&st->ext, &sp->ext);
-
- bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
-
- sp->creation = htonl(secs - st->creation);
- sp->packets[0] = htonl(st->packets[0]);
- sp->packets[1] = htonl(st->packets[1]);
- sp->bytes[0] = htonl(st->bytes[0]);
- sp->bytes[1] = htonl(st->bytes[1]);
- if ((r = st->rule.ptr) == NULL)
- sp->rule = htonl(-1);
- else
- sp->rule = htonl(r->nr);
- if ((r = st->anchor.ptr) == NULL)
- sp->anchor = htonl(-1);
- else
- sp->anchor = htonl(r->nr);
- sp->af = st->af;
- sp->proto = st->proto;
- sp->direction = st->direction;
- sp->log = st->log;
- sp->allow_opts = st->allow_opts;
- sp->timeout = st->timeout;
-
- sp->sync_flags = st->sync_flags & PFSTATE_NOSYNC;
- }
+ bcopy(&st->lan, &sp->lan, sizeof(sp->lan));
+ bcopy(&st->gwy, &sp->gwy, sizeof(sp->gwy));
+ bcopy(&st->ext, &sp->ext, sizeof(sp->ext));
pf_state_peer_hton(&st->src, &sp->src);
pf_state_peer_hton(&st->dst, &sp->dst);
+ bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
+#ifdef __FreeBSD__
+ secs = time_second;
+#else
+ secs = time.tv_sec;
+#endif
+ sp->creation = htonl(secs - st->creation);
if (st->expire <= secs)
sp->expire = htonl(0);
else
sp->expire = htonl(st->expire - secs);
-
- /* do we need to build "compressed" actions for network transfer? */
- if (sc->sc_sync_ifp && compress) {
- switch (action) {
- case PFSYNC_ACT_UPD:
- newaction = PFSYNC_ACT_UPD_C;
- break;
- case PFSYNC_ACT_DEL:
- newaction = PFSYNC_ACT_DEL_C;
- break;
- default:
- /* by default we just send the uncompressed states */
- break;
- }
- }
-
- if (newaction) {
- if (sc->sc_mbuf_net == NULL) {
- if ((sc->sc_mbuf_net = pfsync_get_mbuf(sc, newaction,
- (void *)&sc->sc_statep_net.s)) == NULL) {
- splx(s);
- return (ENOMEM);
- }
- }
- h_net = mtod(sc->sc_mbuf_net, struct pfsync_header *);
-
- switch (newaction) {
- case PFSYNC_ACT_UPD_C:
- if (i != 255) {
- up = (void *)((char *)h_net +
- PFSYNC_HDRLEN + (i * sizeof(*up)));
- up->updates++;
- } else {
- h_net->count++;
- sc->sc_mbuf_net->m_pkthdr.len =
- sc->sc_mbuf_net->m_len += sizeof(*up);
- up = sc->sc_statep_net.u++;
-
- bzero(up, sizeof(*up));
- bcopy(&st->id, up->id, sizeof(up->id));
- up->creatorid = st->creatorid;
- }
- up->timeout = st->timeout;
- up->expire = sp->expire;
- up->src = sp->src;
- up->dst = sp->dst;
- break;
- case PFSYNC_ACT_DEL_C:
- sc->sc_mbuf_net->m_pkthdr.len =
- sc->sc_mbuf_net->m_len += sizeof(*dp);
- dp = sc->sc_statep_net.d++;
- h_net->count++;
-
- bzero(dp, sizeof(*dp));
- bcopy(&st->id, dp->id, sizeof(dp->id));
- dp->creatorid = st->creatorid;
- break;
- }
- }
-
- if (h->count == sc->sc_maxcount ||
- (sc->sc_maxupdates && (sp->updates >= sc->sc_maxupdates)))
+ sp->packets[0] = htonl(st->packets[0]);
+ sp->packets[1] = htonl(st->packets[1]);
+ sp->bytes[0] = htonl(st->bytes[0]);
+ sp->bytes[1] = htonl(st->bytes[1]);
+ if (r == NULL)
+ sp->rule.nr = htonl(-1);
+ else
+ sp->rule.nr = htonl(r->nr);
+ sp->af = st->af;
+ sp->proto = st->proto;
+ sp->direction = st->direction;
+ sp->log = st->log;
+ sp->allow_opts = st->allow_opts;
+
+ ret = 0;
+ if (h->count == sc->sc_count)
ret = pfsync_sendout(sc);
splx(s);
- return (ret);
-}
-
-/* This must be called in splnet() */
-int
-pfsync_request_update(struct pfsync_state_upd *up, struct in_addr *src)
-{
- struct ifnet *ifp = &pfsyncif.sc_if;
- struct pfsync_header *h;
- struct pfsync_softc *sc = ifp->if_softc;
- struct pfsync_state_upd_req *rup;
- int s, ret;
-
- if (sc->sc_mbuf == NULL) {
- if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
- (void *)&sc->sc_statep.s)) == NULL) {
- splx(s);
- return (ENOMEM);
- }
- h = mtod(sc->sc_mbuf, struct pfsync_header *);
- } else {
- h = mtod(sc->sc_mbuf, struct pfsync_header *);
- if (h->action != PFSYNC_ACT_UREQ) {
- pfsync_sendout(sc);
- if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
- (void *)&sc->sc_statep.s)) == NULL) {
- splx(s);
- return (ENOMEM);
- }
- h = mtod(sc->sc_mbuf, struct pfsync_header *);
- }
- }
-
- if (src != NULL)
- sc->sc_sendaddr = *src;
- sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*rup);
- h->count++;
- rup = sc->sc_statep.r++;
- bzero(rup, sizeof(*rup));
- if (up != NULL) {
- bcopy(up->id, rup->id, sizeof(rup->id));
- rup->creatorid = up->creatorid;
- }
-
- if (h->count == sc->sc_maxcount)
- ret = pfsync_sendout(sc);
-
- return (ret);
+ return (0);
}
int
-pfsync_clear_states(u_int32_t creatorid, char *ifname)
+pfsync_clear_state(st)
+ struct pf_state *st;
{
+#ifdef __FreeBSD__
+ struct pfsync_softc *sc = LIST_FIRST(&pfsync_list);
+#else
struct ifnet *ifp = &pfsyncif.sc_if;
struct pfsync_softc *sc = ifp->if_softc;
- struct pfsync_state_clr *cp;
+#endif
+ struct mbuf *m = sc->sc_mbuf;
int s, ret;
s = splnet();
- if (sc->sc_mbuf != NULL)
- pfsync_sendout(sc);
- if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR,
- (void *)&sc->sc_statep.c)) == NULL) {
+ if (m == NULL && (m = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR)) == NULL) {
splx(s);
return (ENOMEM);
}
- sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*cp);
- cp = sc->sc_statep.c;
- cp->creatorid = creatorid;
- if (ifname != NULL)
- strlcpy(cp->ifname, ifname, IFNAMSIZ);
ret = (pfsync_sendout(sc));
splx(s);
@@ -1082,162 +473,76 @@ pfsync_timeout(void *v)
struct pfsync_softc *sc = v;
int s;
+ /* We don't need PF_LOCK/PF_UNLOCK here! */
s = splnet();
pfsync_sendout(sc);
splx(s);
}
-void
-pfsync_send_bus(struct pfsync_softc *sc, u_int8_t status)
-{
- struct pfsync_state_bus *bus;
-
- if (sc->sc_mbuf != NULL)
- pfsync_sendout(sc);
-
- if (pfsync_sync_ok &&
- (sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_BUS,
- (void *)&sc->sc_statep.b)) != NULL) {
- sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*bus);
- bus = sc->sc_statep.b;
- bus->creatorid = pf_status.hostid;
- bus->status = status;
- bus->endtime = htonl(mono_time.tv_sec - sc->sc_ureq_received);
- pfsync_sendout(sc);
- }
-}
-
-void
-pfsync_bulk_update(void *v)
-{
- struct pfsync_softc *sc = v;
- int s, i = 0;
- struct pf_state *state;
-
- s = splnet();
- if (sc->sc_mbuf != NULL)
- pfsync_sendout(sc);
-
- /*
- * Grab at most PFSYNC_BULKPACKETS worth of states which have not
- * been sent since the latest request was made.
- */
- while ((state = TAILQ_FIRST(&state_updates)) != NULL &&
- ++i < (sc->sc_maxcount * PFSYNC_BULKPACKETS)) {
- if (state->pfsync_time > sc->sc_ureq_received) {
- /* we're done */
- pfsync_send_bus(sc, PFSYNC_BUS_END);
- sc->sc_ureq_received = 0;
- timeout_del(&sc->sc_bulk_tmo);
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: bulk update complete\n");
- break;
- } else {
- /* send an update and move to end of list */
- if (!state->sync_flags)
- pfsync_pack_state(PFSYNC_ACT_UPD, state, 0);
- state->pfsync_time = mono_time.tv_sec;
- TAILQ_REMOVE(&state_updates, state, u.s.entry_updates);
- TAILQ_INSERT_TAIL(&state_updates, state,
- u.s.entry_updates);
-
- /* look again for more in a bit */
- timeout_add(&sc->sc_bulk_tmo, 1);
- }
- }
- if (sc->sc_mbuf != NULL)
- pfsync_sendout(sc);
- splx(s);
-}
-
-void
-pfsync_bulkfail(void *v)
-{
- struct pfsync_softc *sc = v;
-
- if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) {
- /* Try again in a bit */
- timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
- pfsync_request_update(NULL, NULL);
- pfsync_sendout(sc);
- } else {
- /* Pretend like the transfer was ok */
- sc->sc_ureq_sent = 0;
- sc->sc_bulk_tries = 0;
- pfsync_sync_ok = 1;
- if (pf_status.debug >= PF_DEBUG_MISC)
- printf("pfsync: failed to receive "
- "bulk update status\n");
- timeout_del(&sc->sc_bulkfail_tmo);
- }
-}
-
int
pfsync_sendout(sc)
struct pfsync_softc *sc;
{
struct ifnet *ifp = &sc->sc_if;
- struct mbuf *m;
+ struct mbuf *m = sc->sc_mbuf;
+#ifdef __FreeBSD__
+ callout_stop(&sc->sc_tmo);
+#else
timeout_del(&sc->sc_tmo);
-
- if (sc->sc_mbuf == NULL)
- return (0);
- m = sc->sc_mbuf;
+#endif
sc->sc_mbuf = NULL;
- sc->sc_statep.s = NULL;
+ sc->sc_ptr = NULL;
+#ifdef __FreeBSD__
+ KASSERT(m != NULL, ("pfsync_sendout: null mbuf"));
+#endif
#if NBPFILTER > 0
if (ifp->if_bpf)
bpf_mtap(ifp->if_bpf, m);
#endif
- if (sc->sc_mbuf_net) {
- m_freem(m);
- m = sc->sc_mbuf_net;
- sc->sc_mbuf_net = NULL;
- sc->sc_statep_net.s = NULL;
- }
+ m_freem(m);
+
+ return (0);
+}
- if (sc->sc_sync_ifp) {
- struct ip *ip;
- struct ifaddr *ifa;
- struct sockaddr sa;
- M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
- if (m == NULL) {
- pfsyncstats.pfsyncs_onomem++;
- return (0);
- }
- ip = mtod(m, struct ip *);
- ip->ip_v = IPVERSION;
- ip->ip_hl = sizeof(*ip) >> 2;
- ip->ip_tos = IPTOS_LOWDELAY;
- ip->ip_len = htons(m->m_pkthdr.len);
- ip->ip_id = htons(ip_randomid());
- ip->ip_off = htons(IP_DF);
- ip->ip_ttl = PFSYNC_DFLTTL;
- ip->ip_p = IPPROTO_PFSYNC;
- ip->ip_sum = 0;
-
- bzero(&sa, sizeof(sa));
- sa.sa_family = AF_INET;
- ifa = ifaof_ifpforaddr(&sa, sc->sc_sync_ifp);
- if (ifa == NULL)
- return (0);
- ip->ip_src.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr;
-
- if (sc->sc_sendaddr.s_addr == INADDR_PFSYNC_GROUP)
- m->m_flags |= M_MCAST;
- ip->ip_dst = sc->sc_sendaddr;
- sc->sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP;
-
- pfsyncstats.pfsyncs_opackets++;
-
- if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))
- pfsyncstats.pfsyncs_oerrors++;
- } else
- m_freem(m);
+#ifdef __FreeBSD__
+static int
+pfsync_modevent(module_t mod, int type, void *data)
+{
+ int error = 0;
- return (0);
+ switch (type) {
+ case MOD_LOAD:
+ LIST_INIT(&pfsync_list);
+ if_clone_attach(&pfsync_cloner);
+ break;
+
+ case MOD_UNLOAD:
+ if_clone_detach(&pfsync_cloner);
+ while (!LIST_EMPTY(&pfsync_list))
+ pfsync_clone_destroy(
+ &LIST_FIRST(&pfsync_list)->sc_if);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return error;
}
+
+static moduledata_t pfsync_mod = {
+ "pfsync",
+ pfsync_modevent,
+ 0
+};
+
+#define PFSYNC_MODVER 1
+
+DECLARE_MODULE(pfsync, pfsync_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+MODULE_VERSION(pfsync, PFSYNC_MODVER);
+#endif /* __FreeBSD__ */
diff --git a/sys/contrib/pf/net/if_pfsync.h b/sys/contrib/pf/net/if_pfsync.h
index b3705c8..23539ba 100644
--- a/sys/contrib/pf/net/if_pfsync.h
+++ b/sys/contrib/pf/net/if_pfsync.h
@@ -1,4 +1,5 @@
-/* $OpenBSD: if_pfsync.h,v 1.13 2004/03/22 04:54:17 mcbride Exp $ */
+/* $FreeBSD$ */
+/* $OpenBSD: if_pfsync.h,v 1.2 2002/12/11 18:31:26 mickey Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@@ -29,208 +30,47 @@
#ifndef _NET_IF_PFSYNC_H_
#define _NET_IF_PFSYNC_H_
-
-#define PFSYNC_ID_LEN sizeof(u_int64_t)
-
-struct pfsync_state_scrub {
- u_int16_t pfss_flags;
- u_int8_t pfss_ttl; /* stashed TTL */
- u_int8_t scrub_flag;
- u_int32_t pfss_ts_mod; /* timestamp modulation */
-} __packed;
-
-struct pfsync_state_host {
- struct pf_addr addr;
- u_int16_t port;
- u_int16_t pad[3];
-} __packed;
-
-struct pfsync_state_peer {
- struct pfsync_state_scrub scrub; /* state is scrubbed */
- u_int32_t seqlo; /* Max sequence number sent */
- u_int32_t seqhi; /* Max the other end ACKd + win */
- u_int32_t seqdiff; /* Sequence number modulator */
- u_int16_t max_win; /* largest window (pre scaling) */
- u_int16_t mss; /* Maximum segment size option */
- u_int8_t state; /* active state level */
- u_int8_t wscale; /* window scaling factor */
- u_int8_t scrub_flag;
- u_int8_t pad[5];
-} __packed;
-
-struct pfsync_state {
- u_int32_t id[2];
- char ifname[IFNAMSIZ];
- struct pfsync_state_host lan;
- struct pfsync_state_host gwy;
- struct pfsync_state_host ext;
- struct pfsync_state_peer src;
- struct pfsync_state_peer dst;
- struct pf_addr rt_addr;
- u_int32_t rule;
- u_int32_t anchor;
- u_int32_t nat_rule;
- u_int32_t creation;
- u_int32_t expire;
- u_int32_t packets[2];
- u_int32_t bytes[2];
- u_int32_t creatorid;
- sa_family_t af;
- u_int8_t proto;
- u_int8_t direction;
- u_int8_t log;
- u_int8_t allow_opts;
- u_int8_t timeout;
- u_int8_t sync_flags;
- u_int8_t updates;
-} __packed;
-
-struct pfsync_state_upd {
- u_int32_t id[2];
- struct pfsync_state_peer src;
- struct pfsync_state_peer dst;
- u_int32_t creatorid;
- u_int32_t expire;
- u_int8_t timeout;
- u_int8_t updates;
- u_int8_t pad[6];
-} __packed;
-
-struct pfsync_state_del {
- u_int32_t id[2];
- u_int32_t creatorid;
- struct {
- u_int8_t state;
- } src;
- struct {
- u_int8_t state;
- } dst;
- u_int8_t pad[2];
-} __packed;
-
-struct pfsync_state_upd_req {
- u_int32_t id[2];
- u_int32_t creatorid;
- u_int32_t pad;
-} __packed;
-
-struct pfsync_state_clr {
- char ifname[IFNAMSIZ];
- u_int32_t creatorid;
- u_int32_t pad;
-} __packed;
-
-struct pfsync_state_bus {
- u_int32_t creatorid;
- u_int32_t endtime;
- u_int8_t status;
-#define PFSYNC_BUS_START 1
-#define PFSYNC_BUS_END 2
- u_int8_t pad[7];
-} __packed;
-
#ifdef _KERNEL
-
-union sc_statep {
- struct pfsync_state *s;
- struct pfsync_state_upd *u;
- struct pfsync_state_del *d;
- struct pfsync_state_clr *c;
- struct pfsync_state_bus *b;
- struct pfsync_state_upd_req *r;
-};
-
-extern int pfsync_sync_ok;
-
struct pfsync_softc {
- struct ifnet sc_if;
- struct ifnet *sc_sync_ifp;
+ struct ifnet sc_if;
- struct ip_moptions sc_imo;
- struct timeout sc_tmo;
- struct timeout sc_bulk_tmo;
- struct timeout sc_bulkfail_tmo;
- struct in_addr sc_sendaddr;
- struct mbuf *sc_mbuf; /* current cummulative mbuf */
- struct mbuf *sc_mbuf_net; /* current cummulative mbuf */
- union sc_statep sc_statep;
- union sc_statep sc_statep_net;
- u_int32_t sc_ureq_received;
- u_int32_t sc_ureq_sent;
- int sc_bulk_tries;
- int sc_maxcount; /* number of states in mtu */
- int sc_maxupdates; /* number of updates/state */
+#ifdef __FreeBSD__
+ struct callout sc_tmo;
+#else
+ struct timeout sc_tmo;
+#endif
+ struct mbuf *sc_mbuf; /* current cummulative mbuf */
+ struct pf_state *sc_ptr; /* current ongoing state */
+ int sc_count; /* number of states in one mtu */
+#ifdef __FreeBSD__
+ LIST_ENTRY(pfsync_softc) sc_next;
+#endif
};
#endif
-
struct pfsync_header {
u_int8_t version;
-#define PFSYNC_VERSION 2
+#define PFSYNC_VERSION 1
u_int8_t af;
u_int8_t action;
-#define PFSYNC_ACT_CLR 0 /* clear all states */
-#define PFSYNC_ACT_INS 1 /* insert state */
-#define PFSYNC_ACT_UPD 2 /* update state */
-#define PFSYNC_ACT_DEL 3 /* delete state */
-#define PFSYNC_ACT_UPD_C 4 /* "compressed" state update */
-#define PFSYNC_ACT_DEL_C 5 /* "compressed" state delete */
-#define PFSYNC_ACT_INS_F 6 /* insert fragment */
-#define PFSYNC_ACT_DEL_F 7 /* delete fragments */
-#define PFSYNC_ACT_UREQ 8 /* request "uncompressed" state */
-#define PFSYNC_ACT_BUS 9 /* Bulk Update Status */
-#define PFSYNC_ACT_MAX 10
+#define PFSYNC_ACT_CLR 0
+#define PFSYNC_ACT_INS 1
+#define PFSYNC_ACT_UPD 2
+#define PFSYNC_ACT_DEL 3
+#define PFSYNC_ACT_MAX 4
u_int8_t count;
-} __packed;
+};
-#define PFSYNC_BULKPACKETS 1 /* # of packets per timeout */
-#define PFSYNC_MAX_BULKTRIES 12
#define PFSYNC_HDRLEN sizeof(struct pfsync_header)
#define PFSYNC_ACTIONS \
- "CLR ST", "INS ST", "UPD ST", "DEL ST", \
- "UPD ST COMP", "DEL ST COMP", "INS FR", "DEL FR", \
- "UPD REQ", "BLK UPD STAT"
-
-#define PFSYNC_DFLTTL 255
-
-struct pfsyncstats {
- u_long pfsyncs_ipackets; /* total input packets, IPv4 */
- u_long pfsyncs_ipackets6; /* total input packets, IPv6 */
- u_long pfsyncs_badif; /* not the right interface */
- u_long pfsyncs_badttl; /* TTL is not PFSYNC_DFLTTL */
- u_long pfsyncs_hdrops; /* packets shorter than header */
- u_long pfsyncs_badver; /* bad (incl unsupp) version */
- u_long pfsyncs_badact; /* bad action */
- u_long pfsyncs_badlen; /* data length does not match */
- u_long pfsyncs_badauth; /* bad authentication */
- u_long pfsyncs_badstate; /* insert/lookup failed */
-
- u_long pfsyncs_opackets; /* total output packets, IPv4 */
- u_long pfsyncs_opackets6; /* total output packets, IPv6 */
- u_long pfsyncs_onomem; /* no memory for an mbuf for a send */
- u_long pfsyncs_oerrors; /* ip output error */
-};
-
-/*
- * Configuration structure for SIOCSETPFSYNC SIOCGETPFSYNC
- */
-struct pfsyncreq {
- char pfsyncr_syncif[IFNAMSIZ];
- int pfsyncr_maxupdates;
- int pfsyncr_authlevel;
-};
-#define SIOCSETPFSYNC _IOW('i', 247, struct ifreq)
-#define SIOCGETPFSYNC _IOWR('i', 248, struct ifreq)
-
+ "CLR ST", "INS ST", "UPD ST", "DEL ST"
#define pf_state_peer_hton(s,d) do { \
(d)->seqlo = htonl((s)->seqlo); \
(d)->seqhi = htonl((s)->seqhi); \
(d)->seqdiff = htonl((s)->seqdiff); \
(d)->max_win = htons((s)->max_win); \
- (d)->mss = htons((s)->mss); \
(d)->state = (s)->state; \
- (d)->wscale = (s)->wscale; \
} while (0)
#define pf_state_peer_ntoh(s,d) do { \
@@ -238,43 +78,15 @@ struct pfsyncreq {
(d)->seqhi = ntohl((s)->seqhi); \
(d)->seqdiff = ntohl((s)->seqdiff); \
(d)->max_win = ntohs((s)->max_win); \
- (d)->mss = ntohs((s)->mss); \
(d)->state = (s)->state; \
- (d)->wscale = (s)->wscale; \
-} while (0)
-
-#define pf_state_host_hton(s,d) do { \
- bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \
- (d)->port = (s)->port; \
-} while (0)
-
-#define pf_state_host_ntoh(s,d) do { \
- bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \
- (d)->port = (s)->port; \
} while (0)
#ifdef _KERNEL
-void pfsync_input(struct mbuf *, ...);
-int pfsync_clear_states(u_int32_t, char *);
-int pfsync_pack_state(u_int8_t, struct pf_state *, int);
-#define pfsync_insert_state(st) do { \
- if ((st->rule.ptr->rule_flag & PFRULE_NOSYNC) || \
- (st->proto == IPPROTO_PFSYNC)) \
- st->sync_flags |= PFSTATE_NOSYNC; \
- else if (!st->sync_flags) \
- pfsync_pack_state(PFSYNC_ACT_INS, (st), 1); \
- st->sync_flags &= ~PFSTATE_FROMSYNC; \
-} while (0)
-#define pfsync_update_state(st) do { \
- if (!st->sync_flags) \
- pfsync_pack_state(PFSYNC_ACT_UPD, (st), 1); \
- st->sync_flags &= ~PFSTATE_FROMSYNC; \
-} while (0)
-#define pfsync_delete_state(st) do { \
- if (!st->sync_flags) \
- pfsync_pack_state(PFSYNC_ACT_DEL, (st), 1); \
- st->sync_flags &= ~PFSTATE_FROMSYNC; \
-} while (0)
+int pfsync_clear_state(struct pf_state *);
+int pfsync_pack_state(u_int8_t, struct pf_state *);
+#define pfsync_insert_state(st) pfsync_pack_state(PFSYNC_ACT_INS, (st))
+#define pfsync_update_state(st) pfsync_pack_state(PFSYNC_ACT_UPD, (st))
+#define pfsync_delete_state(st) pfsync_pack_state(PFSYNC_ACT_DEL, (st))
#endif
#endif /* _NET_IF_PFSYNC_H_ */
diff --git a/sys/contrib/pf/net/pf.c b/sys/contrib/pf/net/pf.c
index 82113ec..46f45c8 100644
--- a/sys/contrib/pf/net/pf.c
+++ b/sys/contrib/pf/net/pf.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: pf.c,v 1.433 2004/03/26 22:20:57 dhartmei Exp $ */
+/* $FreeBSD$ */
+/* $OpenBSD: pf.c,v 1.389.2.4 2004/04/30 23:27:57 brad Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
- * Copyright (c) 2002,2003 Henning Brauer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,9 +35,22 @@
*
*/
+#ifdef __FreeBSD__
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#endif
+
+#ifdef __FreeBSD__
+#include "opt_bpf.h"
+#include "opt_pf.h"
+#define NBPFILTER DEV_BPF
+#define NPFLOG DEV_PFLOG
+#define NPFSYNC DEV_PFSYNC
+#else
#include "bpfilter.h"
#include "pflog.h"
#include "pfsync.h"
+#endif
#include <sys/param.h>
#include <sys/systm.h>
@@ -47,7 +60,11 @@
#include <sys/socketvar.h>
#include <sys/kernel.h>
#include <sys/time.h>
+#ifdef __FreeBSD__
+#include <sys/sysctl.h>
+#else
#include <sys/pool.h>
+#endif
#include <net/if.h>
#include <net/if_types.h>
@@ -69,23 +86,48 @@
#include <netinet/udp_var.h>
#include <netinet/icmp_var.h>
+#ifndef __FreeBSD__
#include <dev/rndvar.h>
+#endif
#include <net/pfvar.h>
#include <net/if_pflog.h>
-
-#if NPFSYNC > 0
#include <net/if_pfsync.h>
-#endif /* NPFSYNC > 0 */
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet/in_pcb.h>
#include <netinet/icmp6.h>
#include <netinet6/nd6.h>
+#ifdef __FreeBSD__
+#include <netinet6/ip6_var.h>
+#include <netinet6/in6_pcb.h>
+#endif
#endif /* INET6 */
+#ifdef ALTQ
+#include <altq/if_altq.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <machine/in_cksum.h>
+#if (__FreeBSD_version >= 500112)
+#include <sys/limits.h>
+#else
+#include <machine/limits.h>
+#endif
+#include <sys/ucred.h>
+#endif
+
+#ifdef __FreeBSD__
+extern int ip_optcopy(struct ip *, struct ip *);
+#if (__FreeBSD_version < 501105)
+int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
+ u_long if_hwassist_flags, int sw_csum);
+#endif
+#endif
#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
+struct pf_state_tree;
/*
* Global variables
@@ -98,17 +140,31 @@ struct pf_palist pf_pabuf;
struct pf_altqqueue *pf_altqs_active;
struct pf_altqqueue *pf_altqs_inactive;
struct pf_status pf_status;
+struct ifnet *status_ifp;
u_int32_t ticket_altqs_active;
u_int32_t ticket_altqs_inactive;
-int altqs_inactive_open;
u_int32_t ticket_pabuf;
+#ifdef __FreeBSD__
+struct callout pf_expire_to; /* expire timeout */
+#else
struct timeout pf_expire_to; /* expire timeout */
+#endif
+
-struct pool pf_src_tree_pl, pf_rule_pl;
+#ifdef __FreeBSD__
+uma_zone_t pf_tree_pl, pf_rule_pl, pf_addr_pl;
+uma_zone_t pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
+#else
+struct pool pf_tree_pl, pf_rule_pl, pf_addr_pl;
struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
+#endif
+void pf_dynaddr_update(void *);
+#ifdef __FreeBSD__
+void pf_dynaddr_update_event(void *arg, struct ifnet *ifp);
+#endif
void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
void pf_print_state(struct pf_state *);
void pf_print_flags(u_int8_t);
@@ -133,62 +189,62 @@ void pf_send_tcp(const struct pf_rule *, sa_family_t,
void pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t,
sa_family_t, struct pf_rule *);
struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *,
- int, int, struct pfi_kif *,
+ int, int, struct ifnet *,
struct pf_addr *, u_int16_t, struct pf_addr *,
u_int16_t, int);
struct pf_rule *pf_get_translation(struct pf_pdesc *, struct mbuf *,
- int, int, struct pfi_kif *, struct pf_src_node **,
+ int, int, struct ifnet *,
struct pf_addr *, u_int16_t,
struct pf_addr *, u_int16_t,
struct pf_addr *, u_int16_t *);
int pf_test_tcp(struct pf_rule **, struct pf_state **,
- int, struct pfi_kif *, struct mbuf *, int,
+ int, struct ifnet *, struct mbuf *, int, int,
void *, struct pf_pdesc *, struct pf_rule **,
struct pf_ruleset **);
int pf_test_udp(struct pf_rule **, struct pf_state **,
- int, struct pfi_kif *, struct mbuf *, int,
+ int, struct ifnet *, struct mbuf *, int, int,
void *, struct pf_pdesc *, struct pf_rule **,
struct pf_ruleset **);
int pf_test_icmp(struct pf_rule **, struct pf_state **,
- int, struct pfi_kif *, struct mbuf *, int,
+ int, struct ifnet *, struct mbuf *, int, int,
void *, struct pf_pdesc *, struct pf_rule **,
struct pf_ruleset **);
int pf_test_other(struct pf_rule **, struct pf_state **,
- int, struct pfi_kif *, struct mbuf *, int, void *,
+ int, struct ifnet *, struct mbuf *, int, void *,
struct pf_pdesc *, struct pf_rule **,
struct pf_ruleset **);
int pf_test_fragment(struct pf_rule **, int,
- struct pfi_kif *, struct mbuf *, void *,
+ struct ifnet *, struct mbuf *, void *,
struct pf_pdesc *, struct pf_rule **,
struct pf_ruleset **);
int pf_test_state_tcp(struct pf_state **, int,
- struct pfi_kif *, struct mbuf *, int,
+ struct ifnet *, struct mbuf *, int, int,
void *, struct pf_pdesc *, u_short *);
int pf_test_state_udp(struct pf_state **, int,
- struct pfi_kif *, struct mbuf *, int,
+ struct ifnet *, struct mbuf *, int, int,
void *, struct pf_pdesc *);
int pf_test_state_icmp(struct pf_state **, int,
- struct pfi_kif *, struct mbuf *, int,
+ struct ifnet *, struct mbuf *, int, int,
void *, struct pf_pdesc *);
int pf_test_state_other(struct pf_state **, int,
- struct pfi_kif *, struct pf_pdesc *);
+ struct ifnet *, struct pf_pdesc *);
struct pf_tag *pf_get_tag(struct mbuf *);
int pf_match_tag(struct mbuf *, struct pf_rule *,
- struct pf_rule *, struct pf_tag *, int *);
+ struct pf_rule *, struct pf_rule *,
+ struct pf_tag *, int *);
void pf_hash(struct pf_addr *, struct pf_addr *,
struct pf_poolhashkey *, sa_family_t);
-int pf_map_addr(u_int8_t, struct pf_rule *,
+int pf_map_addr(u_int8_t, struct pf_pool *,
struct pf_addr *, struct pf_addr *,
- struct pf_addr *, struct pf_src_node **);
-int pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *,
+ struct pf_addr *);
+int pf_get_sport(sa_family_t, u_int8_t, struct pf_pool *,
struct pf_addr *, struct pf_addr *, u_int16_t,
- struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t,
- struct pf_src_node **);
+ struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t);
void pf_route(struct mbuf **, struct pf_rule *, int,
struct ifnet *, struct pf_state *);
void pf_route6(struct mbuf **, struct pf_rule *, int,
struct ifnet *, struct pf_state *);
-int pf_socket_lookup(uid_t *, gid_t *,
+int pf_socket_lookup(uid_t *, gid_t *, int, sa_family_t,
int, struct pf_pdesc *);
u_int8_t pf_get_wscale(struct mbuf *, int, u_int16_t,
sa_family_t);
@@ -202,24 +258,22 @@ int pf_check_proto_cksum(struct mbuf *, int, int,
u_int8_t, sa_family_t);
int pf_addr_wrap_neq(struct pf_addr_wrap *,
struct pf_addr_wrap *);
-static int pf_add_mbuf_tag(struct mbuf *, u_int);
-struct pf_state *pf_find_state_recurse(struct pfi_kif *,
- struct pf_state *, u_int8_t);
-struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
- { &pf_state_pl, PFSTATE_HIWAT },
- { &pf_src_tree_pl, PFSNODE_HIWAT },
- { &pf_frent_pl, PFFRAG_FRENT_HIWAT }
-};
+#ifdef __FreeBSD__
+int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len);
+
+struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX];
+#else
+struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] =
+ { { &pf_state_pl, PFSTATE_HIWAT }, { &pf_frent_pl, PFFRAG_FRENT_HIWAT } };
+#endif
#define STATE_LOOKUP() \
do { \
if (direction == PF_IN) \
- *state = pf_find_state_recurse( \
- kif, &key, PF_EXT_GWY); \
+ *state = pf_find_state(&tree_ext_gwy, &key); \
else \
- *state = pf_find_state_recurse( \
- kif, &key, PF_LAN_EXT); \
+ *state = pf_find_state(&tree_lan_ext, &key); \
if (*state == NULL) \
return (PF_DROP); \
if (direction == PF_OUT && \
@@ -227,8 +281,8 @@ struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
(*state)->rule.ptr->direction == PF_OUT) || \
((*state)->rule.ptr->rt == PF_REPLYTO && \
(*state)->rule.ptr->direction == PF_IN)) && \
- (*state)->rt_kif != NULL && \
- (*state)->rt_kif != kif) \
+ (*state)->rt_ifp != NULL && \
+ (*state)->rt_ifp != ifp) \
return (PF_PASS); \
} while (0)
@@ -240,145 +294,18 @@ struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
(s)->lan.addr.addr32[3] != (s)->gwy.addr.addr32[3])) || \
(s)->lan.port != (s)->gwy.port
-#define BOUND_IFACE(r, k) (((r)->rule_flag & PFRULE_IFBOUND) ? (k) : \
- ((r)->rule_flag & PFRULE_GRBOUND) ? (k)->pfik_parent : \
- (k)->pfik_parent->pfik_parent)
-
-static __inline int pf_src_compare(struct pf_src_node *, struct pf_src_node *);
-static __inline int pf_state_compare_lan_ext(struct pf_state *,
- struct pf_state *);
-static __inline int pf_state_compare_ext_gwy(struct pf_state *,
- struct pf_state *);
-static __inline int pf_state_compare_id(struct pf_state *,
- struct pf_state *);
-
-struct pf_src_tree tree_src_tracking;
-
-struct pf_state_tree_id tree_id;
-struct pf_state_queue state_updates;
-
-RB_GENERATE(pf_src_tree, pf_src_node, entry, pf_src_compare);
-RB_GENERATE(pf_state_tree_lan_ext, pf_state,
- u.s.entry_lan_ext, pf_state_compare_lan_ext);
-RB_GENERATE(pf_state_tree_ext_gwy, pf_state,
- u.s.entry_ext_gwy, pf_state_compare_ext_gwy);
-RB_GENERATE(pf_state_tree_id, pf_state,
- u.s.entry_id, pf_state_compare_id);
-
-static __inline int
-pf_src_compare(struct pf_src_node *a, struct pf_src_node *b)
-{
- int diff;
-
- if (a->rule.ptr > b->rule.ptr)
- return (1);
- if (a->rule.ptr < b->rule.ptr)
- return (-1);
- if ((diff = a->af - b->af) != 0)
- return (diff);
- switch (a->af) {
-#ifdef INET
- case AF_INET:
- if (a->addr.addr32[0] > b->addr.addr32[0])
- return (1);
- if (a->addr.addr32[0] < b->addr.addr32[0])
- return (-1);
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- if (a->addr.addr32[3] > b->addr.addr32[3])
- return (1);
- if (a->addr.addr32[3] < b->addr.addr32[3])
- return (-1);
- if (a->addr.addr32[2] > b->addr.addr32[2])
- return (1);
- if (a->addr.addr32[2] < b->addr.addr32[2])
- return (-1);
- if (a->addr.addr32[1] > b->addr.addr32[1])
- return (1);
- if (a->addr.addr32[1] < b->addr.addr32[1])
- return (-1);
- if (a->addr.addr32[0] > b->addr.addr32[0])
- return (1);
- if (a->addr.addr32[0] < b->addr.addr32[0])
- return (-1);
- break;
-#endif /* INET6 */
- }
- return (0);
-}
+static __inline int pf_state_compare(struct pf_tree_node *,
+ struct pf_tree_node *);
-static __inline int
-pf_state_compare_lan_ext(struct pf_state *a, struct pf_state *b)
-{
- int diff;
-
- if ((diff = a->proto - b->proto) != 0)
- return (diff);
- if ((diff = a->af - b->af) != 0)
- return (diff);
- switch (a->af) {
-#ifdef INET
- case AF_INET:
- if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0])
- return (1);
- if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0])
- return (-1);
- if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
- return (1);
- if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
- return (-1);
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- if (a->lan.addr.addr32[3] > b->lan.addr.addr32[3])
- return (1);
- if (a->lan.addr.addr32[3] < b->lan.addr.addr32[3])
- return (-1);
- if (a->ext.addr.addr32[3] > b->ext.addr.addr32[3])
- return (1);
- if (a->ext.addr.addr32[3] < b->ext.addr.addr32[3])
- return (-1);
- if (a->lan.addr.addr32[2] > b->lan.addr.addr32[2])
- return (1);
- if (a->lan.addr.addr32[2] < b->lan.addr.addr32[2])
- return (-1);
- if (a->ext.addr.addr32[2] > b->ext.addr.addr32[2])
- return (1);
- if (a->ext.addr.addr32[2] < b->ext.addr.addr32[2])
- return (-1);
- if (a->lan.addr.addr32[1] > b->lan.addr.addr32[1])
- return (1);
- if (a->lan.addr.addr32[1] < b->lan.addr.addr32[1])
- return (-1);
- if (a->ext.addr.addr32[1] > b->ext.addr.addr32[1])
- return (1);
- if (a->ext.addr.addr32[1] < b->ext.addr.addr32[1])
- return (-1);
- if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0])
- return (1);
- if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0])
- return (-1);
- if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
- return (1);
- if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
- return (-1);
- break;
-#endif /* INET6 */
- }
-
- if ((diff = a->lan.port - b->lan.port) != 0)
- return (diff);
- if ((diff = a->ext.port - b->ext.port) != 0)
- return (diff);
-
- return (0);
-}
+struct pf_state_tree tree_lan_ext, tree_ext_gwy;
+RB_GENERATE(pf_state_tree, pf_tree_node, entry, pf_state_compare);
+#ifdef __FreeBSD__
+static int
+#else
static __inline int
-pf_state_compare_ext_gwy(struct pf_state *a, struct pf_state *b)
+#endif
+pf_state_compare(struct pf_tree_node *a, struct pf_tree_node *b)
{
int diff;
@@ -389,77 +316,62 @@ pf_state_compare_ext_gwy(struct pf_state *a, struct pf_state *b)
switch (a->af) {
#ifdef INET
case AF_INET:
- if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
+ if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
return (1);
- if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
+ if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
return (-1);
- if (a->gwy.addr.addr32[0] > b->gwy.addr.addr32[0])
+ if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
return (1);
- if (a->gwy.addr.addr32[0] < b->gwy.addr.addr32[0])
+ if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
return (-1);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- if (a->ext.addr.addr32[3] > b->ext.addr.addr32[3])
+ if (a->addr[0].addr32[3] > b->addr[0].addr32[3])
return (1);
- if (a->ext.addr.addr32[3] < b->ext.addr.addr32[3])
+ if (a->addr[0].addr32[3] < b->addr[0].addr32[3])
return (-1);
- if (a->gwy.addr.addr32[3] > b->gwy.addr.addr32[3])
+ if (a->addr[1].addr32[3] > b->addr[1].addr32[3])
return (1);
- if (a->gwy.addr.addr32[3] < b->gwy.addr.addr32[3])
+ if (a->addr[1].addr32[3] < b->addr[1].addr32[3])
return (-1);
- if (a->ext.addr.addr32[2] > b->ext.addr.addr32[2])
+ if (a->addr[0].addr32[2] > b->addr[0].addr32[2])
return (1);
- if (a->ext.addr.addr32[2] < b->ext.addr.addr32[2])
+ if (a->addr[0].addr32[2] < b->addr[0].addr32[2])
return (-1);
- if (a->gwy.addr.addr32[2] > b->gwy.addr.addr32[2])
+ if (a->addr[1].addr32[2] > b->addr[1].addr32[2])
return (1);
- if (a->gwy.addr.addr32[2] < b->gwy.addr.addr32[2])
+ if (a->addr[1].addr32[2] < b->addr[1].addr32[2])
return (-1);
- if (a->ext.addr.addr32[1] > b->ext.addr.addr32[1])
+ if (a->addr[0].addr32[1] > b->addr[0].addr32[1])
return (1);
- if (a->ext.addr.addr32[1] < b->ext.addr.addr32[1])
+ if (a->addr[0].addr32[1] < b->addr[0].addr32[1])
return (-1);
- if (a->gwy.addr.addr32[1] > b->gwy.addr.addr32[1])
+ if (a->addr[1].addr32[1] > b->addr[1].addr32[1])
return (1);
- if (a->gwy.addr.addr32[1] < b->gwy.addr.addr32[1])
+ if (a->addr[1].addr32[1] < b->addr[1].addr32[1])
return (-1);
- if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
+ if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
return (1);
- if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
+ if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
return (-1);
- if (a->gwy.addr.addr32[0] > b->gwy.addr.addr32[0])
+ if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
return (1);
- if (a->gwy.addr.addr32[0] < b->gwy.addr.addr32[0])
+ if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
return (-1);
break;
#endif /* INET6 */
}
- if ((diff = a->ext.port - b->ext.port) != 0)
+ if ((diff = a->port[0] - b->port[0]) != 0)
return (diff);
- if ((diff = a->gwy.port - b->gwy.port) != 0)
+ if ((diff = a->port[1] - b->port[1]) != 0)
return (diff);
return (0);
}
-static __inline int
-pf_state_compare_id(struct pf_state *a, struct pf_state *b)
-{
- if (a->id > b->id)
- return (1);
- if (a->id < b->id)
- return (-1);
- if (a->creatorid > b->creatorid)
- return (1);
- if (a->creatorid < b->creatorid)
- return (-1);
-
- return (0);
-}
-
#ifdef INET6
void
pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af)
@@ -481,140 +393,36 @@ pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af)
#endif
struct pf_state *
-pf_find_state_byid(struct pf_state *key)
+pf_find_state(struct pf_state_tree *tree, struct pf_tree_node *key)
{
- pf_status.fcounters[FCNT_STATE_SEARCH]++;
- return (RB_FIND(pf_state_tree_id, &tree_id, key));
-}
-
-struct pf_state *
-pf_find_state_recurse(struct pfi_kif *kif, struct pf_state *key, u_int8_t tree)
-{
- struct pf_state *s;
+ struct pf_tree_node *k;
pf_status.fcounters[FCNT_STATE_SEARCH]++;
-
- switch (tree) {
- case PF_LAN_EXT:
- for (; kif != NULL; kif = kif->pfik_parent) {
- s = RB_FIND(pf_state_tree_lan_ext,
- &kif->pfik_lan_ext, key);
- if (s != NULL)
- return (s);
- }
- return (NULL);
- case PF_EXT_GWY:
- for (; kif != NULL; kif = kif->pfik_parent) {
- s = RB_FIND(pf_state_tree_ext_gwy,
- &kif->pfik_ext_gwy, key);
- if (s != NULL)
- return (s);
- }
+ k = RB_FIND(pf_state_tree, tree, key);
+ if (k)
+ return (k->state);
+ else
return (NULL);
- default:
- panic("pf_find_state_recurse");
- }
-}
-
-struct pf_state *
-pf_find_state_all(struct pf_state *key, u_int8_t tree, int *more)
-{
- struct pf_state *s, *ss = NULL;
- struct pfi_kif *kif;
-
- pf_status.fcounters[FCNT_STATE_SEARCH]++;
-
- switch (tree) {
- case PF_LAN_EXT:
- TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) {
- s = RB_FIND(pf_state_tree_lan_ext,
- &kif->pfik_lan_ext, key);
- if (s == NULL)
- continue;
- if (more == NULL)
- return (s);
- ss = s;
- (*more)++;
- }
- return (ss);
- case PF_EXT_GWY:
- TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) {
- s = RB_FIND(pf_state_tree_ext_gwy,
- &kif->pfik_ext_gwy, key);
- if (s == NULL)
- continue;
- if (more == NULL)
- return (s);
- ss = s;
- (*more)++;
- }
- return (ss);
- default:
- panic("pf_find_state_all");
- }
}
int
-pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
- struct pf_addr *src, sa_family_t af)
+pf_insert_state(struct pf_state *state)
{
- struct pf_src_node k;
-
- if (*sn == NULL) {
- k.af = af;
- PF_ACPY(&k.addr, src, af);
- if (rule->rule_flag & PFRULE_RULESRCTRACK ||
- rule->rpool.opts & PF_POOL_STICKYADDR)
- k.rule.ptr = rule;
- else
- k.rule.ptr = NULL;
- pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
- *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
- }
- if (*sn == NULL) {
- if (!rule->max_src_nodes ||
- rule->src_nodes < rule->max_src_nodes)
- (*sn) = pool_get(&pf_src_tree_pl, PR_NOWAIT);
- if ((*sn) == NULL)
- return (-1);
- bzero(*sn, sizeof(struct pf_src_node));
- (*sn)->af = af;
- if (rule->rule_flag & PFRULE_RULESRCTRACK ||
- rule->rpool.opts & PF_POOL_STICKYADDR)
- (*sn)->rule.ptr = rule;
- else
- (*sn)->rule.ptr = NULL;
- PF_ACPY(&(*sn)->addr, src, af);
- if (RB_INSERT(pf_src_tree,
- &tree_src_tracking, *sn) != NULL) {
- if (pf_status.debug >= PF_DEBUG_MISC) {
- printf("pf: src_tree insert failed: ");
- pf_print_host(&(*sn)->addr, 0, af);
- printf("\n");
- }
- pool_put(&pf_src_tree_pl, *sn);
- return (-1);
- }
- (*sn)->creation = time.tv_sec;
- (*sn)->ruletype = rule->action;
- if ((*sn)->rule.ptr != NULL)
- (*sn)->rule.ptr->src_nodes++;
- pf_status.scounters[SCNT_SRC_NODE_INSERT]++;
- pf_status.src_nodes++;
- } else {
- if (rule->max_src_states &&
- (*sn)->states >= rule->max_src_states)
- return (-1);
- }
- return (0);
-}
+ struct pf_tree_node *keya, *keyb;
+
+ keya = pool_get(&pf_tree_pl, PR_NOWAIT);
+ if (keya == NULL)
+ return (-1);
+ keya->state = state;
+ keya->proto = state->proto;
+ keya->af = state->af;
+ PF_ACPY(&keya->addr[0], &state->lan.addr, state->af);
+ keya->port[0] = state->lan.port;
+ PF_ACPY(&keya->addr[1], &state->ext.addr, state->af);
+ keya->port[1] = state->ext.port;
-int
-pf_insert_state(struct pfi_kif *kif, struct pf_state *state)
-{
/* Thou MUST NOT insert multiple duplicate keys */
- state->u.s.kif = kif;
- if (RB_INSERT(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state)) {
+ if (RB_INSERT(pf_state_tree, &tree_lan_ext, keya) != NULL) {
if (pf_status.debug >= PF_DEBUG_MISC) {
printf("pf: state insert failed: tree_lan_ext");
printf(" lan: ");
@@ -626,14 +434,28 @@ pf_insert_state(struct pfi_kif *kif, struct pf_state *state)
printf(" ext: ");
pf_print_host(&state->ext.addr, state->ext.port,
state->af);
- if (state->sync_flags & PFSTATE_FROMSYNC)
- printf(" (from sync)");
printf("\n");
}
+ pool_put(&pf_tree_pl, keya);
+ return (-1);
+ }
+
+ keyb = pool_get(&pf_tree_pl, PR_NOWAIT);
+ if (keyb == NULL) {
+ /* Need to pull out the other state */
+ RB_REMOVE(pf_state_tree, &tree_lan_ext, keya);
+ pool_put(&pf_tree_pl, keya);
return (-1);
}
+ keyb->state = state;
+ keyb->proto = state->proto;
+ keyb->af = state->af;
+ PF_ACPY(&keyb->addr[0], &state->ext.addr, state->af);
+ keyb->port[0] = state->ext.port;
+ PF_ACPY(&keyb->addr[1], &state->gwy.addr, state->af);
+ keyb->port[1] = state->gwy.port;
- if (RB_INSERT(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy, state)) {
+ if (RB_INSERT(pf_state_tree, &tree_ext_gwy, keyb) != NULL) {
if (pf_status.debug >= PF_DEBUG_MISC) {
printf("pf: state insert failed: tree_ext_gwy");
printf(" lan: ");
@@ -645,36 +467,16 @@ pf_insert_state(struct pfi_kif *kif, struct pf_state *state)
printf(" ext: ");
pf_print_host(&state->ext.addr, state->ext.port,
state->af);
- if (state->sync_flags & PFSTATE_FROMSYNC)
- printf(" (from sync)");
printf("\n");
}
- RB_REMOVE(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state);
+ RB_REMOVE(pf_state_tree, &tree_lan_ext, keya);
+ pool_put(&pf_tree_pl, keya);
+ pool_put(&pf_tree_pl, keyb);
return (-1);
}
- if (state->id == 0 && state->creatorid == 0) {
- state->id = htobe64(pf_status.stateid++);
- state->creatorid = pf_status.hostid;
- }
- if (RB_INSERT(pf_state_tree_id, &tree_id, state) != NULL) {
- if (pf_status.debug >= PF_DEBUG_MISC) {
- printf("pf: state insert failed: "
- "id: %016llx creatorid: %08x",
- betoh64(state->id), ntohl(state->creatorid));
- if (state->sync_flags & PFSTATE_FROMSYNC)
- printf(" (from sync)");
- printf("\n");
- }
- RB_REMOVE(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state);
- RB_REMOVE(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy, state);
- return (-1);
- }
- TAILQ_INSERT_HEAD(&state_updates, state, u.s.entry_updates);
-
pf_status.fcounters[FCNT_STATE_INSERT]++;
pf_status.states++;
- pfi_attach_state(kif);
#if NPFSYNC
pfsync_insert_state(state);
#endif
@@ -684,16 +486,30 @@ pf_insert_state(struct pfi_kif *kif, struct pf_state *state)
void
pf_purge_timeout(void *arg)
{
+#ifdef __FreeBSD__
+ struct callout *to = arg;
+#else
struct timeout *to = arg;
+#endif
int s;
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
s = splsoftnet();
pf_purge_expired_states();
pf_purge_expired_fragments();
- pf_purge_expired_src_nodes();
splx(s);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+#ifdef __FreeBSD__
+ callout_reset(to, pf_default_rule.timeout[PFTM_INTERVAL] * hz,
+ pf_purge_timeout, to);
+#else
timeout_add(to, pf_default_rule.timeout[PFTM_INTERVAL] * hz);
+#endif
}
u_int32_t
@@ -706,10 +522,19 @@ pf_state_expires(const struct pf_state *state)
/* handle all PFTM_* > PFTM_MAX here */
if (state->timeout == PFTM_PURGE)
+#ifdef __FreeBSD__
+ return (time_second);
+#else
return (time.tv_sec);
+#endif
if (state->timeout == PFTM_UNTIL_PACKET)
return (0);
+#ifdef __FreeBSD__
+ KASSERT((state->timeout < PFTM_MAX),
+ ("pf_state_expires: timeout > PFTM_MAX"));
+#else
KASSERT(state->timeout < PFTM_MAX);
+#endif
timeout = state->rule.ptr->timeout[state->timeout];
if (!timeout)
timeout = pf_default_rule.timeout[state->timeout];
@@ -727,99 +552,81 @@ pf_state_expires(const struct pf_state *state)
return (state->expire + timeout * (end - states) /
(end - start));
else
+#ifdef __FreeBSD__
+ return (time_second);
+#else
return (time.tv_sec);
+#endif
}
return (state->expire + timeout);
}
void
-pf_purge_expired_src_nodes(void)
+pf_purge_expired_states(void)
{
- struct pf_src_node *cur, *next;
-
- for (cur = RB_MIN(pf_src_tree, &tree_src_tracking); cur; cur = next) {
- next = RB_NEXT(pf_src_tree, &tree_src_tracking, cur);
-
- if (cur->states <= 0 && cur->expire <= time.tv_sec) {
- if (cur->rule.ptr != NULL) {
- cur->rule.ptr->src_nodes--;
- if (cur->rule.ptr->states <= 0 &&
- cur->rule.ptr->max_src_nodes <= 0)
- pf_rm_rule(NULL, cur->rule.ptr);
- }
- RB_REMOVE(pf_src_tree, &tree_src_tracking, cur);
- pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
- pf_status.src_nodes--;
- pool_put(&pf_src_tree_pl, cur);
- }
- }
-}
+ struct pf_tree_node *cur, *peer, *next;
+ struct pf_tree_node key;
-void
-pf_src_tree_remove_state(struct pf_state *s)
-{
- u_int32_t timeout;
-
- if (s->src_node != NULL) {
- if (--s->src_node->states <= 0) {
- timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
- if (!timeout)
- timeout =
- pf_default_rule.timeout[PFTM_SRC_NODE];
- s->src_node->expire = time.tv_sec + timeout;
- }
- }
- if (s->nat_src_node != s->src_node && s->nat_src_node != NULL) {
- if (--s->nat_src_node->states <= 0) {
- timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
- if (!timeout)
- timeout =
- pf_default_rule.timeout[PFTM_SRC_NODE];
- s->nat_src_node->expire = time.tv_sec + timeout;
- }
- }
- s->src_node = s->nat_src_node = NULL;
-}
+ for (cur = RB_MIN(pf_state_tree, &tree_ext_gwy); cur; cur = next) {
+ next = RB_NEXT(pf_state_tree, &tree_ext_gwy, cur);
-void
-pf_purge_expired_states(void)
-{
- struct pf_state *cur, *next;
-
- for (cur = RB_MIN(pf_state_tree_id, &tree_id);
- cur; cur = next) {
- next = RB_NEXT(pf_state_tree_id, &tree_id, cur);
-
- if (pf_state_expires(cur) <= time.tv_sec) {
- if (cur->src.state == PF_TCPS_PROXY_DST)
- pf_send_tcp(cur->rule.ptr, cur->af,
- &cur->ext.addr, &cur->lan.addr,
- cur->ext.port, cur->lan.port,
- cur->src.seqhi, cur->src.seqlo + 1, 0,
+#ifdef __FreeBSD__
+ if (pf_state_expires(cur->state) <= (u_int32_t)time_second) {
+#else
+ if (pf_state_expires(cur->state) <= time.tv_sec) {
+#endif
+ if (cur->state->src.state == PF_TCPS_PROXY_DST)
+ pf_send_tcp(cur->state->rule.ptr,
+ cur->state->af,
+ &cur->state->ext.addr,
+ &cur->state->lan.addr,
+ cur->state->ext.port,
+ cur->state->lan.port,
+ cur->state->src.seqhi,
+ cur->state->src.seqlo + 1,
+ 0,
TH_RST|TH_ACK, 0, 0);
- RB_REMOVE(pf_state_tree_ext_gwy,
- &cur->u.s.kif->pfik_ext_gwy, cur);
- RB_REMOVE(pf_state_tree_lan_ext,
- &cur->u.s.kif->pfik_lan_ext, cur);
- RB_REMOVE(pf_state_tree_id, &tree_id, cur);
+ RB_REMOVE(pf_state_tree, &tree_ext_gwy, cur);
+
+ /* Need this key's peer (in the other tree) */
+ key.state = cur->state;
+ key.proto = cur->state->proto;
+ key.af = cur->state->af;
+ PF_ACPY(&key.addr[0], &cur->state->lan.addr,
+ cur->state->af);
+ key.port[0] = cur->state->lan.port;
+ PF_ACPY(&key.addr[1], &cur->state->ext.addr,
+ cur->state->af);
+ key.port[1] = cur->state->ext.port;
+
+ peer = RB_FIND(pf_state_tree, &tree_lan_ext, &key);
+#ifdef __FreeBSD__
+ KASSERT((peer), ("peer null :%s", __FUNCTION__));
+ KASSERT((peer->state == cur->state),
+ ("peer->state != cur->state: %s", __FUNCTION__));
+#else
+ KASSERT(peer);
+ KASSERT(peer->state == cur->state);
+#endif
+ RB_REMOVE(pf_state_tree, &tree_lan_ext, peer);
+
#if NPFSYNC
- pfsync_delete_state(cur);
+ pfsync_delete_state(cur->state);
#endif
- pf_src_tree_remove_state(cur);
- if (--cur->rule.ptr->states <= 0 &&
- cur->rule.ptr->src_nodes <= 0)
- pf_rm_rule(NULL, cur->rule.ptr);
- if (cur->nat_rule.ptr != NULL)
- if (--cur->nat_rule.ptr->states <= 0 &&
- cur->nat_rule.ptr->src_nodes <= 0)
- pf_rm_rule(NULL, cur->nat_rule.ptr);
- if (cur->anchor.ptr != NULL)
- if (--cur->anchor.ptr->states <= 0)
- pf_rm_rule(NULL, cur->anchor.ptr);
- pf_normalize_tcp_cleanup(cur);
- pfi_detach_state(cur->u.s.kif);
- TAILQ_REMOVE(&state_updates, cur, u.s.entry_updates);
- pool_put(&pf_state_pl, cur);
+ if (--cur->state->rule.ptr->states <= 0)
+ pf_rm_rule(NULL, cur->state->rule.ptr);
+ if (cur->state->nat_rule.ptr != NULL)
+ if (--cur->state->nat_rule.ptr->states <= 0)
+ pf_rm_rule(NULL,
+ cur->state->nat_rule.ptr);
+ if (cur->state->anchor.ptr != NULL)
+ if (--cur->state->anchor.ptr->states <= 0)
+ pf_rm_rule(NULL,
+ cur->state->anchor.ptr);
+ pf_normalize_tcp_cleanup(cur->state);
+ pool_put(&pf_state_pl, cur->state);
+ pool_put(&pf_tree_pl, cur);
+ pool_put(&pf_tree_pl, peer);
pf_status.fcounters[FCNT_STATE_REMOVALS]++;
pf_status.states--;
}
@@ -859,6 +666,129 @@ pf_tbladdr_copyout(struct pf_addr_wrap *aw)
kt->pfrkt_cnt : -1;
}
+int
+pf_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
+{
+ if (aw->type != PF_ADDR_DYNIFTL)
+ return (0);
+ aw->p.dyn = pool_get(&pf_addr_pl, PR_NOWAIT);
+ if (aw->p.dyn == NULL)
+ return (1);
+ bcopy(aw->v.ifname, aw->p.dyn->ifname, sizeof(aw->p.dyn->ifname));
+ aw->p.dyn->ifp = ifunit(aw->p.dyn->ifname);
+ if (aw->p.dyn->ifp == NULL) {
+ pool_put(&pf_addr_pl, aw->p.dyn);
+ aw->p.dyn = NULL;
+ return (1);
+ }
+ aw->p.dyn->addr = &aw->v.a.addr;
+ aw->p.dyn->af = af;
+ aw->p.dyn->undefined = 1;
+#ifndef __FreeBSD__
+ aw->p.dyn->hook_cookie = hook_establish(
+ aw->p.dyn->ifp->if_addrhooks, 1,
+ pf_dynaddr_update, aw->p.dyn);
+ if (aw->p.dyn->hook_cookie == NULL) {
+ pool_put(&pf_addr_pl, aw->p.dyn);
+ aw->p.dyn = NULL;
+ return (1);
+ }
+#else
+ PF_UNLOCK();
+ aw->p.dyn->hook_cookie = EVENTHANDLER_REGISTER(ifaddr_event,
+ pf_dynaddr_update_event, aw->p.dyn, EVENTHANDLER_PRI_ANY);
+ PF_LOCK();
+ if (aw->p.dyn->hook_cookie == NULL) {
+ pool_put(&pf_addr_pl, aw->p.dyn);
+ aw->p.dyn = NULL;
+ return (1);
+ }
+#endif
+ pf_dynaddr_update(aw->p.dyn);
+ return (0);
+}
+
+#ifdef __FreeBSD__
+void
+pf_dynaddr_update_event(void *arg, struct ifnet *ifp)
+{
+ PF_LOCK();
+ pf_dynaddr_update(arg);
+ PF_UNLOCK();
+}
+#endif
+
+void
+pf_dynaddr_update(void *p)
+{
+ struct pf_addr_dyn *ad = (struct pf_addr_dyn *)p;
+ struct ifaddr *ia;
+ int s, changed = 0;
+
+ if (ad == NULL || ad->ifp == NULL)
+ panic("pf_dynaddr_update");
+ s = splsoftnet();
+ TAILQ_FOREACH(ia, &ad->ifp->if_addrlist, ifa_list)
+ if (ia->ifa_addr != NULL &&
+ ia->ifa_addr->sa_family == ad->af) {
+ if (ad->af == AF_INET) {
+ struct in_addr *a, *b;
+
+ a = &ad->addr->v4;
+ b = &((struct sockaddr_in *)ia->ifa_addr)
+ ->sin_addr;
+ if (ad->undefined ||
+ memcmp(a, b, sizeof(*a))) {
+ bcopy(b, a, sizeof(*a));
+ changed = 1;
+ }
+ } else if (ad->af == AF_INET6) {
+ struct in6_addr *a, *b;
+
+ a = &ad->addr->v6;
+ b = &((struct sockaddr_in6 *)ia->ifa_addr)
+ ->sin6_addr;
+ if (ad->undefined ||
+ memcmp(a, b, sizeof(*a))) {
+ bcopy(b, a, sizeof(*a));
+ changed = 1;
+ }
+ }
+ if (changed)
+ ad->undefined = 0;
+ break;
+ }
+ if (ia == NULL)
+ ad->undefined = 1;
+ splx(s);
+}
+
+void
+pf_dynaddr_remove(struct pf_addr_wrap *aw)
+{
+ if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL)
+ return;
+#ifndef __FreeBSD__
+ hook_disestablish(aw->p.dyn->ifp->if_addrhooks,
+ aw->p.dyn->hook_cookie);
+#else
+ PF_UNLOCK();
+ EVENTHANDLER_DEREGISTER(ifaddr_event, aw->p.dyn->hook_cookie);
+ PF_LOCK();
+#endif
+ pool_put(&pf_addr_pl, aw->p.dyn);
+ aw->p.dyn = NULL;
+}
+
+void
+pf_dynaddr_copyout(struct pf_addr_wrap *aw)
+{
+ if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL)
+ return;
+ bcopy(aw->p.dyn->ifname, aw->v.ifname, sizeof(aw->v.ifname));
+ aw->p.dyn = (struct pf_addr_dyn *)1;
+}
+
void
pf_print_host(struct pf_addr *addr, u_int16_t p, sa_family_t af)
{
@@ -1004,7 +934,7 @@ pf_calc_skip_steps(struct pf_rulequeue *rules)
head[i] = cur;
while (cur != NULL) {
- if (cur->kif != prev->kif || cur->ifnot != prev->ifnot)
+ if (cur->ifp != prev->ifp || cur->ifnot != prev->ifnot)
PF_SET_SKIP_STEPS(PF_SKIP_IFP);
if (cur->direction != prev->direction)
PF_SET_SKIP_STEPS(PF_SKIP_DIR);
@@ -1047,7 +977,11 @@ pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2)
return (1);
return (0);
case PF_ADDR_DYNIFTL:
- return (aw1->p.dyn->pfid_kt != aw2->p.dyn->pfid_kt);
+ if (aw1->p.dyn->ifp != aw2->p.dyn->ifp)
+ return (1);
+ if (PF_ANEQ(&aw1->v.a.mask, &aw2->v.a.mask, 0))
+ return (1);
+ return (0);
case PF_ADDR_NOROUTE:
return (0);
case PF_ADDR_TABLE:
@@ -1059,6 +993,33 @@ pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2)
}
void
+pf_rule_set_qid(struct pf_rulequeue *rules)
+{
+ struct pf_rule *rule;
+
+ TAILQ_FOREACH(rule, rules, entries)
+ if (rule->qname[0] != 0) {
+ rule->qid = pf_qname_to_qid(rule->qname);
+ if (rule->pqname[0] != 0)
+ rule->pqid = pf_qname_to_qid(rule->pqname);
+ else
+ rule->pqid = rule->qid;
+ }
+}
+
+u_int32_t
+pf_qname_to_qid(char *qname)
+{
+ struct pf_altq *altq;
+
+ TAILQ_FOREACH(altq, pf_altqs_active, entries)
+ if (!strcmp(altq->qname, qname))
+ return (altq->qid);
+
+ return (0);
+}
+
+void
pf_update_anchor_rules()
{
struct pf_rule *rule;
@@ -1181,7 +1142,7 @@ pf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa,
/* Change inner protocol port, fix inner protocol checksum. */
if (ip != NULL) {
u_int16_t oip = *ip;
- u_int32_t opc;
+ u_int32_t opc = 0; /* make the compiler happy */
if (pc != NULL)
opc = *pc;
@@ -1261,14 +1222,20 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
{
struct mbuf *m;
struct m_tag *mtag;
- int len, tlen;
+ int len = 0, tlen; /* make the compiler happy */
#ifdef INET
- struct ip *h;
+ struct ip *h = NULL; /* make the compiler happy */
#endif /* INET */
#ifdef INET6
- struct ip6_hdr *h6;
+ struct ip6_hdr *h6 = NULL; /* make the compiler happy */
#endif /* INET6 */
- struct tcphdr *th;
+ struct tcphdr *th = NULL; /* make the compiler happy */
+#ifdef __FreeBSD__
+ struct ip *ip;
+#if (__FreeBSD_version < 501114)
+ struct route ro;
+#endif
+#endif
char *opt;
/* maximum segment size tcp option */
@@ -1374,12 +1341,44 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
h->ip_v = 4;
h->ip_hl = sizeof(*h) >> 2;
h->ip_tos = IPTOS_LOWDELAY;
- h->ip_len = htons(len);
+#ifdef __FreeBSD__
+ h->ip_off = htons(path_mtu_discovery ? IP_DF : 0);
+#else
h->ip_off = htons(ip_mtudisc ? IP_DF : 0);
+#endif
+ h->ip_len = htons(len);
h->ip_ttl = ttl ? ttl : ip_defttl;
h->ip_sum = 0;
+#ifdef __FreeBSD__
+ ip = mtod(m, struct ip *);
+ /*
+ * XXX
+ * OpenBSD changed ip_len/ip_off byte ordering!
+ * Because FreeBSD assumes host byte ordering we need to
+ * change here.
+ */
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
+#if (__FreeBSD_version < 501114)
+ bzero(&ro, sizeof(ro));
+ ip_rtaddr(ip->ip_dst, &ro);
+ PF_UNLOCK();
+ ip_output(m, (void *)NULL, &ro, 0, (void *)NULL,
+ (void *)NULL);
+ PF_LOCK();
+ if(ro.ro_rt) {
+ RTFREE(ro.ro_rt);
+ }
+#else /* __FreeBSD_version >= 501114 */
+ PF_UNLOCK();
+ ip_output(m, (void *)NULL, (void *)NULL, 0, (void *)NULL,
+ (void *)NULL);
+ PF_LOCK();
+#endif
+#else /* ! __FreeBSD__ */
ip_output(m, (void *)NULL, (void *)NULL, 0, (void *)NULL,
(void *)NULL);
+#endif
break;
#endif /* INET */
#ifdef INET6
@@ -1391,7 +1390,13 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
h6->ip6_vfc |= IPV6_VERSION;
h6->ip6_hlim = IPV6_DEFHLIM;
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
+ PF_LOCK();
+#else
ip6_output(m, NULL, NULL, 0, NULL, NULL);
+#endif
break;
#endif /* INET6 */
}
@@ -1403,11 +1408,18 @@ pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
{
struct m_tag *mtag;
struct mbuf *m0;
+#ifdef __FreeBSD__
+ struct ip *ip;
+#endif
mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT);
if (mtag == NULL)
return;
+#ifdef __FreeBSD__
+ m0 = m_copypacket(m, M_DONTWAIT);
+#else
m0 = m_copy(m, 0, M_COPYALL);
+#endif
if (m0 == NULL) {
m_tag_free(mtag);
return;
@@ -1433,12 +1445,28 @@ pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
switch (af) {
#ifdef INET
case AF_INET:
- icmp_error(m0, type, code, 0, (void *)NULL);
+#ifdef __FreeBSD__
+ /* icmp_error() expects host byte ordering */
+ ip = mtod(m0, struct ip *);
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
+ PF_UNLOCK();
+#endif
+ icmp_error(m0, type, code, 0, NULL);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
icmp6_error(m0, type, code, 0);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
break;
#endif /* INET6 */
}
@@ -1553,8 +1581,8 @@ pf_get_tag(struct mbuf *m)
}
int
-pf_match_tag(struct mbuf *m, struct pf_rule *r, struct pf_rule *nat_rule,
- struct pf_tag *pftag, int *tag)
+pf_match_tag(struct mbuf *m, struct pf_rule *r, struct pf_rule *nat,
+ struct pf_rule *rdr, struct pf_tag *pftag, int *tag)
{
if (*tag == -1) { /* find mbuf tag */
pftag = pf_get_tag(m);
@@ -1562,8 +1590,10 @@ pf_match_tag(struct mbuf *m, struct pf_rule *r, struct pf_rule *nat_rule,
*tag = pftag->tag;
else
*tag = 0;
- if (nat_rule != NULL && nat_rule->tag)
- *tag = nat_rule->tag;
+ if (nat != NULL && nat->tag)
+ *tag = nat->tag;
+ if (rdr != NULL && rdr->tag)
+ *tag = rdr->tag;
}
return ((!r->match_tag_not && r->match_tag == *tag) ||
@@ -1647,7 +1677,7 @@ pf_poolmask(struct pf_addr *naddr, struct pf_addr *raddr,
}
void
-pf_addr_inc(struct pf_addr *addr, sa_family_t af)
+pf_addr_inc(struct pf_addr *addr, u_int8_t af)
{
switch (af) {
#ifdef INET
@@ -1736,59 +1766,20 @@ pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
}
int
-pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
- struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn)
+pf_map_addr(u_int8_t af, struct pf_pool *rpool, struct pf_addr *saddr,
+ struct pf_addr *naddr, struct pf_addr *init_addr)
{
unsigned char hash[16];
- struct pf_pool *rpool = &r->rpool;
- struct pf_addr *raddr = &rpool->cur->addr.v.a.addr;
- struct pf_addr *rmask = &rpool->cur->addr.v.a.mask;
+ struct pf_addr *raddr;
+ struct pf_addr *rmask;
struct pf_pooladdr *acur = rpool->cur;
- struct pf_src_node k;
-
- if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR &&
- (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
- k.af = af;
- PF_ACPY(&k.addr, saddr, af);
- if (r->rule_flag & PFRULE_RULESRCTRACK ||
- r->rpool.opts & PF_POOL_STICKYADDR)
- k.rule.ptr = r;
- else
- k.rule.ptr = NULL;
- pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
- *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
- if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, af)) {
- PF_ACPY(naddr, &(*sn)->raddr, af);
- if (pf_status.debug >= PF_DEBUG_MISC) {
- printf("pf_map_addr: src tracking maps ");
- pf_print_host(&k.addr, 0, af);
- printf(" to ");
- pf_print_host(naddr, 0, af);
- printf("\n");
- }
- return (0);
- }
- }
if (rpool->cur->addr.type == PF_ADDR_NOROUTE)
return (1);
- if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
- if (af == AF_INET) {
- if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 &&
- (rpool->opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN)
- return (1);
- raddr = &rpool->cur->addr.p.dyn->pfid_addr4;
- rmask = &rpool->cur->addr.p.dyn->pfid_mask4;
- } else {
- if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 &&
- (rpool->opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN)
- return (1);
- raddr = &rpool->cur->addr.p.dyn->pfid_addr6;
- rmask = &rpool->cur->addr.p.dyn->pfid_mask6;
- }
- } else if (rpool->cur->addr.type == PF_ADDR_TABLE) {
+ if (rpool->cur->addr.type == PF_ADDR_DYNIFTL &&
+ rpool->cur->addr.p.dyn->undefined)
+ return (1);
+ if (rpool->cur->addr.type == PF_ADDR_TABLE) {
if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN)
return (1); /* unsupported */
} else {
@@ -1848,11 +1839,6 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
&rpool->tblidx, &rpool->counter,
&raddr, &rmask, af))
goto get_addr;
- } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
- if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
- &rpool->tblidx, &rpool->counter,
- &raddr, &rmask, af))
- goto get_addr;
} else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
goto get_addr;
@@ -1864,17 +1850,7 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
if (pfr_pool_get(rpool->cur->addr.p.tbl,
&rpool->tblidx, &rpool->counter,
&raddr, &rmask, af)) {
- /* table contains no address of type 'af' */
- if (rpool->cur != acur)
- goto try_next;
- return (1);
- }
- } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
- rpool->tblidx = -1;
- if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
- &rpool->tblidx, &rpool->counter,
- &raddr, &rmask, af)) {
- /* table contains no address of type 'af' */
+ /* table contain no address of type 'af' */
if (rpool->cur != acur)
goto try_next;
return (1);
@@ -1890,12 +1866,10 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
PF_AINC(&rpool->counter, af);
break;
}
- if (*sn != NULL)
- PF_ACPY(&(*sn)->raddr, naddr, af);
if (pf_status.debug >= PF_DEBUG_MISC &&
(rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
- printf("pf_map_addr: selected address ");
+ printf("pf_map_addr: selected address: ");
pf_print_host(naddr, 0, af);
printf("\n");
}
@@ -1904,41 +1878,41 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
}
int
-pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
+pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_pool *rpool,
struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t dport,
- struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high,
- struct pf_src_node **sn)
+ struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high)
{
- struct pf_state key;
+ struct pf_tree_node key;
struct pf_addr init_addr;
u_int16_t cut;
bzero(&init_addr, sizeof(init_addr));
- if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
+ if (pf_map_addr(af, rpool, saddr, naddr, &init_addr))
return (1);
do {
key.af = af;
key.proto = proto;
- PF_ACPY(&key.ext.addr, daddr, key.af);
- PF_ACPY(&key.gwy.addr, naddr, key.af);
- key.ext.port = dport;
+ PF_ACPY(&key.addr[0], daddr, key.af);
+ PF_ACPY(&key.addr[1], naddr, key.af);
+ key.port[0] = dport;
/*
* port search; start random, step;
* similar 2 portloop in in_pcbbind
*/
if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP)) {
- key.gwy.port = 0;
- if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
+ key.port[1] = 0;
+ if (pf_find_state(&tree_ext_gwy, &key) == NULL)
return (0);
} else if (low == 0 && high == 0) {
- key.gwy.port = *nport;
- if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
+ key.port[1] = *nport;
+ if (pf_find_state(&tree_ext_gwy, &key) == NULL) {
return (0);
+ }
} else if (low == high) {
- key.gwy.port = htons(low);
- if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL) {
+ key.port[1] = htons(low);
+ if (pf_find_state(&tree_ext_gwy, &key) == NULL) {
*nport = htons(low);
return (0);
}
@@ -1954,16 +1928,16 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
cut = arc4random() % (1 + high - low) + low;
/* low <= cut <= high */
for (tmp = cut; tmp <= high; ++(tmp)) {
- key.gwy.port = htons(tmp);
- if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
+ key.port[1] = htons(tmp);
+ if (pf_find_state(&tree_ext_gwy, &key) ==
NULL) {
*nport = htons(tmp);
return (0);
}
}
for (tmp = cut - 1; tmp >= low; --(tmp)) {
- key.gwy.port = htons(tmp);
- if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
+ key.port[1] = htons(tmp);
+ if (pf_find_state(&tree_ext_gwy, &key) ==
NULL) {
*nport = htons(tmp);
return (0);
@@ -1971,10 +1945,10 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
}
}
- switch (r->rpool.opts & PF_POOL_TYPEMASK) {
+ switch (rpool->opts & PF_POOL_TYPEMASK) {
case PF_POOL_RANDOM:
case PF_POOL_ROUNDROBIN:
- if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
+ if (pf_map_addr(af, rpool, saddr, naddr, &init_addr))
return (1);
break;
case PF_POOL_NONE:
@@ -1982,6 +1956,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
case PF_POOL_BITMASK:
default:
return (1);
+ break;
}
} while (! PF_AEQ(&init_addr, naddr, af) );
@@ -1990,7 +1965,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
struct pf_rule *
pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
- int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport,
+ int direction, struct ifnet *ifp, struct pf_addr *saddr, u_int16_t sport,
struct pf_addr *daddr, u_int16_t dport, int rs_num)
{
struct pf_rule *r, *rm = NULL, *anchorrule = NULL;
@@ -2011,8 +1986,8 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
}
r->evaluations++;
- if (r->kif != NULL &&
- (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+ if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
+ (r->ifp == ifp && r->ifnot)))
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -2058,7 +2033,7 @@ pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
struct pf_rule *
pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
- struct pfi_kif *kif, struct pf_src_node **sn,
+ struct ifnet *ifp,
struct pf_addr *saddr, u_int16_t sport,
struct pf_addr *daddr, u_int16_t dport,
struct pf_addr *naddr, u_int16_t *nport)
@@ -2066,16 +2041,16 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
struct pf_rule *r = NULL;
if (direction == PF_OUT) {
- r = pf_match_translation(pd, m, off, direction, kif, saddr,
+ r = pf_match_translation(pd, m, off, direction, ifp, saddr,
sport, daddr, dport, PF_RULESET_BINAT);
if (r == NULL)
- r = pf_match_translation(pd, m, off, direction, kif,
+ r = pf_match_translation(pd, m, off, direction, ifp,
saddr, sport, daddr, dport, PF_RULESET_NAT);
} else {
- r = pf_match_translation(pd, m, off, direction, kif, saddr,
+ r = pf_match_translation(pd, m, off, direction, ifp, saddr,
sport, daddr, dport, PF_RULESET_RDR);
if (r == NULL)
- r = pf_match_translation(pd, m, off, direction, kif,
+ r = pf_match_translation(pd, m, off, direction, ifp,
saddr, sport, daddr, dport, PF_RULESET_BINAT);
}
@@ -2085,10 +2060,11 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
case PF_NOBINAT:
case PF_NORDR:
return (NULL);
+ break;
case PF_NAT:
- if (pf_get_sport(pd->af, pd->proto, r, saddr,
+ if (pf_get_sport(pd->af, pd->proto, &r->rpool, saddr,
daddr, dport, naddr, nport, r->rpool.proxy_port[0],
- r->rpool.proxy_port[1], sn)) {
+ r->rpool.proxy_port[1])) {
DPFPRINTF(PF_DEBUG_MISC,
("pf: NAT proxy port allocation "
"(%u-%u) failed\n",
@@ -2100,58 +2076,21 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
case PF_BINAT:
switch (direction) {
case PF_OUT:
- if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
- if (pd->af == AF_INET) {
- if (r->rpool.cur->addr.p.dyn->
- pfid_acnt4 < 1)
- return (NULL);
- PF_POOLMASK(naddr,
- &r->rpool.cur->addr.p.dyn->
- pfid_addr4,
- &r->rpool.cur->addr.p.dyn->
- pfid_mask4,
- saddr, AF_INET);
- } else {
- if (r->rpool.cur->addr.p.dyn->
- pfid_acnt6 < 1)
- return (NULL);
- PF_POOLMASK(naddr,
- &r->rpool.cur->addr.p.dyn->
- pfid_addr6,
- &r->rpool.cur->addr.p.dyn->
- pfid_mask6,
- saddr, AF_INET6);
- }
- } else
+ if (r->rpool.cur->addr.type ==
+ PF_ADDR_DYNIFTL &&
+ r->rpool.cur->addr.p.dyn->undefined)
+ return (NULL);
+ else
PF_POOLMASK(naddr,
&r->rpool.cur->addr.v.a.addr,
&r->rpool.cur->addr.v.a.mask,
saddr, pd->af);
break;
case PF_IN:
- if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
- if (pd->af == AF_INET) {
- if (r->src.addr.p.dyn->
- pfid_acnt4 < 1)
- return (NULL);
- PF_POOLMASK(naddr,
- &r->src.addr.p.dyn->
- pfid_addr4,
- &r->src.addr.p.dyn->
- pfid_mask4,
- daddr, AF_INET);
- } else {
- if (r->src.addr.p.dyn->
- pfid_acnt6 < 1)
- return (NULL);
- PF_POOLMASK(naddr,
- &r->src.addr.p.dyn->
- pfid_addr6,
- &r->src.addr.p.dyn->
- pfid_mask6,
- daddr, AF_INET6);
- }
- } else
+ if (r->src.addr.type == PF_ADDR_DYNIFTL &&
+ r->src.addr.p.dyn->undefined)
+ return (NULL);
+ else
PF_POOLMASK(naddr,
&r->src.addr.v.a.addr,
&r->src.addr.v.a.mask, daddr,
@@ -2160,7 +2099,7 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
}
break;
case PF_RDR: {
- if (pf_map_addr(r->af, r, saddr, naddr, NULL, sn))
+ if (pf_map_addr(r->af, &r->rpool, saddr, naddr, NULL))
return (NULL);
if (r->rpool.proxy_port[1]) {
@@ -2182,6 +2121,7 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
}
default:
return (NULL);
+ break;
}
}
@@ -2189,25 +2129,38 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
}
int
-pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, struct pf_pdesc *pd)
+pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, sa_family_t af,
+ int proto, struct pf_pdesc *pd)
{
struct pf_addr *saddr, *daddr;
u_int16_t sport, dport;
+#ifdef __FreeBSD__
+ struct inpcbinfo *pi;
+#else
struct inpcbtable *tb;
+#endif
struct inpcb *inp;
*uid = UID_MAX;
*gid = GID_MAX;
- switch (pd->proto) {
+ switch (proto) {
case IPPROTO_TCP:
sport = pd->hdr.tcp->th_sport;
dport = pd->hdr.tcp->th_dport;
+#ifdef __FreeBSD__
+ pi = &tcbinfo;
+#else
tb = &tcbtable;
+#endif
break;
case IPPROTO_UDP:
sport = pd->hdr.udp->uh_sport;
dport = pd->hdr.udp->uh_dport;
+#ifdef __FreeBSD__
+ pi = &udbinfo;
+#else
tb = &udbtable;
+#endif
break;
default:
return (0);
@@ -2224,32 +2177,82 @@ pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, struct pf_pdesc *pd)
saddr = pd->dst;
daddr = pd->src;
}
- switch (pd->af) {
+ switch(af) {
case AF_INET:
+#ifdef __FreeBSD__
+#if (__FreeBSD_version >= 500043)
+ INP_INFO_RLOCK(pi); /* XXX LOR */
+#endif
+ inp = in_pcblookup_hash(pi, saddr->v4, sport, daddr->v4,
+ dport, 0, NULL);
+ if (inp == NULL) {
+ inp = in_pcblookup_hash(pi, saddr->v4, sport,
+ daddr->v4, dport, INPLOOKUP_WILDCARD, NULL);
+ if(inp == NULL) {
+#if (__FreeBSD_version >= 500043)
+ INP_INFO_RUNLOCK(pi);
+#endif
+ return (0);
+ }
+ }
+#else
inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport);
if (inp == NULL) {
- inp = in_pcblookup_listen(tb, daddr->v4, dport, 0);
+ inp = in_pcblookup(tb, &saddr->v4, sport, &daddr->v4,
+ dport, INPLOOKUP_WILDCARD);
if (inp == NULL)
return (0);
}
+#endif
break;
#ifdef INET6
case AF_INET6:
+#ifdef __FreeBSD__
+#if (__FreeBSD_version >= 500043)
+ INP_INFO_RLOCK(pi);
+#endif
+ inp = in6_pcblookup_hash(pi, &saddr->v6, sport,
+ &daddr->v6, dport, 0, NULL);
+ if (inp == NULL) {
+ inp = in6_pcblookup_hash(pi, &saddr->v6, sport,
+ &daddr->v6, dport, INPLOOKUP_WILDCARD, NULL);
+ if (inp == NULL) {
+#if (__FreeBSD_version >= 500043)
+ INP_INFO_RUNLOCK(pi);
+#endif
+ return (0);
+ }
+ }
+#else
inp = in6_pcbhashlookup(tb, &saddr->v6, sport, &daddr->v6,
dport);
if (inp == NULL) {
- inp = in6_pcblookup_listen(tb, &daddr->v6, dport, 0);
+ inp = in_pcblookup(tb, &saddr->v6, sport, &daddr->v6,
+ dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6);
if (inp == NULL)
return (0);
}
+#endif
break;
#endif /* INET6 */
default:
return (0);
}
+#ifdef __FreeBSD__
+#if (__FreeBSD_version >= 500043)
+ INP_LOCK(inp);
+#endif
+ *uid = inp->inp_socket->so_cred->cr_uid;
+ *gid = inp->inp_socket->so_cred->cr_groups[0];
+#if (__FreeBSD_version >= 500043)
+ INP_UNLOCK(inp);
+ INP_INFO_RUNLOCK(pi);
+#endif
+#else
*uid = inp->inp_socket->so_euid;
*gid = inp->inp_socket->so_egid;
+#endif
return (1);
}
@@ -2280,14 +2283,13 @@ pf_get_wscale(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af)
if (wscale > TCP_MAX_WINSHIFT)
wscale = TCP_MAX_WINSHIFT;
wscale |= PF_WSCALE_FLAG;
- /* FALLTHROUGH */
+ /* fallthrough */
default:
optlen = opt[1];
if (optlen < 2)
optlen = 2;
hlen -= optlen;
opt += optlen;
- break;
}
}
return (wscale);
@@ -2317,14 +2319,13 @@ pf_get_mss(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af)
break;
case TCPOPT_MAXSEG:
bcopy((caddr_t)(opt + 2), (caddr_t)&mss, 2);
- /* FALLTHROUGH */
+ /* fallthrough */
default:
optlen = opt[1];
if (optlen < 2)
optlen = 2;
hlen -= optlen;
opt += optlen;
- break;
}
}
return (mss);
@@ -2342,7 +2343,7 @@ pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
struct route_in6 ro6;
#endif /* INET6 */
struct rtentry *rt = NULL;
- int hlen;
+ int hlen = 0; /* make the compiler happy */
u_int16_t mss = tcp_mssdflt;
switch (af) {
@@ -2354,7 +2355,15 @@ pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = addr->v4;
+#ifdef __FreeBSD__
+#ifdef RTF_PRCLONING
+ rtalloc_ign(&ro, (RTF_CLONING | RTF_PRCLONING));
+#else /* !RTF_PRCLONING */
+ rtalloc_ign(&ro, RTF_CLONING);
+#endif
+#else /* ! __FreeBSD__ */
rtalloc_noclone(&ro, NO_CLONING);
+#endif
rt = ro.ro_rt;
break;
#endif /* INET */
@@ -2366,7 +2375,16 @@ pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
dst6->sin6_family = AF_INET6;
dst6->sin6_len = sizeof(*dst6);
dst6->sin6_addr = addr->v6;
+#ifdef __FreeBSD__
+#ifdef RTF_PRCLONING
+ rtalloc_ign((struct route *)&ro6,
+ (RTF_CLONING | RTF_PRCLONING));
+#else /* !RTF_PRCLONING */
+ rtalloc_ign((struct route *)&ro6, RTF_CLONING);
+#endif
+#else /* ! __FreeBSD__ */
rtalloc_noclone((struct route *)&ro6, NO_CLONING);
+#endif
rt = ro6.ro_rt;
break;
#endif /* INET6 */
@@ -2387,22 +2405,22 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
{
struct pf_rule *r = s->rule.ptr;
- s->rt_kif = NULL;
+ s->rt_ifp = NULL;
if (!r->rt || r->rt == PF_FASTROUTE)
return;
switch (s->af) {
#ifdef INET
case AF_INET:
- pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL,
- &s->nat_src_node);
- s->rt_kif = r->rpool.cur->kif;
+ pf_map_addr(AF_INET, &r->rpool, saddr,
+ &s->rt_addr, NULL);
+ s->rt_ifp = r->rpool.cur->ifp;
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL,
- &s->nat_src_node);
- s->rt_kif = r->rpool.cur->kif;
+ pf_map_addr(AF_INET6, &r->rpool, saddr,
+ &s->rt_addr, NULL);
+ s->rt_ifp = r->rpool.cur->ifp;
break;
#endif /* INET6 */
}
@@ -2410,11 +2428,12 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
int
pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
- struct pfi_kif *kif, struct mbuf *m, int off, void *h,
+ struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h,
struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)
{
- struct pf_rule *nr = NULL;
+ struct pf_rule *nat = NULL, *rdr = NULL;
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
+ struct pf_addr baddr, naddr;
struct tcphdr *th = pd->hdr.tcp;
u_int16_t bport, nport = 0;
sa_family_t af = pd->af;
@@ -2423,7 +2442,6 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
gid_t gid;
struct pf_rule *r, *a = NULL;
struct pf_ruleset *ruleset = NULL;
- struct pf_src_node *nsn = NULL;
u_short reason;
int rewrite = 0;
struct pf_tag *pftag = NULL;
@@ -2435,37 +2453,35 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
if (direction == PF_OUT) {
bport = nport = th->th_sport;
/* check outgoing packet for BINAT/NAT */
- if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
+ if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp,
saddr, th->th_sport, daddr, th->th_dport,
- &pd->naddr, &nport)) != NULL) {
- PF_ACPY(&pd->baddr, saddr, af);
+ &naddr, &nport)) != NULL) {
+ PF_ACPY(&baddr, saddr, af);
pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
- &th->th_sum, &pd->naddr, nport, 0, af);
+ &th->th_sum, &naddr, nport, 0, af);
rewrite++;
- if (nr->natpass)
+ if (nat->natpass)
r = NULL;
- pd->nat_rule = nr;
}
} else {
bport = nport = th->th_dport;
/* check incoming packet for BINAT/RDR */
- if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
- saddr, th->th_sport, daddr, th->th_dport,
- &pd->naddr, &nport)) != NULL) {
- PF_ACPY(&pd->baddr, daddr, af);
+ if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr,
+ th->th_sport, daddr, th->th_dport,
+ &naddr, &nport)) != NULL) {
+ PF_ACPY(&baddr, daddr, af);
pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
- &th->th_sum, &pd->naddr, nport, 0, af);
+ &th->th_sum, &naddr, nport, 0, af);
rewrite++;
- if (nr->natpass)
+ if (rdr->natpass)
r = NULL;
- pd->nat_rule = nr;
}
}
while (r != NULL) {
r->evaluations++;
- if (r->kif != NULL &&
- (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+ if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
+ (r->ifp == ifp && r->ifnot)))
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -2490,16 +2506,19 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
else if ((r->flagset & th->th_flags) != r->flags)
r = TAILQ_NEXT(r, entries);
else if (r->uid.op && (lookup != -1 || (lookup =
- pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
+ pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP,
+ pd), 1)) &&
!pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
uid))
r = TAILQ_NEXT(r, entries);
else if (r->gid.op && (lookup != -1 || (lookup =
- pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
+ pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_TCP,
+ pd), 1)) &&
!pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
gid))
r = TAILQ_NEXT(r, entries);
- else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
+ else if (r->match_tag &&
+ !pf_match_tag(m, r, nat, rdr, pftag, &tag))
r = TAILQ_NEXT(r, entries);
else if (r->anchorname[0] && r->anchor == NULL)
r = TAILQ_NEXT(r, entries);
@@ -2528,12 +2547,18 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
a = *am;
ruleset = *rsm;
+ r->packets++;
+ r->bytes += pd->tot_len;
+ if (a != NULL) {
+ a->packets++;
+ a->bytes += pd->tot_len;
+ }
REASON_SET(&reason, PFRES_MATCH);
if (r->log) {
if (rewrite)
- m_copyback(m, off, sizeof(*th), th);
- PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
+ m_copyback(m, off, sizeof(*th), (caddr_t)th);
+ PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
}
if ((r->action == PF_DROP) &&
@@ -2541,16 +2566,14 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
(r->rule_flag & PFRULE_RETURNICMP) ||
(r->rule_flag & PFRULE_RETURN))) {
/* undo NAT changes, if they have taken place */
- if (nr != NULL) {
- if (direction == PF_OUT) {
- pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
- &th->th_sum, &pd->baddr, bport, 0, af);
- rewrite++;
- } else {
- pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
- &th->th_sum, &pd->baddr, bport, 0, af);
- rewrite++;
- }
+ if (nat != NULL) {
+ pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
+ &th->th_sum, &baddr, bport, 0, af);
+ rewrite++;
+ } else if (rdr != NULL) {
+ pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
+ &th->th_sum, &baddr, bport, 0, af);
+ rewrite++;
}
if (((r->rule_flag & PFRULE_RETURNRST) ||
(r->rule_flag & PFRULE_RETURN)) &&
@@ -2581,45 +2604,16 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
return (PF_DROP);
}
- if (r->keep_state || nr != NULL ||
+ if (r->keep_state || nat != NULL || rdr != NULL ||
(pd->flags & PFDESC_TCP_NORM)) {
/* create new state */
u_int16_t len;
struct pf_state *s = NULL;
- struct pf_src_node *sn = NULL;
len = pd->tot_len - off - (th->th_off << 2);
-
- /* check maximums */
- if (r->max_states && (r->states >= r->max_states))
- goto cleanup;
- /* src node for flter rule */
- if ((r->rule_flag & PFRULE_SRCTRACK ||
- r->rpool.opts & PF_POOL_STICKYADDR) &&
- pf_insert_src_node(&sn, r, saddr, af) != 0)
- goto cleanup;
- /* src node for translation rule */
- if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
- ((direction == PF_OUT &&
- pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
- (pf_insert_src_node(&nsn, nr, saddr, af) != 0)))
- goto cleanup;
- s = pool_get(&pf_state_pl, PR_NOWAIT);
+ if (!r->max_states || r->states < r->max_states)
+ s = pool_get(&pf_state_pl, PR_NOWAIT);
if (s == NULL) {
-cleanup:
- if (sn != NULL && sn->states == 0 && sn->expire == 0) {
- RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
- pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
- pf_status.src_nodes--;
- pool_put(&pf_src_tree_pl, sn);
- }
- if (nsn != sn && nsn != NULL && nsn->states == 0 &&
- nsn->expire == 0) {
- RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
- pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
- pf_status.src_nodes--;
- pool_put(&pf_src_tree_pl, nsn);
- }
REASON_SET(&reason, PFRES_MEMORY);
return (PF_DROP);
}
@@ -2628,7 +2622,10 @@ cleanup:
if (a != NULL)
a->states++;
s->rule.ptr = r;
- s->nat_rule.ptr = nr;
+ if (nat != NULL)
+ s->nat_rule.ptr = nat;
+ else
+ s->nat_rule.ptr = rdr;
if (s->nat_rule.ptr != NULL)
s->nat_rule.ptr->states++;
s->anchor.ptr = a;
@@ -2642,8 +2639,8 @@ cleanup:
s->gwy.port = th->th_sport; /* sport */
PF_ACPY(&s->ext.addr, daddr, af);
s->ext.port = th->th_dport;
- if (nr != NULL) {
- PF_ACPY(&s->lan.addr, &pd->baddr, af);
+ if (nat != NULL) {
+ PF_ACPY(&s->lan.addr, &baddr, af);
s->lan.port = bport;
} else {
PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
@@ -2654,8 +2651,8 @@ cleanup:
s->lan.port = th->th_dport;
PF_ACPY(&s->ext.addr, saddr, af);
s->ext.port = th->th_sport;
- if (nr != NULL) {
- PF_ACPY(&s->gwy.addr, &pd->baddr, af);
+ if (rdr != NULL) {
+ PF_ACPY(&s->gwy.addr, &baddr, af);
s->gwy.port = bport;
} else {
PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
@@ -2689,27 +2686,27 @@ cleanup:
}
if (th->th_flags & TH_FIN)
s->src.seqhi++;
+ s->dst.seqlo = 0; /* Haven't seen these yet */
s->dst.seqhi = 1;
s->dst.max_win = 1;
+ s->dst.seqdiff = 0; /* Defer random generation */
s->src.state = TCPS_SYN_SENT;
s->dst.state = TCPS_CLOSED;
+#ifdef __FreeBSD__
+ s->creation = time_second;
+ s->expire = time_second;
+#else
s->creation = time.tv_sec;
s->expire = time.tv_sec;
+#endif
s->timeout = PFTM_TCP_FIRST_PACKET;
+ s->packets[0] = 1;
+ s->bytes[0] = pd->tot_len;
pf_set_rt_ifp(s, saddr);
- if (sn != NULL) {
- s->src_node = sn;
- s->src_node->states++;
- }
- if (nsn != NULL) {
- PF_ACPY(&nsn->raddr, &pd->naddr, af);
- s->nat_src_node = nsn;
- s->nat_src_node->states++;
- }
+
if ((pd->flags & PFDESC_TCP_NORM) && pf_normalize_tcp_init(m,
off, pd, th, &s->src, &s->dst)) {
REASON_SET(&reason, PFRES_MEMORY);
- pf_src_tree_remove_state(s);
pool_put(&pf_state_pl, s);
return (PF_DROP);
}
@@ -2717,14 +2714,12 @@ cleanup:
pf_normalize_tcp_stateful(m, off, pd, &reason, th, &s->src,
&s->dst, &rewrite)) {
pf_normalize_tcp_cleanup(s);
- pf_src_tree_remove_state(s);
pool_put(&pf_state_pl, s);
return (PF_DROP);
}
- if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
+ if (pf_insert_state(s)) {
pf_normalize_tcp_cleanup(s);
REASON_SET(&reason, PFRES_MEMORY);
- pf_src_tree_remove_state(s);
pool_put(&pf_state_pl, s);
return (PF_DROP);
} else
@@ -2732,17 +2727,14 @@ cleanup:
if ((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN &&
r->keep_state == PF_STATE_SYNPROXY) {
s->src.state = PF_TCPS_PROXY_SRC;
- if (nr != NULL) {
- if (direction == PF_OUT) {
- pf_change_ap(saddr, &th->th_sport,
- pd->ip_sum, &th->th_sum, &pd->baddr,
- bport, 0, af);
- } else {
- pf_change_ap(daddr, &th->th_dport,
- pd->ip_sum, &th->th_sum, &pd->baddr,
- bport, 0, af);
- }
- }
+ if (nat != NULL)
+ pf_change_ap(saddr, &th->th_sport,
+ pd->ip_sum, &th->th_sum, &baddr,
+ bport, 0, af);
+ else if (rdr != NULL)
+ pf_change_ap(daddr, &th->th_dport,
+ pd->ip_sum, &th->th_sum, &baddr,
+ bport, 0, af);
s->src.seqhi = arc4random();
/* Find mss option */
mss = pf_get_mss(m, off, th->th_off, af);
@@ -2750,26 +2742,27 @@ cleanup:
mss = pf_calc_mss(daddr, af, mss);
s->src.mss = mss;
pf_send_tcp(r, af, daddr, saddr, th->th_dport,
- th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
- TH_SYN|TH_ACK, 0, s->src.mss, 0);
+ th->th_sport, s->src.seqhi,
+ ntohl(th->th_seq) + 1, TH_SYN|TH_ACK, 0, s->src.mss, 0);
return (PF_SYNPROXY_DROP);
}
}
/* copy back packet headers if we performed NAT operations */
if (rewrite)
- m_copyback(m, off, sizeof(*th), th);
+ m_copyback(m, off, sizeof(*th), (caddr_t)th);
return (PF_PASS);
}
int
pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
- struct pfi_kif *kif, struct mbuf *m, int off, void *h,
+ struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h,
struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)
{
- struct pf_rule *nr = NULL;
+ struct pf_rule *nat = NULL, *rdr = NULL;
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
+ struct pf_addr baddr, naddr;
struct udphdr *uh = pd->hdr.udp;
u_int16_t bport, nport = 0;
sa_family_t af = pd->af;
@@ -2778,7 +2771,6 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
gid_t gid;
struct pf_rule *r, *a = NULL;
struct pf_ruleset *ruleset = NULL;
- struct pf_src_node *nsn = NULL;
u_short reason;
int rewrite = 0;
struct pf_tag *pftag = NULL;
@@ -2789,37 +2781,35 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
if (direction == PF_OUT) {
bport = nport = uh->uh_sport;
/* check outgoing packet for BINAT/NAT */
- if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
+ if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp,
saddr, uh->uh_sport, daddr, uh->uh_dport,
- &pd->naddr, &nport)) != NULL) {
- PF_ACPY(&pd->baddr, saddr, af);
+ &naddr, &nport)) != NULL) {
+ PF_ACPY(&baddr, saddr, af);
pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum,
- &uh->uh_sum, &pd->naddr, nport, 1, af);
+ &uh->uh_sum, &naddr, nport, 1, af);
rewrite++;
- if (nr->natpass)
+ if (nat->natpass)
r = NULL;
- pd->nat_rule = nr;
}
} else {
bport = nport = uh->uh_dport;
/* check incoming packet for BINAT/RDR */
- if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
- saddr, uh->uh_sport, daddr, uh->uh_dport, &pd->naddr,
- &nport)) != NULL) {
- PF_ACPY(&pd->baddr, daddr, af);
+ if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr,
+ uh->uh_sport, daddr, uh->uh_dport, &naddr, &nport))
+ != NULL) {
+ PF_ACPY(&baddr, daddr, af);
pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum,
- &uh->uh_sum, &pd->naddr, nport, 1, af);
+ &uh->uh_sum, &naddr, nport, 1, af);
rewrite++;
- if (nr->natpass)
+ if (rdr->natpass)
r = NULL;
- pd->nat_rule = nr;
}
}
while (r != NULL) {
r->evaluations++;
- if (r->kif != NULL &&
- (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+ if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
+ (r->ifp == ifp && r->ifnot)))
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -2842,16 +2832,19 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
else if (r->rule_flag & PFRULE_FRAGMENT)
r = TAILQ_NEXT(r, entries);
else if (r->uid.op && (lookup != -1 || (lookup =
- pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
+ pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP,
+ pd), 1)) &&
!pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
uid))
r = TAILQ_NEXT(r, entries);
else if (r->gid.op && (lookup != -1 || (lookup =
- pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
+ pf_socket_lookup(&uid, &gid, direction, af, IPPROTO_UDP,
+ pd), 1)) &&
!pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
gid))
r = TAILQ_NEXT(r, entries);
- else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
+ else if (r->match_tag &&
+ !pf_match_tag(m, r, nat, rdr, pftag, &tag))
r = TAILQ_NEXT(r, entries);
else if (r->anchorname[0] && r->anchor == NULL)
r = TAILQ_NEXT(r, entries);
@@ -2879,28 +2872,32 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
a = *am;
ruleset = *rsm;
+ r->packets++;
+ r->bytes += pd->tot_len;
+ if (a != NULL) {
+ a->packets++;
+ a->bytes += pd->tot_len;
+ }
REASON_SET(&reason, PFRES_MATCH);
if (r->log) {
if (rewrite)
- m_copyback(m, off, sizeof(*uh), uh);
- PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
+ m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
+ PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
}
if ((r->action == PF_DROP) &&
((r->rule_flag & PFRULE_RETURNICMP) ||
(r->rule_flag & PFRULE_RETURN))) {
/* undo NAT changes, if they have taken place */
- if (nr != NULL) {
- if (direction == PF_OUT) {
- pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum,
- &uh->uh_sum, &pd->baddr, bport, 1, af);
- rewrite++;
- } else {
- pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum,
- &uh->uh_sum, &pd->baddr, bport, 1, af);
- rewrite++;
- }
+ if (nat != NULL) {
+ pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum,
+ &uh->uh_sum, &baddr, bport, 1, af);
+ rewrite++;
+ } else if (rdr != NULL) {
+ pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum,
+ &uh->uh_sum, &baddr, bport, 1, af);
+ rewrite++;
}
if ((af == AF_INET) && r->return_icmp)
pf_send_icmp(m, r->return_icmp >> 8,
@@ -2918,41 +2915,13 @@ pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
return (PF_DROP);
}
- if (r->keep_state || nr != NULL) {
+ if (r->keep_state || nat != NULL || rdr != NULL) {
/* create new state */
struct pf_state *s = NULL;
- struct pf_src_node *sn = NULL;
-
- /* check maximums */
- if (r->max_states && (r->states >= r->max_states))
- goto cleanup;
- /* src node for flter rule */
- if ((r->rule_flag & PFRULE_SRCTRACK ||
- r->rpool.opts & PF_POOL_STICKYADDR) &&
- pf_insert_src_node(&sn, r, saddr, af) != 0)
- goto cleanup;
- /* src node for translation rule */
- if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
- ((direction == PF_OUT &&
- pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
- (pf_insert_src_node(&nsn, nr, saddr, af) != 0)))
- goto cleanup;
- s = pool_get(&pf_state_pl, PR_NOWAIT);
+
+ if (!r->max_states || r->states < r->max_states)
+ s = pool_get(&pf_state_pl, PR_NOWAIT);
if (s == NULL) {
-cleanup:
- if (sn != NULL && sn->states == 0 && sn->expire == 0) {
- RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
- pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
- pf_status.src_nodes--;
- pool_put(&pf_src_tree_pl, sn);
- }
- if (nsn != sn && nsn != NULL && nsn->states == 0 &&
- nsn->expire == 0) {
- RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
- pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
- pf_status.src_nodes--;
- pool_put(&pf_src_tree_pl, nsn);
- }
REASON_SET(&reason, PFRES_MEMORY);
return (PF_DROP);
}
@@ -2961,7 +2930,10 @@ cleanup:
if (a != NULL)
a->states++;
s->rule.ptr = r;
- s->nat_rule.ptr = nr;
+ if (nat != NULL)
+ s->nat_rule.ptr = nat;
+ else
+ s->nat_rule.ptr = rdr;
if (s->nat_rule.ptr != NULL)
s->nat_rule.ptr->states++;
s->anchor.ptr = a;
@@ -2975,8 +2947,8 @@ cleanup:
s->gwy.port = uh->uh_sport;
PF_ACPY(&s->ext.addr, daddr, af);
s->ext.port = uh->uh_dport;
- if (nr != NULL) {
- PF_ACPY(&s->lan.addr, &pd->baddr, af);
+ if (nat != NULL) {
+ PF_ACPY(&s->lan.addr, &baddr, af);
s->lan.port = bport;
} else {
PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
@@ -2987,32 +2959,37 @@ cleanup:
s->lan.port = uh->uh_dport;
PF_ACPY(&s->ext.addr, saddr, af);
s->ext.port = uh->uh_sport;
- if (nr != NULL) {
- PF_ACPY(&s->gwy.addr, &pd->baddr, af);
+ if (rdr != NULL) {
+ PF_ACPY(&s->gwy.addr, &baddr, af);
s->gwy.port = bport;
} else {
PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
s->gwy.port = s->lan.port;
}
}
+ s->src.seqlo = 0;
+ s->src.seqhi = 0;
+ s->src.seqdiff = 0;
+ s->src.max_win = 0;
s->src.state = PFUDPS_SINGLE;
+ s->dst.seqlo = 0;
+ s->dst.seqhi = 0;
+ s->dst.seqdiff = 0;
+ s->dst.max_win = 0;
s->dst.state = PFUDPS_NO_TRAFFIC;
+#ifdef __FreeBSD__
+ s->creation = time_second;
+ s->expire = time_second;
+#else
s->creation = time.tv_sec;
s->expire = time.tv_sec;
+#endif
s->timeout = PFTM_UDP_FIRST_PACKET;
+ s->packets[0] = 1;
+ s->bytes[0] = pd->tot_len;
pf_set_rt_ifp(s, saddr);
- if (sn != NULL) {
- s->src_node = sn;
- s->src_node->states++;
- }
- if (nsn != NULL) {
- PF_ACPY(&nsn->raddr, &pd->naddr, af);
- s->nat_src_node = nsn;
- s->nat_src_node->states++;
- }
- if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
+ if (pf_insert_state(s)) {
REASON_SET(&reason, PFRES_MEMORY);
- pf_src_tree_remove_state(s);
pool_put(&pf_state_pl, s);
return (PF_DROP);
} else
@@ -3021,25 +2998,26 @@ cleanup:
/* copy back packet headers if we performed NAT operations */
if (rewrite)
- m_copyback(m, off, sizeof(*uh), uh);
+ m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
return (PF_PASS);
}
int
pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
- struct pfi_kif *kif, struct mbuf *m, int off, void *h,
+ struct ifnet *ifp, struct mbuf *m, int ipoff, int off, void *h,
struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm)
{
- struct pf_rule *nr = NULL;
+ struct pf_rule *nat = NULL, *rdr = NULL;
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
+ struct pf_addr baddr, naddr;
struct pf_rule *r, *a = NULL;
struct pf_ruleset *ruleset = NULL;
- struct pf_src_node *nsn = NULL;
u_short reason;
- u_int16_t icmpid;
+ u_int16_t icmpid = 0; /* make the compiler happy */
sa_family_t af = pd->af;
- u_int8_t icmptype, icmpcode;
+ u_int8_t icmptype = 0; /* make the compiler happy */
+ u_int8_t icmpcode = 0; /* make the compiler happy */
int state_icmp = 0;
struct pf_tag *pftag = NULL;
int tag = -1;
@@ -3081,58 +3059,56 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
if (direction == PF_OUT) {
/* check outgoing packet for BINAT/NAT */
- if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
- saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
- PF_ACPY(&pd->baddr, saddr, af);
+ if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp, saddr, 0,
+ daddr, 0, &naddr, NULL)) != NULL) {
+ PF_ACPY(&baddr, saddr, af);
switch (af) {
#ifdef INET
case AF_INET:
pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
- pd->naddr.v4.s_addr, 0);
+ naddr.v4.s_addr, 0);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
pf_change_a6(saddr, &pd->hdr.icmp6->icmp6_cksum,
- &pd->naddr, 0);
+ &naddr, 0);
rewrite++;
break;
#endif /* INET6 */
}
- if (nr->natpass)
+ if (nat->natpass)
r = NULL;
- pd->nat_rule = nr;
}
} else {
/* check incoming packet for BINAT/RDR */
- if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
- saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
- PF_ACPY(&pd->baddr, daddr, af);
+ if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr, 0,
+ daddr, 0, &naddr, NULL)) != NULL) {
+ PF_ACPY(&baddr, daddr, af);
switch (af) {
#ifdef INET
case AF_INET:
pf_change_a(&daddr->v4.s_addr,
- pd->ip_sum, pd->naddr.v4.s_addr, 0);
+ pd->ip_sum, naddr.v4.s_addr, 0);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
pf_change_a6(daddr, &pd->hdr.icmp6->icmp6_cksum,
- &pd->naddr, 0);
+ &naddr, 0);
rewrite++;
break;
#endif /* INET6 */
}
- if (nr->natpass)
+ if (rdr->natpass)
r = NULL;
- pd->nat_rule = nr;
}
}
while (r != NULL) {
r->evaluations++;
- if (r->kif != NULL &&
- (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+ if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
+ (r->ifp == ifp && r->ifnot)))
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -3152,7 +3128,8 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
r = TAILQ_NEXT(r, entries);
else if (r->rule_flag & PFRULE_FRAGMENT)
r = TAILQ_NEXT(r, entries);
- else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
+ else if (r->match_tag &&
+ !pf_match_tag(m, r, nat, rdr, pftag, &tag))
r = TAILQ_NEXT(r, entries);
else if (r->anchorname[0] && r->anchor == NULL)
r = TAILQ_NEXT(r, entries);
@@ -3180,15 +3157,21 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
a = *am;
ruleset = *rsm;
+ r->packets++;
+ r->bytes += pd->tot_len;
+ if (a != NULL) {
+ a->packets++;
+ a->bytes += pd->tot_len;
+ }
REASON_SET(&reason, PFRES_MATCH);
if (r->log) {
#ifdef INET6
if (rewrite)
m_copyback(m, off, sizeof(struct icmp6_hdr),
- pd->hdr.icmp6);
+ (caddr_t)pd->hdr.icmp6);
#endif /* INET6 */
- PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
+ PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
}
if (r->action != PF_PASS)
@@ -3199,41 +3182,14 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
return (PF_DROP);
}
- if (!state_icmp && (r->keep_state || nr != NULL)) {
+ if (!state_icmp && (r->keep_state ||
+ nat != NULL || rdr != NULL)) {
/* create new state */
struct pf_state *s = NULL;
- struct pf_src_node *sn = NULL;
-
- /* check maximums */
- if (r->max_states && (r->states >= r->max_states))
- goto cleanup;
- /* src node for flter rule */
- if ((r->rule_flag & PFRULE_SRCTRACK ||
- r->rpool.opts & PF_POOL_STICKYADDR) &&
- pf_insert_src_node(&sn, r, saddr, af) != 0)
- goto cleanup;
- /* src node for translation rule */
- if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
- ((direction == PF_OUT &&
- pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
- (pf_insert_src_node(&nsn, nr, saddr, af) != 0)))
- goto cleanup;
- s = pool_get(&pf_state_pl, PR_NOWAIT);
+
+ if (!r->max_states || r->states < r->max_states)
+ s = pool_get(&pf_state_pl, PR_NOWAIT);
if (s == NULL) {
-cleanup:
- if (sn != NULL && sn->states == 0 && sn->expire == 0) {
- RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
- pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
- pf_status.src_nodes--;
- pool_put(&pf_src_tree_pl, sn);
- }
- if (nsn != sn && nsn != NULL && nsn->states == 0 &&
- nsn->expire == 0) {
- RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
- pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
- pf_status.src_nodes--;
- pool_put(&pf_src_tree_pl, nsn);
- }
REASON_SET(&reason, PFRES_MEMORY);
return (PF_DROP);
}
@@ -3242,7 +3198,10 @@ cleanup:
if (a != NULL)
a->states++;
s->rule.ptr = r;
- s->nat_rule.ptr = nr;
+ if (nat != NULL)
+ s->nat_rule.ptr = nat;
+ else
+ s->nat_rule.ptr = rdr;
if (s->nat_rule.ptr != NULL)
s->nat_rule.ptr->states++;
s->anchor.ptr = a;
@@ -3256,8 +3215,8 @@ cleanup:
s->gwy.port = icmpid;
PF_ACPY(&s->ext.addr, daddr, af);
s->ext.port = icmpid;
- if (nr != NULL)
- PF_ACPY(&s->lan.addr, &pd->baddr, af);
+ if (nat != NULL)
+ PF_ACPY(&s->lan.addr, &baddr, af);
else
PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
s->lan.port = icmpid;
@@ -3266,28 +3225,36 @@ cleanup:
s->lan.port = icmpid;
PF_ACPY(&s->ext.addr, saddr, af);
s->ext.port = icmpid;
- if (nr != NULL)
- PF_ACPY(&s->gwy.addr, &pd->baddr, af);
+ if (rdr != NULL)
+ PF_ACPY(&s->gwy.addr, &baddr, af);
else
PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
s->gwy.port = icmpid;
}
+
+ s->src.seqlo = 0;
+ s->src.seqhi = 0;
+ s->src.seqdiff = 0;
+ s->src.max_win = 0;
+ s->src.state = 0;
+ s->dst.seqlo = 0;
+ s->dst.seqhi = 0;
+ s->dst.seqdiff = 0;
+ s->dst.max_win = 0;
+ s->dst.state = 0;
+#ifdef __FreeBSD__
+ s->creation = time_second;
+ s->expire = time_second;
+#else
s->creation = time.tv_sec;
s->expire = time.tv_sec;
+#endif
s->timeout = PFTM_ICMP_FIRST_PACKET;
+ s->packets[0] = 1;
+ s->bytes[0] = pd->tot_len;
pf_set_rt_ifp(s, saddr);
- if (sn != NULL) {
- s->src_node = sn;
- s->src_node->states++;
- }
- if (nsn != NULL) {
- PF_ACPY(&nsn->raddr, &pd->naddr, af);
- s->nat_src_node = nsn;
- s->nat_src_node->states++;
- }
- if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
+ if (pf_insert_state(s)) {
REASON_SET(&reason, PFRES_MEMORY);
- pf_src_tree_remove_state(s);
pool_put(&pf_state_pl, s);
return (PF_DROP);
} else
@@ -3298,7 +3265,7 @@ cleanup:
/* copy back packet headers if we performed IPv6 NAT operations */
if (rewrite)
m_copyback(m, off, sizeof(struct icmp6_hdr),
- pd->hdr.icmp6);
+ (caddr_t)pd->hdr.icmp6);
#endif /* INET6 */
return (PF_PASS);
@@ -3306,14 +3273,14 @@ cleanup:
int
pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
- struct pfi_kif *kif, struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
+ struct ifnet *ifp, struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
struct pf_rule **am, struct pf_ruleset **rsm)
{
- struct pf_rule *nr = NULL;
+ struct pf_rule *nat = NULL, *rdr = NULL;
struct pf_rule *r, *a = NULL;
struct pf_ruleset *ruleset = NULL;
- struct pf_src_node *nsn = NULL;
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
+ struct pf_addr baddr, naddr;
sa_family_t af = pd->af;
u_short reason;
struct pf_tag *pftag = NULL;
@@ -3323,54 +3290,52 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
if (direction == PF_OUT) {
/* check outgoing packet for BINAT/NAT */
- if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
- saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
- PF_ACPY(&pd->baddr, saddr, af);
+ if ((nat = pf_get_translation(pd, m, off, PF_OUT, ifp, saddr, 0,
+ daddr, 0, &naddr, NULL)) != NULL) {
+ PF_ACPY(&baddr, saddr, af);
switch (af) {
#ifdef INET
case AF_INET:
pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
- pd->naddr.v4.s_addr, 0);
+ naddr.v4.s_addr, 0);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- PF_ACPY(saddr, &pd->naddr, af);
+ PF_ACPY(saddr, &naddr, af);
break;
#endif /* INET6 */
}
- if (nr->natpass)
+ if (nat->natpass)
r = NULL;
- pd->nat_rule = nr;
}
} else {
/* check incoming packet for BINAT/RDR */
- if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
- saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
- PF_ACPY(&pd->baddr, daddr, af);
+ if ((rdr = pf_get_translation(pd, m, off, PF_IN, ifp, saddr, 0,
+ daddr, 0, &naddr, NULL)) != NULL) {
+ PF_ACPY(&baddr, daddr, af);
switch (af) {
#ifdef INET
case AF_INET:
pf_change_a(&daddr->v4.s_addr,
- pd->ip_sum, pd->naddr.v4.s_addr, 0);
+ pd->ip_sum, naddr.v4.s_addr, 0);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- PF_ACPY(daddr, &pd->naddr, af);
+ PF_ACPY(daddr, &naddr, af);
break;
#endif /* INET6 */
}
- if (nr->natpass)
+ if (rdr->natpass)
r = NULL;
- pd->nat_rule = nr;
}
}
while (r != NULL) {
r->evaluations++;
- if (r->kif != NULL &&
- (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+ if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
+ (r->ifp == ifp && r->ifnot)))
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -3386,7 +3351,8 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
r = TAILQ_NEXT(r, entries);
else if (r->rule_flag & PFRULE_FRAGMENT)
r = TAILQ_NEXT(r, entries);
- else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
+ else if (r->match_tag &&
+ !pf_match_tag(m, r, nat, rdr, pftag, &tag))
r = TAILQ_NEXT(r, entries);
else if (r->anchorname[0] && r->anchor == NULL)
r = TAILQ_NEXT(r, entries);
@@ -3414,33 +3380,36 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
a = *am;
ruleset = *rsm;
+ r->packets++;
+ r->bytes += pd->tot_len;
+ if (a != NULL) {
+ a->packets++;
+ a->bytes += pd->tot_len;
+ }
REASON_SET(&reason, PFRES_MATCH);
-
if (r->log)
- PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
+ PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
if ((r->action == PF_DROP) &&
((r->rule_flag & PFRULE_RETURNICMP) ||
(r->rule_flag & PFRULE_RETURN))) {
struct pf_addr *a = NULL;
- if (nr != NULL) {
- if (direction == PF_OUT)
- a = saddr;
- else
- a = daddr;
- }
+ if (nat != NULL)
+ a = saddr;
+ else if (rdr != NULL)
+ a = daddr;
if (a != NULL) {
switch (af) {
#ifdef INET
case AF_INET:
pf_change_a(&a->v4.s_addr, pd->ip_sum,
- pd->baddr.v4.s_addr, 0);
+ baddr.v4.s_addr, 0);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- PF_ACPY(a, &pd->baddr, af);
+ PF_ACPY(a, &baddr, af);
break;
#endif /* INET6 */
}
@@ -3461,41 +3430,13 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
return (PF_DROP);
}
- if (r->keep_state || nr != NULL) {
+ if (r->keep_state || nat != NULL || rdr != NULL) {
/* create new state */
struct pf_state *s = NULL;
- struct pf_src_node *sn = NULL;
-
- /* check maximums */
- if (r->max_states && (r->states >= r->max_states))
- goto cleanup;
- /* src node for flter rule */
- if ((r->rule_flag & PFRULE_SRCTRACK ||
- r->rpool.opts & PF_POOL_STICKYADDR) &&
- pf_insert_src_node(&sn, r, saddr, af) != 0)
- goto cleanup;
- /* src node for translation rule */
- if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
- ((direction == PF_OUT &&
- pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
- (pf_insert_src_node(&nsn, nr, saddr, af) != 0)))
- goto cleanup;
- s = pool_get(&pf_state_pl, PR_NOWAIT);
+
+ if (!r->max_states || r->states < r->max_states)
+ s = pool_get(&pf_state_pl, PR_NOWAIT);
if (s == NULL) {
-cleanup:
- if (sn != NULL && sn->states == 0 && sn->expire == 0) {
- RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
- pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
- pf_status.src_nodes--;
- pool_put(&pf_src_tree_pl, sn);
- }
- if (nsn != sn && nsn != NULL && nsn->states == 0 &&
- nsn->expire == 0) {
- RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
- pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
- pf_status.src_nodes--;
- pool_put(&pf_src_tree_pl, nsn);
- }
REASON_SET(&reason, PFRES_MEMORY);
return (PF_DROP);
}
@@ -3504,7 +3445,10 @@ cleanup:
if (a != NULL)
a->states++;
s->rule.ptr = r;
- s->nat_rule.ptr = nr;
+ if (nat != NULL)
+ s->nat_rule.ptr = nat;
+ else
+ s->nat_rule.ptr = rdr;
if (s->nat_rule.ptr != NULL)
s->nat_rule.ptr->states++;
s->anchor.ptr = a;
@@ -3515,37 +3459,51 @@ cleanup:
s->af = af;
if (direction == PF_OUT) {
PF_ACPY(&s->gwy.addr, saddr, af);
+ s->gwy.port = 0;
PF_ACPY(&s->ext.addr, daddr, af);
- if (nr != NULL)
- PF_ACPY(&s->lan.addr, &pd->baddr, af);
+ s->ext.port = 0;
+ if (nat != NULL)
+ PF_ACPY(&s->lan.addr, &baddr, af);
else
PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
+ s->lan.port = 0;
} else {
PF_ACPY(&s->lan.addr, daddr, af);
+ s->lan.port = 0;
PF_ACPY(&s->ext.addr, saddr, af);
- if (nr != NULL)
- PF_ACPY(&s->gwy.addr, &pd->baddr, af);
+ s->ext.port = 0;
+ if (rdr != NULL)
+ PF_ACPY(&s->gwy.addr, &baddr, af);
else
PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
+ s->gwy.port = 0;
}
+ s->src.seqlo = 0;
+ s->src.seqhi = 0;
+ s->src.seqdiff = 0;
+ s->src.max_win = 0;
s->src.state = PFOTHERS_SINGLE;
+ s->dst.seqlo = 0;
+ s->dst.seqhi = 0;
+ s->dst.seqdiff = 0;
+ s->dst.max_win = 0;
s->dst.state = PFOTHERS_NO_TRAFFIC;
+#ifdef __FreeBSD__
+ s->creation = time_second;
+ s->expire = time_second;
+#else
s->creation = time.tv_sec;
s->expire = time.tv_sec;
+#endif
s->timeout = PFTM_OTHER_FIRST_PACKET;
+ s->packets[0] = 1;
+ s->bytes[0] = pd->tot_len;
pf_set_rt_ifp(s, saddr);
- if (sn != NULL) {
- s->src_node = sn;
- s->src_node->states++;
- }
- if (nsn != NULL) {
- PF_ACPY(&nsn->raddr, &pd->naddr, af);
- s->nat_src_node = nsn;
- s->nat_src_node->states++;
- }
- if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
+ if (pf_insert_state(s)) {
REASON_SET(&reason, PFRES_MEMORY);
- pf_src_tree_remove_state(s);
+ if (r->log)
+ PFLOG_PACKET(ifp, h, m, af, direction, reason,
+ r, a, ruleset);
pool_put(&pf_state_pl, s);
return (PF_DROP);
} else
@@ -3556,7 +3514,7 @@ cleanup:
}
int
-pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
+pf_test_fragment(struct pf_rule **rm, int direction, struct ifnet *ifp,
struct mbuf *m, void *h, struct pf_pdesc *pd, struct pf_rule **am,
struct pf_ruleset **rsm)
{
@@ -3570,8 +3528,8 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
while (r != NULL) {
r->evaluations++;
- if (r->kif != NULL &&
- (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+ if (r->ifp != NULL && ((r->ifp != ifp && !r->ifnot) ||
+ (r->ifp == ifp && r->ifnot)))
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != direction)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -3589,7 +3547,8 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
r->flagset || r->type || r->code ||
r->os_fingerprint != PF_OSFP_ANY)
r = TAILQ_NEXT(r, entries);
- else if (r->match_tag && !pf_match_tag(m, r, NULL, pftag, &tag))
+ else if (r->match_tag &&
+ !pf_match_tag(m, r, NULL, NULL, pftag, &tag))
r = TAILQ_NEXT(r, entries);
else if (r->anchorname[0] && r->anchor == NULL)
r = TAILQ_NEXT(r, entries);
@@ -3613,10 +3572,15 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
a = *am;
ruleset = *rsm;
+ r->packets++;
+ r->bytes += pd->tot_len;
+ if (a != NULL) {
+ a->packets++;
+ a->bytes += pd->tot_len;
+ }
REASON_SET(&reason, PFRES_MATCH);
-
if (r->log)
- PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset);
+ PFLOG_PACKET(ifp, h, m, af, direction, reason, r, a, ruleset);
if (r->action != PF_PASS)
return (PF_DROP);
@@ -3630,41 +3594,36 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
}
int
-pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
- struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
+pf_test_state_tcp(struct pf_state **state, int direction, struct ifnet *ifp,
+ struct mbuf *m, int ipoff, int off, void *h, struct pf_pdesc *pd,
u_short *reason)
{
- struct pf_state key;
+ struct pf_tree_node key;
struct tcphdr *th = pd->hdr.tcp;
u_int16_t win = ntohs(th->th_win);
u_int32_t ack, end, seq;
u_int8_t sws, dws;
- int ackskew;
+ int ackskew, dirndx;
int copyback = 0;
struct pf_state_peer *src, *dst;
key.af = pd->af;
key.proto = IPPROTO_TCP;
- if (direction == PF_IN) {
- PF_ACPY(&key.ext.addr, pd->src, key.af);
- PF_ACPY(&key.gwy.addr, pd->dst, key.af);
- key.ext.port = th->th_sport;
- key.gwy.port = th->th_dport;
- } else {
- PF_ACPY(&key.lan.addr, pd->src, key.af);
- PF_ACPY(&key.ext.addr, pd->dst, key.af);
- key.lan.port = th->th_sport;
- key.ext.port = th->th_dport;
- }
+ PF_ACPY(&key.addr[0], pd->src, key.af);
+ PF_ACPY(&key.addr[1], pd->dst, key.af);
+ key.port[0] = th->th_sport;
+ key.port[1] = th->th_dport;
STATE_LOOKUP();
if (direction == (*state)->direction) {
src = &(*state)->src;
dst = &(*state)->dst;
+ dirndx = 0;
} else {
src = &(*state)->dst;
dst = &(*state)->src;
+ dirndx = 1;
}
if ((*state)->src.state == PF_TCPS_PROXY_SRC) {
@@ -3705,8 +3664,7 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
(*state)->dst.seqhi = arc4random();
pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr,
&dst->addr, src->port, dst->port,
- (*state)->dst.seqhi, 0, TH_SYN, 0,
- (*state)->src.mss, 0);
+ (*state)->dst.seqhi, 0, TH_SYN, 0, (*state)->src.mss, 0);
return (PF_SYNPROXY_DROP);
} else if (((th->th_flags & (TH_SYN|TH_ACK)) !=
(TH_SYN|TH_ACK)) ||
@@ -3863,6 +3821,9 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
(ackskew <= (MAXACKWINDOW << sws))) {
/* Acking not more than one window forward */
+ (*state)->packets[dirndx]++;
+ (*state)->bytes[dirndx] += pd->tot_len;
+
/* update max window */
if (src->max_win < win)
src->max_win = win;
@@ -3891,7 +3852,11 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
src->state = dst->state = TCPS_TIME_WAIT;
/* update expire time */
+#ifdef __FreeBSD__
+ (*state)->expire = time_second;
+#else
(*state)->expire = time.tv_sec;
+#endif
if (src->state >= TCPS_FIN_WAIT_2 &&
dst->state >= TCPS_FIN_WAIT_2)
(*state)->timeout = PFTM_TCP_CLOSED;
@@ -3947,6 +3912,9 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
(*state)->packets[0], (*state)->packets[1]);
}
+ (*state)->packets[dirndx]++;
+ (*state)->bytes[dirndx] += pd->tot_len;
+
/* update max window */
if (src->max_win < win)
src->max_win = win;
@@ -4012,8 +3980,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
}
if (dst->scrub || src->scrub) {
- if (pf_normalize_tcp_stateful(m, off, pd, reason, th,
- src, dst, &copyback))
+ if (pf_normalize_tcp_stateful(m, off, pd, reason, th, src, dst,
+ &copyback))
return (PF_DROP);
}
@@ -4029,47 +3997,56 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
&th->th_sum, &(*state)->lan.addr,
(*state)->lan.port, 0, pd->af);
- m_copyback(m, off, sizeof(*th), th);
+ m_copyback(m, off, sizeof(*th), (caddr_t)th);
} else if (copyback) {
/* Copyback sequence modulation or stateful scrub changes */
- m_copyback(m, off, sizeof(*th), th);
+ m_copyback(m, off, sizeof(*th), (caddr_t)th);
}
+ (*state)->rule.ptr->packets++;
+ (*state)->rule.ptr->bytes += pd->tot_len;
+ if ((*state)->nat_rule.ptr != NULL) {
+ (*state)->nat_rule.ptr->packets++;
+ (*state)->nat_rule.ptr->bytes += pd->tot_len;
+ }
+ if ((*state)->anchor.ptr != NULL) {
+ (*state)->anchor.ptr->packets++;
+ (*state)->anchor.ptr->bytes += pd->tot_len;
+ }
return (PF_PASS);
}
int
-pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
- struct mbuf *m, int off, void *h, struct pf_pdesc *pd)
+pf_test_state_udp(struct pf_state **state, int direction, struct ifnet *ifp,
+ struct mbuf *m, int ipoff, int off, void *h, struct pf_pdesc *pd)
{
struct pf_state_peer *src, *dst;
- struct pf_state key;
+ struct pf_tree_node key;
struct udphdr *uh = pd->hdr.udp;
+ int dirndx;
key.af = pd->af;
key.proto = IPPROTO_UDP;
- if (direction == PF_IN) {
- PF_ACPY(&key.ext.addr, pd->src, key.af);
- PF_ACPY(&key.gwy.addr, pd->dst, key.af);
- key.ext.port = uh->uh_sport;
- key.gwy.port = uh->uh_dport;
- } else {
- PF_ACPY(&key.lan.addr, pd->src, key.af);
- PF_ACPY(&key.ext.addr, pd->dst, key.af);
- key.lan.port = uh->uh_sport;
- key.ext.port = uh->uh_dport;
- }
+ PF_ACPY(&key.addr[0], pd->src, key.af);
+ PF_ACPY(&key.addr[1], pd->dst, key.af);
+ key.port[0] = uh->uh_sport;
+ key.port[1] = uh->uh_dport;
STATE_LOOKUP();
if (direction == (*state)->direction) {
src = &(*state)->src;
dst = &(*state)->dst;
+ dirndx = 0;
} else {
src = &(*state)->dst;
dst = &(*state)->src;
+ dirndx = 1;
}
+ (*state)->packets[dirndx]++;
+ (*state)->bytes[dirndx] += pd->tot_len;
+
/* update states */
if (src->state < PFUDPS_SINGLE)
src->state = PFUDPS_SINGLE;
@@ -4077,7 +4054,11 @@ pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
dst->state = PFUDPS_MULTIPLE;
/* update expire time */
+#ifdef __FreeBSD__
+ (*state)->expire = time_second;
+#else
(*state)->expire = time.tv_sec;
+#endif
if (src->state == PFUDPS_MULTIPLE && dst->state == PFUDPS_MULTIPLE)
(*state)->timeout = PFTM_UDP_MULTIPLE;
else
@@ -4093,20 +4074,31 @@ pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
&uh->uh_sum, &(*state)->lan.addr,
(*state)->lan.port, 1, pd->af);
- m_copyback(m, off, sizeof(*uh), uh);
+ m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
}
+ (*state)->rule.ptr->packets++;
+ (*state)->rule.ptr->bytes += pd->tot_len;
+ if ((*state)->nat_rule.ptr != NULL) {
+ (*state)->nat_rule.ptr->packets++;
+ (*state)->nat_rule.ptr->bytes += pd->tot_len;
+ }
+ if ((*state)->anchor.ptr != NULL) {
+ (*state)->anchor.ptr->packets++;
+ (*state)->anchor.ptr->bytes += pd->tot_len;
+ }
return (PF_PASS);
}
int
-pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
- struct mbuf *m, int off, void *h, struct pf_pdesc *pd)
+pf_test_state_icmp(struct pf_state **state, int direction, struct ifnet *ifp,
+ struct mbuf *m, int ipoff, int off, void *h, struct pf_pdesc *pd)
{
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
- u_int16_t icmpid, *icmpsum;
- u_int8_t icmptype;
- int state_icmp = 0;
+ u_int16_t icmpid = 0; /* make the compiler happy */
+ u_int16_t *icmpsum = NULL; /* make the compiler happy */
+ u_int8_t icmptype = 0; /* make the compiler happy */
+ int state_icmp = 0, dirndx;
switch (pd->proto) {
#ifdef INET
@@ -4144,25 +4136,25 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
* ICMP query/reply message not related to a TCP/UDP packet.
* Search for an ICMP state.
*/
- struct pf_state key;
+ struct pf_tree_node key;
key.af = pd->af;
key.proto = pd->proto;
- if (direction == PF_IN) {
- PF_ACPY(&key.ext.addr, pd->src, key.af);
- PF_ACPY(&key.gwy.addr, pd->dst, key.af);
- key.ext.port = icmpid;
- key.gwy.port = icmpid;
- } else {
- PF_ACPY(&key.lan.addr, pd->src, key.af);
- PF_ACPY(&key.ext.addr, pd->dst, key.af);
- key.lan.port = icmpid;
- key.ext.port = icmpid;
- }
+ PF_ACPY(&key.addr[0], saddr, key.af);
+ PF_ACPY(&key.addr[1], daddr, key.af);
+ key.port[0] = icmpid;
+ key.port[1] = icmpid;
STATE_LOOKUP();
+ dirndx = (direction == (*state)->direction) ? 0 : 1;
+ (*state)->packets[dirndx]++;
+ (*state)->bytes[dirndx] += pd->tot_len;
+#ifdef __FreeBSD__
+ (*state)->expire = time_second;
+#else
(*state)->expire = time.tv_sec;
+#endif
(*state)->timeout = PFTM_ICMP_ERROR_REPLY;
/* translate source/destination address, if necessary */
@@ -4183,7 +4175,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
&(*state)->gwy.addr, 0);
m_copyback(m, off,
sizeof(struct icmp6_hdr),
- pd->hdr.icmp6);
+ (caddr_t)pd->hdr.icmp6);
break;
#endif /* INET6 */
}
@@ -4203,7 +4195,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
&(*state)->lan.addr, 0);
m_copyback(m, off,
sizeof(struct icmp6_hdr),
- pd->hdr.icmp6);
+ (caddr_t)pd->hdr.icmp6);
break;
#endif /* INET6 */
}
@@ -4226,8 +4218,8 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
struct ip6_hdr h2_6;
int terminal = 0;
#endif /* INET6 */
- int ipoff2;
- int off2;
+ int ipoff2 = 0; /* make the compiler happy */
+ int off2 = 0; /* make the compiler happy */
pd2.af = pd->af;
switch (pd->af) {
@@ -4317,7 +4309,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
case IPPROTO_TCP: {
struct tcphdr th;
u_int32_t seq;
- struct pf_state key;
+ struct pf_tree_node key;
struct pf_state_peer *src, *dst;
u_int8_t dws;
int copyback = 0;
@@ -4336,17 +4328,10 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
key.af = pd2.af;
key.proto = IPPROTO_TCP;
- if (direction == PF_IN) {
- PF_ACPY(&key.ext.addr, pd2.dst, key.af);
- PF_ACPY(&key.gwy.addr, pd2.src, key.af);
- key.ext.port = th.th_dport;
- key.gwy.port = th.th_sport;
- } else {
- PF_ACPY(&key.lan.addr, pd2.dst, key.af);
- PF_ACPY(&key.ext.addr, pd2.src, key.af);
- key.lan.port = th.th_dport;
- key.ext.port = th.th_sport;
- }
+ PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
+ key.port[0] = th.th_dport;
+ PF_ACPY(&key.addr[1], pd2.src, pd2.af);
+ key.port[1] = th.th_sport;
STATE_LOOKUP();
@@ -4358,8 +4343,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
dst = &(*state)->dst;
}
- if (src->wscale && dst->wscale &&
- !(th.th_flags & TH_SYN))
+ if (src->wscale && dst->wscale && !(th.th_flags & TH_SYN))
dws = dst->wscale & PF_WSCALE_MASK;
else
dws = 0;
@@ -4409,22 +4393,22 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
#ifdef INET
case AF_INET:
m_copyback(m, off, ICMP_MINLEN,
- pd->hdr.icmp);
+ (caddr_t)pd->hdr.icmp);
m_copyback(m, ipoff2, sizeof(h2),
- &h2);
+ (caddr_t)&h2);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
m_copyback(m, off,
sizeof(struct icmp6_hdr),
- pd->hdr.icmp6);
+ (caddr_t)pd->hdr.icmp6);
m_copyback(m, ipoff2, sizeof(h2_6),
- &h2_6);
+ (caddr_t)&h2_6);
break;
#endif /* INET6 */
}
- m_copyback(m, off2, 8, &th);
+ m_copyback(m, off2, 8, (caddr_t)&th);
}
return (PF_PASS);
@@ -4432,7 +4416,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
}
case IPPROTO_UDP: {
struct udphdr uh;
- struct pf_state key;
+ struct pf_tree_node key;
if (!pf_pull_hdr(m, off2, &uh, sizeof(uh),
NULL, NULL, pd2.af)) {
@@ -4444,17 +4428,10 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
key.af = pd2.af;
key.proto = IPPROTO_UDP;
- if (direction == PF_IN) {
- PF_ACPY(&key.ext.addr, pd2.dst, key.af);
- PF_ACPY(&key.gwy.addr, pd2.src, key.af);
- key.ext.port = uh.uh_dport;
- key.gwy.port = uh.uh_sport;
- } else {
- PF_ACPY(&key.lan.addr, pd2.dst, key.af);
- PF_ACPY(&key.ext.addr, pd2.src, key.af);
- key.lan.port = uh.uh_dport;
- key.ext.port = uh.uh_sport;
- }
+ PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
+ key.port[0] = uh.uh_dport;
+ PF_ACPY(&key.addr[1], pd2.src, pd2.af);
+ key.port[1] = uh.uh_sport;
STATE_LOOKUP();
@@ -4476,21 +4453,23 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
#ifdef INET
case AF_INET:
m_copyback(m, off, ICMP_MINLEN,
- pd->hdr.icmp);
- m_copyback(m, ipoff2, sizeof(h2), &h2);
+ (caddr_t)pd->hdr.icmp);
+ m_copyback(m, ipoff2, sizeof(h2),
+ (caddr_t)&h2);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
m_copyback(m, off,
sizeof(struct icmp6_hdr),
- pd->hdr.icmp6);
+ (caddr_t)pd->hdr.icmp6);
m_copyback(m, ipoff2, sizeof(h2_6),
- &h2_6);
+ (caddr_t)&h2_6);
break;
#endif /* INET6 */
}
- m_copyback(m, off2, sizeof(uh), &uh);
+ m_copyback(m, off2, sizeof(uh),
+ (caddr_t)&uh);
}
return (PF_PASS);
@@ -4499,7 +4478,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
#ifdef INET
case IPPROTO_ICMP: {
struct icmp iih;
- struct pf_state key;
+ struct pf_tree_node key;
if (!pf_pull_hdr(m, off2, &iih, ICMP_MINLEN,
NULL, NULL, pd2.af)) {
@@ -4511,17 +4490,10 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
key.af = pd2.af;
key.proto = IPPROTO_ICMP;
- if (direction == PF_IN) {
- PF_ACPY(&key.ext.addr, pd2.dst, key.af);
- PF_ACPY(&key.gwy.addr, pd2.src, key.af);
- key.ext.port = iih.icmp_id;
- key.gwy.port = iih.icmp_id;
- } else {
- PF_ACPY(&key.lan.addr, pd2.dst, key.af);
- PF_ACPY(&key.ext.addr, pd2.src, key.af);
- key.lan.port = iih.icmp_id;
- key.ext.port = iih.icmp_id;
- }
+ PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
+ key.port[0] = iih.icmp_id;
+ PF_ACPY(&key.addr[1], pd2.src, pd2.af);
+ key.port[1] = iih.icmp_id;
STATE_LOOKUP();
@@ -4539,9 +4511,12 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
pd2.ip_sum, icmpsum,
pd->ip_sum, 0, AF_INET);
}
- m_copyback(m, off, ICMP_MINLEN, pd->hdr.icmp);
- m_copyback(m, ipoff2, sizeof(h2), &h2);
- m_copyback(m, off2, ICMP_MINLEN, &iih);
+ m_copyback(m, off, ICMP_MINLEN,
+ (caddr_t)pd->hdr.icmp);
+ m_copyback(m, ipoff2, sizeof(h2),
+ (caddr_t)&h2);
+ m_copyback(m, off2, ICMP_MINLEN,
+ (caddr_t)&iih);
}
return (PF_PASS);
@@ -4551,7 +4526,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
#ifdef INET6
case IPPROTO_ICMPV6: {
struct icmp6_hdr iih;
- struct pf_state key;
+ struct pf_tree_node key;
if (!pf_pull_hdr(m, off2, &iih,
sizeof(struct icmp6_hdr), NULL, NULL, pd2.af)) {
@@ -4563,17 +4538,10 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
key.af = pd2.af;
key.proto = IPPROTO_ICMPV6;
- if (direction == PF_IN) {
- PF_ACPY(&key.ext.addr, pd2.dst, key.af);
- PF_ACPY(&key.gwy.addr, pd2.src, key.af);
- key.ext.port = iih.icmp6_id;
- key.gwy.port = iih.icmp6_id;
- } else {
- PF_ACPY(&key.lan.addr, pd2.dst, key.af);
- PF_ACPY(&key.ext.addr, pd2.src, key.af);
- key.lan.port = iih.icmp6_id;
- key.ext.port = iih.icmp6_id;
- }
+ PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
+ key.port[0] = iih.icmp6_id;
+ PF_ACPY(&key.addr[1], pd2.src, pd2.af);
+ key.port[1] = iih.icmp6_id;
STATE_LOOKUP();
@@ -4592,10 +4560,11 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
pd->ip_sum, 0, AF_INET6);
}
m_copyback(m, off, sizeof(struct icmp6_hdr),
- pd->hdr.icmp6);
- m_copyback(m, ipoff2, sizeof(h2_6), &h2_6);
+ (caddr_t)pd->hdr.icmp6);
+ m_copyback(m, ipoff2, sizeof(h2_6),
+ (caddr_t)&h2_6);
m_copyback(m, off2, sizeof(struct icmp6_hdr),
- &iih);
+ (caddr_t)&iih);
}
return (PF_PASS);
@@ -4603,21 +4572,14 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
}
#endif /* INET6 */
default: {
- struct pf_state key;
+ struct pf_tree_node key;
key.af = pd2.af;
key.proto = pd2.proto;
- if (direction == PF_IN) {
- PF_ACPY(&key.ext.addr, pd2.dst, key.af);
- PF_ACPY(&key.gwy.addr, pd2.src, key.af);
- key.ext.port = 0;
- key.gwy.port = 0;
- } else {
- PF_ACPY(&key.lan.addr, pd2.dst, key.af);
- PF_ACPY(&key.ext.addr, pd2.src, key.af);
- key.lan.port = 0;
- key.ext.port = 0;
- }
+ PF_ACPY(&key.addr[0], pd2.dst, pd2.af);
+ key.port[0] = 0;
+ PF_ACPY(&key.addr[1], pd2.src, pd2.af);
+ key.port[1] = 0;
STATE_LOOKUP();
@@ -4639,17 +4601,18 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
#ifdef INET
case AF_INET:
m_copyback(m, off, ICMP_MINLEN,
- pd->hdr.icmp);
- m_copyback(m, ipoff2, sizeof(h2), &h2);
+ (caddr_t)pd->hdr.icmp);
+ m_copyback(m, ipoff2, sizeof(h2),
+ (caddr_t)&h2);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
m_copyback(m, off,
sizeof(struct icmp6_hdr),
- pd->hdr.icmp6);
+ (caddr_t)pd->hdr.icmp6);
m_copyback(m, ipoff2, sizeof(h2_6),
- &h2_6);
+ (caddr_t)&h2_6);
break;
#endif /* INET6 */
}
@@ -4663,36 +4626,35 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
}
int
-pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
+pf_test_state_other(struct pf_state **state, int direction, struct ifnet *ifp,
struct pf_pdesc *pd)
{
struct pf_state_peer *src, *dst;
- struct pf_state key;
+ struct pf_tree_node key;
+ int dirndx;
key.af = pd->af;
key.proto = pd->proto;
- if (direction == PF_IN) {
- PF_ACPY(&key.ext.addr, pd->src, key.af);
- PF_ACPY(&key.gwy.addr, pd->dst, key.af);
- key.ext.port = 0;
- key.gwy.port = 0;
- } else {
- PF_ACPY(&key.lan.addr, pd->src, key.af);
- PF_ACPY(&key.ext.addr, pd->dst, key.af);
- key.lan.port = 0;
- key.ext.port = 0;
- }
+ PF_ACPY(&key.addr[0], pd->src, key.af);
+ PF_ACPY(&key.addr[1], pd->dst, key.af);
+ key.port[0] = 0;
+ key.port[1] = 0;
STATE_LOOKUP();
if (direction == (*state)->direction) {
src = &(*state)->src;
dst = &(*state)->dst;
+ dirndx = 0;
} else {
src = &(*state)->dst;
dst = &(*state)->src;
+ dirndx = 1;
}
+ (*state)->packets[dirndx]++;
+ (*state)->bytes[dirndx] += pd->tot_len;
+
/* update states */
if (src->state < PFOTHERS_SINGLE)
src->state = PFOTHERS_SINGLE;
@@ -4700,7 +4662,11 @@ pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
dst->state = PFOTHERS_MULTIPLE;
/* update expire time */
+#ifdef __FreeBSD__
+ (*state)->expire = time_second;
+#else
(*state)->expire = time.tv_sec;
+#endif
if (src->state == PFOTHERS_MULTIPLE && dst->state == PFOTHERS_MULTIPLE)
(*state)->timeout = PFTM_OTHER_MULTIPLE;
else
@@ -4740,6 +4706,16 @@ pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
}
}
+ (*state)->rule.ptr->packets++;
+ (*state)->rule.ptr->bytes += pd->tot_len;
+ if ((*state)->nat_rule.ptr != NULL) {
+ (*state)->nat_rule.ptr->packets++;
+ (*state)->nat_rule.ptr->bytes += pd->tot_len;
+ }
+ if ((*state)->anchor.ptr != NULL) {
+ (*state)->anchor.ptr->packets++;
+ (*state)->anchor.ptr->bytes += pd->tot_len;
+ }
return (PF_PASS);
}
@@ -4766,8 +4742,7 @@ pf_pull_hdr(struct mbuf *m, int off, void *p, int len,
}
return (NULL);
}
- if (m->m_pkthdr.len < off + len ||
- ntohs(h->ip_len) < off + len) {
+ if (m->m_pkthdr.len < off + len || ntohs(h->ip_len) < off + len) {
ACTION_SET(actionp, PF_DROP);
REASON_SET(reasonp, PFRES_SHORT);
return (NULL);
@@ -4806,7 +4781,15 @@ pf_routable(struct pf_addr *addr, sa_family_t af)
dst->sin_family = af;
dst->sin_len = sizeof(*dst);
dst->sin_addr = addr->v4;
+#ifdef __FreeBSD__
+#ifdef RTF_PRCLONING
+ rtalloc_ign(&ro, (RTF_CLONING|RTF_PRCLONING));
+#else /* !RTF_PRCLONING */
+ rtalloc_ign(&ro, RTF_CLONING);
+#endif
+#else /* ! __FreeBSD__ */
rtalloc_noclone(&ro, NO_CLONING);
+#endif
if (ro.ro_rt != NULL) {
ret = 1;
@@ -4817,20 +4800,184 @@ pf_routable(struct pf_addr *addr, sa_family_t af)
}
#ifdef INET
+
+#if defined(__FreeBSD__) && (__FreeBSD_version < 501105)
+int
+ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
+ u_long if_hwassist_flags, int sw_csum)
+{
+ int error = 0;
+ int hlen = ip->ip_hl << 2;
+ int len = (mtu - hlen) & ~7; /* size of payload in each fragment */
+ int off;
+ struct mbuf *m0 = *m_frag; /* the original packet */
+ int firstlen;
+ struct mbuf **mnext;
+ int nfrags;
+
+ if (ip->ip_off & IP_DF) { /* Fragmentation not allowed */
+ ipstat.ips_cantfrag++;
+ return EMSGSIZE;
+ }
+
+ /*
+ * Must be able to put at least 8 bytes per fragment.
+ */
+ if (len < 8)
+ return EMSGSIZE;
+
+ /*
+ * If the interface will not calculate checksums on
+ * fragmented packets, then do it here.
+ */
+ if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA &&
+ (if_hwassist_flags & CSUM_IP_FRAGS) == 0) {
+ in_delayed_cksum(m0);
+ m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+ }
+
+ if (len > PAGE_SIZE) {
+ /*
+ * Fragment large datagrams such that each segment
+ * contains a multiple of PAGE_SIZE amount of data,
+ * plus headers. This enables a receiver to perform
+ * page-flipping zero-copy optimizations.
+ *
+ * XXX When does this help given that sender and receiver
+ * could have different page sizes, and also mtu could
+ * be less than the receiver's page size ?
+ */
+ int newlen;
+ struct mbuf *m;
+
+ for (m = m0, off = 0; m && (off+m->m_len) <= mtu; m = m->m_next)
+ off += m->m_len;
+
+ /*
+ * firstlen (off - hlen) must be aligned on an
+ * 8-byte boundary
+ */
+ if (off < hlen)
+ goto smart_frag_failure;
+ off = ((off - hlen) & ~7) + hlen;
+ newlen = (~PAGE_MASK) & mtu;
+ if ((newlen + sizeof (struct ip)) > mtu) {
+ /* we failed, go back the default */
+smart_frag_failure:
+ newlen = len;
+ off = hlen + len;
+ }
+ len = newlen;
+
+ } else {
+ off = hlen + len;
+ }
+
+ firstlen = off - hlen;
+ mnext = &m0->m_nextpkt; /* pointer to next packet */
+
+ /*
+ * Loop through length of segment after first fragment,
+ * make new header and copy data of each part and link onto chain.
+ * Here, m0 is the original packet, m is the fragment being created.
+ * The fragments are linked off the m_nextpkt of the original
+ * packet, which after processing serves as the first fragment.
+ */
+ for (nfrags = 1; off < ip->ip_len; off += len, nfrags++) {
+ struct ip *mhip; /* ip header on the fragment */
+ struct mbuf *m;
+ int mhlen = sizeof (struct ip);
+
+ MGETHDR(m, M_DONTWAIT, MT_HEADER);
+ if (m == 0) {
+ error = ENOBUFS;
+ ipstat.ips_odropped++;
+ goto done;
+ }
+ m->m_flags |= (m0->m_flags & M_MCAST) | M_FRAG;
+ /*
+ * In the first mbuf, leave room for the link header, then
+ * copy the original IP header including options. The payload
+ * goes into an additional mbuf chain returned by m_copy().
+ */
+ m->m_data += max_linkhdr;
+ mhip = mtod(m, struct ip *);
+ *mhip = *ip;
+ if (hlen > sizeof (struct ip)) {
+ mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
+ mhip->ip_v = IPVERSION;
+ mhip->ip_hl = mhlen >> 2;
+ }
+ m->m_len = mhlen;
+ /* XXX do we need to add ip->ip_off below ? */
+ mhip->ip_off = ((off - hlen) >> 3) + ip->ip_off;
+ if (off + len >= ip->ip_len) { /* last fragment */
+ len = ip->ip_len - off;
+ m->m_flags |= M_LASTFRAG;
+ } else
+ mhip->ip_off |= IP_MF;
+ mhip->ip_len = htons((u_short)(len + mhlen));
+ m->m_next = m_copy(m0, off, len);
+ if (m->m_next == 0) { /* copy failed */
+ m_free(m);
+ error = ENOBUFS; /* ??? */
+ ipstat.ips_odropped++;
+ goto done;
+ }
+ m->m_pkthdr.len = mhlen + len;
+ m->m_pkthdr.rcvif = (struct ifnet *)0;
+#ifdef MAC
+ mac_create_fragment(m0, m);
+#endif
+ m->m_pkthdr.csum_flags = m0->m_pkthdr.csum_flags;
+ mhip->ip_off = htons(mhip->ip_off);
+ mhip->ip_sum = 0;
+ if (sw_csum & CSUM_DELAY_IP)
+ mhip->ip_sum = in_cksum(m, mhlen);
+ *mnext = m;
+ mnext = &m->m_nextpkt;
+ }
+ ipstat.ips_ofragments += nfrags;
+
+ /* set first marker for fragment chain */
+ m0->m_flags |= M_FIRSTFRAG | M_FRAG;
+ m0->m_pkthdr.csum_data = nfrags;
+
+ /*
+ * Update first fragment by trimming what's been copied out
+ * and updating header.
+ */
+ m_adj(m0, hlen + firstlen - ip->ip_len);
+ m0->m_pkthdr.len = hlen + firstlen;
+ ip->ip_len = htons((u_short)m0->m_pkthdr.len);
+ ip->ip_off |= IP_MF;
+ ip->ip_off = htons(ip->ip_off);
+ ip->ip_sum = 0;
+ if (sw_csum & CSUM_DELAY_IP)
+ ip->ip_sum = in_cksum(m0, hlen);
+
+done:
+ *m_frag = m0;
+ return error;
+}
+#endif /* __FreeBSD__ && __FreeBSD_version > 501105 */
+
void
pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
struct pf_state *s)
{
struct mbuf *m0, *m1;
struct route iproute;
- struct route *ro;
+ struct route *ro = NULL; /* XXX: was uninitialized */
struct sockaddr_in *dst;
struct ip *ip;
struct ifnet *ifp = NULL;
struct m_tag *mtag;
struct pf_addr naddr;
- struct pf_src_node *sn = NULL;
int error = 0;
+#ifdef __FreeBSD__
+ int sw_csum;
+#endif
if (m == NULL || *m == NULL || r == NULL ||
(dir != PF_IN && dir != PF_OUT) || oifp == NULL)
@@ -4845,7 +4992,11 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
goto bad;
m_tag_prepend(m0, mtag);
}
+#ifdef __FreeBSD__
+ m0 = m_dup(*m, M_DONTWAIT);
+#else
m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT);
+#endif
if (m0 == NULL)
return;
} else {
@@ -4881,72 +5032,94 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
if (TAILQ_EMPTY(&r->rpool.list))
panic("pf_route: TAILQ_EMPTY(&r->rpool.list)");
if (s == NULL) {
- pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src,
- &naddr, NULL, &sn);
+ pf_map_addr(AF_INET, &r->rpool,
+ (struct pf_addr *)&ip->ip_src,
+ &naddr, NULL);
if (!PF_AZERO(&naddr, AF_INET))
dst->sin_addr.s_addr = naddr.v4.s_addr;
- ifp = r->rpool.cur->kif ?
- r->rpool.cur->kif->pfik_ifp : NULL;
+ ifp = r->rpool.cur->ifp;
} else {
if (!PF_AZERO(&s->rt_addr, AF_INET))
dst->sin_addr.s_addr =
s->rt_addr.v4.s_addr;
- ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
+ ifp = s->rt_ifp;
}
}
if (ifp == NULL)
goto bad;
- mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL);
- if (mtag == NULL) {
- struct m_tag *mtag;
+ if (m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL) != NULL)
+ goto bad;
+ mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
+ if (mtag == NULL)
+ goto bad;
+ m_tag_prepend(m0, mtag);
- mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
- if (mtag == NULL)
+ if (oifp != ifp) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ if (pf_test(PF_OUT, ifp, &m0) != PF_PASS) {
+ PF_LOCK();
goto bad;
- m_tag_prepend(m0, mtag);
- }
-
- if (oifp != ifp && mtag == NULL) {
+ } else if (m0 == NULL) {
+ PF_LOCK();
+ goto done;
+ }
+ PF_LOCK();
+#else
if (pf_test(PF_OUT, ifp, &m0) != PF_PASS)
goto bad;
else if (m0 == NULL)
goto done;
+#endif
if (m0->m_len < sizeof(struct ip))
panic("pf_route: m0->m_len < sizeof(struct ip)");
ip = mtod(m0, struct ip *);
}
- /* Copied from ip_output. */
-#ifdef IPSEC
- /*
- * If deferred crypto processing is needed, check that the
- * interface supports it.
- */
- if ((mtag = m_tag_find(m0, PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED, NULL))
- != NULL && (ifp->if_capabilities & IFCAP_IPSEC) == 0) {
- /* Notify IPsec to do its own crypto. */
- ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1));
- goto bad;
- }
-#endif /* IPSEC */
-
- /* Catch routing changes wrt. hardware checksumming for TCP or UDP. */
- if (m0->m_pkthdr.csum & M_TCPV4_CSUM_OUT) {
- if (!(ifp->if_capabilities & IFCAP_CSUM_TCPv4) ||
- ifp->if_bridge != NULL) {
- in_delayed_cksum(m0);
- m0->m_pkthdr.csum &= ~M_TCPV4_CSUM_OUT; /* Clear */
- }
- } else if (m0->m_pkthdr.csum & M_UDPV4_CSUM_OUT) {
- if (!(ifp->if_capabilities & IFCAP_CSUM_UDPv4) ||
- ifp->if_bridge != NULL) {
- in_delayed_cksum(m0);
- m0->m_pkthdr.csum &= ~M_UDPV4_CSUM_OUT; /* Clear */
+#ifdef __FreeBSD__
+ /* Copied from FreeBSD 5.1-CURRENT ip_output. */
+ m0->m_pkthdr.csum_flags |= CSUM_IP;
+ sw_csum = m0->m_pkthdr.csum_flags & ~ifp->if_hwassist;
+ if (sw_csum & CSUM_DELAY_DATA) {
+ /*
+ * XXX: in_delayed_cksum assumes HBO for ip->ip_len (at least)
+ */
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off); /* XXX: needed? */
+ in_delayed_cksum(m0);
+ HTONS(ip->ip_len);
+ HTONS(ip->ip_off);
+ sw_csum &= ~CSUM_DELAY_DATA;
+ }
+ m0->m_pkthdr.csum_flags &= ifp->if_hwassist;
+
+ if (ntohs(ip->ip_len) <= ifp->if_mtu ||
+ (ifp->if_hwassist & CSUM_FRAGMENT &&
+ ((ip->ip_off & htons(IP_DF)) == 0))) {
+ /*
+ * ip->ip_len = htons(ip->ip_len);
+ * ip->ip_off = htons(ip->ip_off);
+ */
+ ip->ip_sum = 0;
+ if (sw_csum & CSUM_DELAY_IP) {
+ /* From KAME */
+ if (ip->ip_v == IPVERSION &&
+ (ip->ip_hl << 2) == sizeof(*ip)) {
+ ip->ip_sum = in_cksum_hdr(ip);
+ } else {
+ ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
+ }
}
+ PF_UNLOCK();
+ error = (*ifp->if_output)(ifp, m0, sintosa(dst), ro->ro_rt);
+ PF_LOCK();
+ goto done;
}
+#else
+ /* Copied from ip_output. */
if (ntohs(ip->ip_len) <= ifp->if_mtu) {
if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
ifp->if_bridge == NULL) {
@@ -4964,7 +5137,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
error = (*ifp->if_output)(ifp, m0, sintosa(dst), NULL);
goto done;
}
-
+#endif
/*
* Too large for interface; fragment if possible.
* Must be able to put at least 8 bytes per fragment.
@@ -4972,27 +5145,56 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
if (ip->ip_off & htons(IP_DF)) {
ipstat.ips_cantfrag++;
if (r->rt != PF_DUPTO) {
+#ifdef __FreeBSD__
+ /* icmp_error() expects host byte ordering */
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
+ PF_UNLOCK();
+#endif
icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0,
ifp);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
goto done;
} else
goto bad;
}
m1 = m0;
+#ifdef __FreeBSD__
+ /*
+ * XXX: is cheaper + less error prone than own function
+ */
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
+ error = ip_fragment(ip, &m0, ifp->if_mtu, ifp->if_hwassist, sw_csum);
+#else
error = ip_fragment(m0, ifp, ifp->if_mtu);
+#endif
if (error) {
+#ifndef __FreeBSD__ /* ip_fragment does not do m_freem() on FreeBSD */
m0 = NULL;
+#endif
goto bad;
}
for (m0 = m1; m0; m0 = m1) {
m1 = m0->m_nextpkt;
m0->m_nextpkt = 0;
+#ifdef __FreeBSD__
+ if (error == 0) {
+ PF_UNLOCK();
+ error = (*ifp->if_output)(ifp, m0, sintosa(dst),
+ NULL);
+ PF_LOCK();
+ } else
+#else
if (error == 0)
error = (*ifp->if_output)(ifp, m0, sintosa(dst),
NULL);
else
+#endif
m_freem(m0);
}
@@ -5025,7 +5227,6 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
struct ip6_hdr *ip6;
struct ifnet *ifp = NULL;
struct pf_addr naddr;
- struct pf_src_node *sn = NULL;
int error = 0;
if (m == NULL || *m == NULL || r == NULL ||
@@ -5041,7 +5242,11 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
goto bad;
m_tag_prepend(m0, mtag);
}
+#ifdef __FreeBSD__
+ m0 = m_dup(*m, M_DONTWAIT);
+#else
m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT);
+#endif
if (m0 == NULL)
return;
} else {
@@ -5067,24 +5272,30 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
if (mtag == NULL)
goto bad;
m_tag_prepend(m0, mtag);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
+ PF_LOCK();
+#else
ip6_output(m0, NULL, NULL, 0, NULL, NULL);
+#endif
return;
}
if (TAILQ_EMPTY(&r->rpool.list))
panic("pf_route6: TAILQ_EMPTY(&r->rpool.list)");
if (s == NULL) {
- pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src,
- &naddr, NULL, &sn);
+ pf_map_addr(AF_INET6, &r->rpool,
+ (struct pf_addr *)&ip6->ip6_src, &naddr, NULL);
if (!PF_AZERO(&naddr, AF_INET6))
PF_ACPY((struct pf_addr *)&dst->sin6_addr,
&naddr, AF_INET6);
- ifp = r->rpool.cur->kif ? r->rpool.cur->kif->pfik_ifp : NULL;
+ ifp = r->rpool.cur->ifp;
} else {
if (!PF_AZERO(&s->rt_addr, AF_INET6))
PF_ACPY((struct pf_addr *)&dst->sin6_addr,
&s->rt_addr, AF_INET6);
- ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
+ ifp = s->rt_ifp;
}
if (ifp == NULL)
@@ -5097,10 +5308,22 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
if (mtag == NULL)
goto bad;
m_tag_prepend(m0, mtag);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS) {
+ PF_LOCK();
+ goto bad;
+ } else if (m0 == NULL) {
+ PF_LOCK();
+ goto done;
+ }
+ PF_LOCK();
+#else
if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS)
goto bad;
else if (m0 == NULL)
goto done;
+#endif
}
}
@@ -5111,12 +5334,26 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
if (IN6_IS_ADDR_LINKLOCAL(&dst->sin6_addr))
dst->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
error = nd6_output(ifp, ifp, m0, dst, NULL);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
} else {
in6_ifstat_inc(ifp, ifs6_in_toobig);
+#ifdef __FreeBSD__
+ if (r->rt != PF_DUPTO) {
+ PF_UNLOCK();
+ icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
+ PF_LOCK();
+ } else
+#else
if (r->rt != PF_DUPTO)
icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
else
+#endif
goto bad;
}
@@ -5132,6 +5369,135 @@ bad:
#endif /* INET6 */
+#ifdef __FreeBSD__
+/*
+ * XXX
+ * FreeBSD supports cksum offload for the following drivers.
+ * em(4), gx(4), lge(4), nge(4), ti(4), xl(4)
+ * If we can make full use of it we would outperform ipfw/ipfilter in
+ * very heavy traffic.
+ * I have not tested 'cause I don't have NICs that supports cksum offload.
+ * (There might be problems. Typical phenomena would be
+ * 1. No route message for UDP packet.
+ * 2. No connection acceptance from external hosts regardless of rule set.)
+ */
+int
+pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af)
+{
+ u_int16_t sum = 0;
+ int hw_assist = 0;
+ struct ip *ip;
+
+ if (off < sizeof(struct ip) || len < sizeof(struct udphdr))
+ return (1);
+ if (m->m_pkthdr.len < off + len)
+ return (1);
+
+ switch (p) {
+ case IPPROTO_TCP:
+ if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
+ if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
+ sum = m->m_pkthdr.csum_data;
+ } else {
+ ip = mtod(m, struct ip *);
+ sum = in_pseudo(ip->ip_src.s_addr,
+ ip->ip_dst.s_addr,
+ htonl(m->m_pkthdr.csum_data +
+ IPPROTO_TCP) + ip->ip_len);
+ }
+ sum ^= 0xffff;
+ ++hw_assist;
+ }
+ break;
+ case IPPROTO_UDP:
+ if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
+ if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
+ sum = m->m_pkthdr.csum_data;
+ } else {
+ ip = mtod(m, struct ip *);
+ sum = in_pseudo(ip->ip_src.s_addr,
+ ip->ip_dst.s_addr, htonl((u_short)len +
+ m->m_pkthdr.csum_data + IPPROTO_UDP));
+ }
+ sum ^= 0xffff;
+ ++hw_assist;
+ }
+ break;
+ case IPPROTO_ICMP:
+#ifdef INET6
+ case IPPROTO_ICMPV6:
+#endif /* INET6 */
+ break;
+ default:
+ return (1);
+ }
+
+ if (!hw_assist) {
+ switch (af) {
+ case AF_INET:
+ if (p == IPPROTO_ICMP) {
+ if (m->m_len < off)
+ return (1);
+ m->m_data += off;
+ m->m_len -= off;
+ sum = in_cksum(m, len);
+ m->m_data -= off;
+ m->m_len += off;
+ } else {
+ if (m->m_len < sizeof(struct ip))
+ return (1);
+ sum = in4_cksum(m, p, off, len);
+ if (sum == 0) {
+ m->m_pkthdr.csum_flags |=
+ (CSUM_DATA_VALID |
+ CSUM_PSEUDO_HDR);
+ m->m_pkthdr.csum_data = 0xffff;
+ }
+ }
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (m->m_len < sizeof(struct ip6_hdr))
+ return (1);
+ sum = in6_cksum(m, p, off, len);
+ /*
+ * XXX
+ * IPv6 H/W cksum off-load not supported yet!
+ *
+ * if (sum == 0) {
+ * m->m_pkthdr.csum_flags |=
+ * (CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
+ * m->m_pkthdr.csum_data = 0xffff;
+ *}
+ */
+ break;
+#endif /* INET6 */
+ default:
+ return (1);
+ }
+ }
+ if (sum) {
+ switch (p) {
+ case IPPROTO_TCP:
+ tcpstat.tcps_rcvbadsum++;
+ break;
+ case IPPROTO_UDP:
+ udpstat.udps_badsum++;
+ break;
+ case IPPROTO_ICMP:
+ icmpstat.icps_checksum++;
+ break;
+#ifdef INET6
+ case IPPROTO_ICMPV6:
+ icmp6stat.icp6s_checksum++;
+ break;
+#endif /* INET6 */
+ }
+ return (1);
+ }
+ return (0);
+}
+#else
/*
* check protocol (tcp/udp/icmp/icmp6) checksum and set mbuf flag
* off is the offset where the protocol header starts
@@ -5139,8 +5505,7 @@ bad:
* returns 0 when the checksum is valid, otherwise returns 1.
*/
int
-pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
- sa_family_t af)
+pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af)
{
u_int16_t flag_ok, flag_bad;
u_int16_t sum;
@@ -5220,49 +5585,42 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
m->m_pkthdr.csum |= flag_ok;
return (0);
}
-
-static int
-pf_add_mbuf_tag(struct mbuf *m, u_int tag)
-{
- struct m_tag *mtag;
-
- if (m_tag_find(m, tag, NULL) != NULL)
- return (0);
- mtag = m_tag_get(tag, 0, M_NOWAIT);
- if (mtag == NULL)
- return (1);
- m_tag_prepend(m, mtag);
- return (0);
-}
+#endif
#ifdef INET
int
pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
{
- struct pfi_kif *kif;
- u_short action, reason = 0, log = 0;
- struct mbuf *m = *m0;
- struct ip *h;
- struct pf_rule *a = NULL, *r = &pf_default_rule, *tr, *nr;
- struct pf_state *s = NULL;
- struct pf_ruleset *ruleset = NULL;
- struct pf_pdesc pd;
- int off, dirndx, pqid = 0;
-
+ u_short action, reason = 0, log = 0;
+ struct mbuf *m = *m0;
+ struct ip *h = NULL; /* XXX: was uninitialized */
+ struct pf_rule *a = NULL, *r = &pf_default_rule, *tr;
+ struct pf_state *s = NULL;
+ struct pf_ruleset *ruleset = NULL;
+ struct pf_pdesc pd;
+ int off;
+ int pqid = 0;
+
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
if (!pf_status.running ||
- (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL))
- return (PF_PASS);
-
- kif = pfi_index2kif[ifp->if_index];
- if (kif == NULL)
- return (PF_DROP);
+ (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL)) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ return (PF_PASS);
+ }
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 501000)
+ M_ASSERTPKTHDR(m);
+#else
#ifdef DIAGNOSTIC
if ((m->m_flags & M_PKTHDR) == 0)
panic("non-M_PKTHDR is passed to pf_test");
#endif
+#endif
- memset(&pd, 0, sizeof(pd));
if (m->m_pkthdr.len < (int)sizeof(*h)) {
action = PF_DROP;
REASON_SET(&reason, PFRES_SHORT);
@@ -5271,7 +5629,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
}
/* We do IP header normalization and packet reassembly here */
- if (pf_normalize_ip(m0, dir, kif, &reason) != PF_PASS) {
+ if (pf_normalize_ip(m0, dir, ifp, &reason) != PF_PASS) {
action = PF_DROP;
goto done;
}
@@ -5286,9 +5644,9 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
goto done;
}
+ memset(&pd, 0, sizeof(pd));
pd.src = (struct pf_addr *)&h->ip_src;
pd.dst = (struct pf_addr *)&h->ip_dst;
- PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET);
pd.ip_sum = &h->ip_sum;
pd.proto = h->ip_p;
pd.af = AF_INET;
@@ -5297,7 +5655,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
/* handle fragments that didn't get reassembled by normalization */
if (h->ip_off & htons(IP_MF | IP_OFFMASK)) {
- action = pf_test_fragment(&r, dir, kif, m, h,
+ action = pf_test_fragment(&r, dir, ifp, m, h,
&pd, &a, &ruleset);
goto done;
}
@@ -5321,21 +5679,17 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
pd.p_len = pd.tot_len - off - (th.th_off << 2);
if ((th.th_flags & TH_ACK) && pd.p_len == 0)
pqid = 1;
- action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
+ action = pf_normalize_tcp(dir, ifp, m, 0, off, h, &pd);
if (action == PF_DROP)
- goto done;
- action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
+ break;
+ action = pf_test_state_tcp(&s, dir, ifp, m, 0, off, h, &pd,
&reason);
if (action == PF_PASS) {
-#if NPFSYNC
- pfsync_update_state(s);
-#endif
r = s->rule.ptr;
- a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
- action = pf_test_tcp(&r, &s, dir, kif,
- m, off, h, &pd, &a, &ruleset);
+ action = pf_test_tcp(&r, &s, dir, ifp,
+ m, 0, off, h, &pd, &a, &ruleset);
break;
}
@@ -5353,23 +5707,14 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
action = PF_DROP;
goto done;
}
- if (uh.uh_dport == 0 ||
- ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
- ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
- action = PF_DROP;
- goto done;
- }
- action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
+ action = pf_test_state_udp(&s, dir, ifp, m, 0, off, h, &pd);
if (action == PF_PASS) {
-#if NPFSYNC
- pfsync_update_state(s);
-#endif
r = s->rule.ptr;
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
- action = pf_test_udp(&r, &s, dir, kif,
- m, off, h, &pd, &a, &ruleset);
+ action = pf_test_udp(&r, &s, dir, ifp,
+ m, 0, off, h, &pd, &a, &ruleset);
break;
}
@@ -5387,36 +5732,55 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
action = PF_DROP;
goto done;
}
- action = pf_test_state_icmp(&s, dir, kif, m, off, h, &pd);
+ action = pf_test_state_icmp(&s, dir, ifp, m, 0, off, h, &pd);
if (action == PF_PASS) {
-#if NPFSYNC
- pfsync_update_state(s);
-#endif
r = s->rule.ptr;
+ r->packets++;
+ r->bytes += ntohs(h->ip_len);
a = s->anchor.ptr;
+ if (a != NULL) {
+ a->packets++;
+ a->bytes += ntohs(h->ip_len);
+ }
log = s->log;
} else if (s == NULL)
- action = pf_test_icmp(&r, &s, dir, kif,
- m, off, h, &pd, &a, &ruleset);
+ action = pf_test_icmp(&r, &s, dir, ifp,
+ m, 0, off, h, &pd, &a, &ruleset);
break;
}
default:
- action = pf_test_state_other(&s, dir, kif, &pd);
+ action = pf_test_state_other(&s, dir, ifp, &pd);
if (action == PF_PASS) {
-#if NPFSYNC
- pfsync_update_state(s);
-#endif
r = s->rule.ptr;
a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
- action = pf_test_other(&r, &s, dir, kif, m, off, h,
+ action = pf_test_other(&r, &s, dir, ifp, m, off, h,
&pd, &a, &ruleset);
break;
}
+ if (ifp == status_ifp) {
+ pf_status.bcounters[0][dir == PF_OUT] += pd.tot_len;
+ pf_status.pcounters[0][dir == PF_OUT][action != PF_PASS]++;
+ }
+
done:
+ tr = r;
+ if (r == &pf_default_rule && s != NULL && s->nat_rule.ptr != NULL)
+ tr = s->nat_rule.ptr;
+ if (tr->src.addr.type == PF_ADDR_TABLE)
+ pfr_update_stats(tr->src.addr.p.tbl,
+ (s == NULL || s->direction == dir) ? pd.src : pd.dst, pd.af,
+ pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
+ tr->src.not);
+ if (tr->dst.addr.type == PF_ADDR_TABLE)
+ pfr_update_stats(tr->dst.addr.p.tbl,
+ (s == NULL || s->direction == dir) ? pd.dst : pd.src, pd.af,
+ pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
+ tr->dst.not);
+
if (action == PF_PASS && h->ip_hl > 5 &&
!((s && s->allow_opts) || r->allow_opts)) {
action = PF_DROP;
@@ -5446,87 +5810,8 @@ done:
}
#endif
- /*
- * connections redirected to loopback should not match sockets
- * bound specifically to loopback due to security implications,
- * see tcp_input() and in_pcblookup_listen().
- */
- if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
- pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
- (s->nat_rule.ptr->action == PF_RDR ||
- s->nat_rule.ptr->action == PF_BINAT) &&
- (ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET &&
- pf_add_mbuf_tag(m, PACKET_TAG_PF_TRANSLATE_LOCALHOST)) {
- action = PF_DROP;
- REASON_SET(&reason, PFRES_MEMORY);
- }
-
if (log)
- PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, a, ruleset);
-
- kif->pfik_bytes[0][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
- kif->pfik_packets[0][dir == PF_OUT][action != PF_PASS]++;
-
- if (action == PF_PASS || r->action == PF_DROP) {
- r->packets++;
- r->bytes += pd.tot_len;
- if (a != NULL) {
- a->packets++;
- a->bytes += pd.tot_len;
- }
- if (s != NULL) {
- dirndx = (dir == s->direction) ? 0 : 1;
- s->packets[dirndx]++;
- s->bytes[dirndx] += pd.tot_len;
- if (s->nat_rule.ptr != NULL) {
- s->nat_rule.ptr->packets++;
- s->nat_rule.ptr->bytes += pd.tot_len;
- }
- if (s->src_node != NULL) {
- s->src_node->packets++;
- s->src_node->bytes += pd.tot_len;
- }
- if (s->nat_src_node != NULL) {
- s->nat_src_node->packets++;
- s->nat_src_node->bytes += pd.tot_len;
- }
- }
- tr = r;
- nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
- if (nr != NULL) {
- struct pf_addr *x;
- /*
- * XXX: we need to make sure that the addresses
- * passed to pfr_update_stats() are the same than
- * the addresses used during matching (pfr_match)
- */
- if (r == &pf_default_rule) {
- tr = nr;
- x = (s == NULL || s->direction == dir) ?
- &pd.baddr : &pd.naddr;
- } else
- x = (s == NULL || s->direction == dir) ?
- &pd.naddr : &pd.baddr;
- if (x == &pd.baddr || s == NULL) {
- /* we need to change the address */
- if (dir == PF_OUT)
- pd.src = x;
- else
- pd.dst = x;
- }
- }
- if (tr->src.addr.type == PF_ADDR_TABLE)
- pfr_update_stats(tr->src.addr.p.tbl, (s == NULL ||
- s->direction == dir) ? pd.src : pd.dst, pd.af,
- pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
- tr->src.not);
- if (tr->dst.addr.type == PF_ADDR_TABLE)
- pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL ||
- s->direction == dir) ? pd.dst : pd.src, pd.af,
- pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
- tr->dst.not);
- }
-
+ PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, a, ruleset);
if (action == PF_SYNPROXY_DROP) {
m_freem(*m0);
@@ -5536,6 +5821,10 @@ done:
/* pf_route can free the mbuf causing *m0 to become NULL */
pf_route(m0, r, dir, ifp, s);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+
return (action);
}
#endif /* INET */
@@ -5544,30 +5833,36 @@ done:
int
pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
{
- struct pfi_kif *kif;
- u_short action, reason = 0, log = 0;
- struct mbuf *m = *m0;
- struct ip6_hdr *h;
- struct pf_rule *a = NULL, *r = &pf_default_rule, *tr, *nr;
- struct pf_state *s = NULL;
- struct pf_ruleset *ruleset = NULL;
- struct pf_pdesc pd;
- int off, terminal = 0, dirndx;
+ u_short action, reason = 0, log = 0;
+ struct mbuf *m = *m0;
+ struct ip6_hdr *h = NULL; /* make the compiler happy */
+ struct pf_rule *a = NULL, *r = &pf_default_rule, *tr;
+ struct pf_state *s = NULL;
+ struct pf_ruleset *ruleset = NULL;
+ struct pf_pdesc pd;
+ int off, terminal = 0;
+
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
if (!pf_status.running ||
- (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL))
+ (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL)) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
return (PF_PASS);
+ }
- kif = pfi_index2kif[ifp->if_index];
- if (kif == NULL)
- return (PF_DROP);
-
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 501000)
+ M_ASSERTPKTHDR(m);
+#else
#ifdef DIAGNOSTIC
if ((m->m_flags & M_PKTHDR) == 0)
panic("non-M_PKTHDR is passed to pf_test");
#endif
+#endif
- memset(&pd, 0, sizeof(pd));
if (m->m_pkthdr.len < (int)sizeof(*h)) {
action = PF_DROP;
REASON_SET(&reason, PFRES_SHORT);
@@ -5576,16 +5871,16 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
}
/* We do IP header normalization and packet reassembly here */
- if (pf_normalize_ip6(m0, dir, kif, &reason) != PF_PASS) {
+ if (pf_normalize_ip6(m0, dir, ifp, &reason) != PF_PASS) {
action = PF_DROP;
goto done;
}
m = *m0;
h = mtod(m, struct ip6_hdr *);
+ memset(&pd, 0, sizeof(pd));
pd.src = (struct pf_addr *)&h->ip6_src;
pd.dst = (struct pf_addr *)&h->ip6_dst;
- PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET6);
pd.ip_sum = NULL;
pd.af = AF_INET6;
pd.tos = 0;
@@ -5596,7 +5891,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
do {
switch (pd.proto) {
case IPPROTO_FRAGMENT:
- action = pf_test_fragment(&r, dir, kif, m, h,
+ action = pf_test_fragment(&r, dir, ifp, m, h,
&pd, &a, &ruleset);
if (action == PF_DROP)
REASON_SET(&reason, PFRES_FRAG);
@@ -5648,21 +5943,17 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
goto done;
}
pd.p_len = pd.tot_len - off - (th.th_off << 2);
- action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
+ action = pf_normalize_tcp(dir, ifp, m, 0, off, h, &pd);
if (action == PF_DROP)
- goto done;
- action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
+ break;
+ action = pf_test_state_tcp(&s, dir, ifp, m, 0, off, h, &pd,
&reason);
if (action == PF_PASS) {
-#if NPFSYNC
- pfsync_update_state(s);
-#endif
r = s->rule.ptr;
- a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
- action = pf_test_tcp(&r, &s, dir, kif,
- m, off, h, &pd, &a, &ruleset);
+ action = pf_test_tcp(&r, &s, dir, ifp,
+ m, 0, off, h, &pd, &a, &ruleset);
break;
}
@@ -5680,23 +5971,13 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
action = PF_DROP;
goto done;
}
- if (uh.uh_dport == 0 ||
- ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
- ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
- action = PF_DROP;
- goto done;
- }
- action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
+ action = pf_test_state_udp(&s, dir, ifp, m, 0, off, h, &pd);
if (action == PF_PASS) {
-#if NPFSYNC
- pfsync_update_state(s);
-#endif
r = s->rule.ptr;
- a = s->anchor.ptr;
log = s->log;
} else if (s == NULL)
- action = pf_test_udp(&r, &s, dir, kif,
- m, off, h, &pd, &a, &ruleset);
+ action = pf_test_udp(&r, &s, dir, ifp,
+ m, 0, off, h, &pd, &a, &ruleset);
break;
}
@@ -5714,34 +5995,45 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0)
action = PF_DROP;
goto done;
}
- action = pf_test_state_icmp(&s, dir, kif,
- m, off, h, &pd);
+ action = pf_test_state_icmp(&s, dir, ifp,
+ m, 0, off, h, &pd);
if (action == PF_PASS) {
-#if NPFSYNC
- pfsync_update_state(s);
-#endif
r = s->rule.ptr;
- a = s->anchor.ptr;
+ r->packets++;
+ r->bytes += h->ip6_plen;
log = s->log;
} else if (s == NULL)
- action = pf_test_icmp(&r, &s, dir, kif,
- m, off, h, &pd, &a, &ruleset);
+ action = pf_test_icmp(&r, &s, dir, ifp,
+ m, 0, off, h, &pd, &a, &ruleset);
break;
}
default:
- action = pf_test_state_other(&s, dir, kif, &pd);
- if (action == PF_PASS) {
- r = s->rule.ptr;
- a = s->anchor.ptr;
- log = s->log;
- } else if (s == NULL)
- action = pf_test_other(&r, &s, dir, kif, m, off, h,
- &pd, &a, &ruleset);
+ action = pf_test_other(&r, &s, dir, ifp, m, off, h,
+ &pd, &a, &ruleset);
break;
}
+ if (ifp == status_ifp) {
+ pf_status.bcounters[1][dir == PF_OUT] += pd.tot_len;
+ pf_status.pcounters[1][dir == PF_OUT][action != PF_PASS]++;
+ }
+
done:
+ tr = r;
+ if (r == &pf_default_rule && s != NULL && s->nat_rule.ptr != NULL)
+ tr = s->nat_rule.ptr;
+ if (tr->src.addr.type == PF_ADDR_TABLE)
+ pfr_update_stats(tr->src.addr.p.tbl,
+ (s == NULL || s->direction == dir) ? pd.src : pd.dst, pd.af,
+ pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
+ tr->src.not);
+ if (tr->dst.addr.type == PF_ADDR_TABLE)
+ pfr_update_stats(tr->dst.addr.p.tbl,
+ (s == NULL || s->direction == dir) ? pd.dst : pd.src, pd.af,
+ pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
+ tr->dst.not);
+
/* XXX handle IPv6 options, if not allowed. not implemented. */
#ifdef ALTQ
@@ -5764,82 +6056,8 @@ done:
}
#endif
- if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
- pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
- (s->nat_rule.ptr->action == PF_RDR ||
- s->nat_rule.ptr->action == PF_BINAT) &&
- IN6_IS_ADDR_LOOPBACK(&pd.dst->v6) &&
- pf_add_mbuf_tag(m, PACKET_TAG_PF_TRANSLATE_LOCALHOST)) {
- action = PF_DROP;
- REASON_SET(&reason, PFRES_MEMORY);
- }
-
if (log)
- PFLOG_PACKET(kif, h, m, AF_INET6, dir, reason, r, a, ruleset);
-
- kif->pfik_bytes[1][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
- kif->pfik_packets[1][dir == PF_OUT][action != PF_PASS]++;
-
- if (action == PF_PASS || r->action == PF_DROP) {
- r->packets++;
- r->bytes += pd.tot_len;
- if (a != NULL) {
- a->packets++;
- a->bytes += pd.tot_len;
- }
- if (s != NULL) {
- dirndx = (dir == s->direction) ? 0 : 1;
- s->packets[dirndx]++;
- s->bytes[dirndx] += pd.tot_len;
- if (s->nat_rule.ptr != NULL) {
- s->nat_rule.ptr->packets++;
- s->nat_rule.ptr->bytes += pd.tot_len;
- }
- if (s->src_node != NULL) {
- s->src_node->packets++;
- s->src_node->bytes += pd.tot_len;
- }
- if (s->nat_src_node != NULL) {
- s->nat_src_node->packets++;
- s->nat_src_node->bytes += pd.tot_len;
- }
- }
- tr = r;
- nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
- if (nr != NULL) {
- struct pf_addr *x;
- /*
- * XXX: we need to make sure that the addresses
- * passed to pfr_update_stats() are the same than
- * the addresses used during matching (pfr_match)
- */
- if (r == &pf_default_rule) {
- tr = nr;
- x = (s == NULL || s->direction == dir) ?
- &pd.baddr : &pd.naddr;
- } else {
- x = (s == NULL || s->direction == dir) ?
- &pd.naddr : &pd.baddr;
- }
- if (x == &pd.baddr || s == NULL) {
- if (dir == PF_OUT)
- pd.src = x;
- else
- pd.dst = x;
- }
- }
- if (tr->src.addr.type == PF_ADDR_TABLE)
- pfr_update_stats(tr->src.addr.p.tbl, (s == NULL ||
- s->direction == dir) ? pd.src : pd.dst, pd.af,
- pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
- tr->src.not);
- if (tr->dst.addr.type == PF_ADDR_TABLE)
- pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL ||
- s->direction == dir) ? pd.dst : pd.src, pd.af,
- pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
- tr->dst.not);
- }
-
+ PFLOG_PACKET(ifp, h, m, AF_INET6, dir, reason, r, a, ruleset);
if (action == PF_SYNPROXY_DROP) {
m_freem(*m0);
@@ -5849,6 +6067,9 @@ done:
/* pf_route6 can free the mbuf causing *m0 to become NULL */
pf_route6(m0, r, dir, ifp, s);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
return (action);
}
#endif /* INET6 */
diff --git a/sys/contrib/pf/net/pf_ioctl.c b/sys/contrib/pf/net/pf_ioctl.c
index dd25ce2..3053de3 100644
--- a/sys/contrib/pf/net/pf_ioctl.c
+++ b/sys/contrib/pf/net/pf_ioctl.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: pf_ioctl.c,v 1.112 2004/03/22 04:54:18 mcbride Exp $ */
+/* $FreeBSD$ */
+/* $OpenBSD: pf_ioctl.c,v 1.81.2.2 2004/04/30 23:28:58 brad Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
- * Copyright (c) 2002,2003 Henning Brauer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,7 +35,10 @@
*
*/
-#include "pfsync.h"
+#ifdef __FreeBSD__
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#endif
#include <sys/param.h>
#include <sys/systm.h>
@@ -46,9 +49,14 @@
#include <sys/socketvar.h>
#include <sys/kernel.h>
#include <sys/time.h>
+#include <sys/malloc.h>
+#ifdef __FreeBSD__
+#include <sys/module.h>
+#include <sys/conf.h>
+#else
#include <sys/timeout.h>
#include <sys/pool.h>
-#include <sys/malloc.h>
+#endif
#include <net/if.h>
#include <net/if_types.h>
@@ -61,67 +69,305 @@
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
-#include <dev/rndvar.h>
#include <net/pfvar.h>
-#if NPFSYNC > 0
-#include <net/if_pfsync.h>
-#endif /* NPFSYNC > 0 */
-
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet/in_pcb.h>
+#if defined(__FreeBSD__) && (__FreeBSD_version < 501108)
+#include <netinet6/ip6protosw.h>
+#endif
#endif /* INET6 */
#ifdef ALTQ
#include <altq/altq.h>
#endif
+#ifdef __FreeBSD__
+#if (__FreeBSD_version >= 500112)
+#include <sys/limits.h>
+#else
+#include <machine/limits.h>
+#endif
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#if __FreeBSD_version < 501108
+#include <sys/protosw.h>
+#endif
+#include <net/pfil.h>
+#endif /* __FreeBSD__ */
+
+#ifdef __FreeBSD__
+void init_zone_var(void);
+void cleanup_pf_zone(void);
+int pfattach(void);
+#else
void pfattach(int);
-int pfopen(dev_t, int, int, struct proc *);
-int pfclose(dev_t, int, int, struct proc *);
+int pfopen(struct cdev *, int, int, struct proc *);
+int pfclose(struct cdev *, int, int, struct proc *);
+#endif
struct pf_pool *pf_get_pool(char *, char *, u_int32_t,
- u_int8_t, u_int8_t, u_int8_t, u_int8_t, u_int8_t);
+ u_int8_t, u_int32_t, u_int8_t, u_int8_t, u_int8_t);
int pf_get_ruleset_number(u_int8_t);
void pf_init_ruleset(struct pf_ruleset *);
void pf_mv_pool(struct pf_palist *, struct pf_palist *);
void pf_empty_pool(struct pf_palist *);
-int pfioctl(dev_t, u_long, caddr_t, int, struct proc *);
-#ifdef ALTQ
-int pf_begin_altq(u_int32_t *);
-int pf_rollback_altq(u_int32_t);
-int pf_commit_altq(u_int32_t);
-#endif /* ALTQ */
-int pf_begin_rules(u_int32_t *, int, char *, char *);
-int pf_rollback_rules(u_int32_t, int, char *, char *);
-int pf_commit_rules(u_int32_t, int, char *, char *);
+#ifdef __FreeBSD__
+int pfioctl(struct cdev *, u_long, caddr_t, int, struct thread *);
+#else
+int pfioctl(struct cdev *, u_long, caddr_t, int, struct proc *);
+#endif
+#ifdef __FreeBSD__
+extern struct callout pf_expire_to;
+#if __FreeBSD_version < 501108
+extern struct protosw inetsw[];
+#endif
+#else
extern struct timeout pf_expire_to;
+#endif
struct pf_rule pf_default_rule;
+#ifdef ALTQ
+static int pfaltq_running;
+#endif
#define TAGID_MAX 50000
-TAILQ_HEAD(pf_tags, pf_tagname) pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags),
- pf_qids = TAILQ_HEAD_INITIALIZER(pf_qids);
+TAILQ_HEAD(pf_tags, pf_tagname) pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags);
+
+#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
-#if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE)
-#error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
+
+#ifdef __FreeBSD__
+static struct cdev *pf_dev;
+
+/*
+ * XXX - These are new and need to be checked when moveing to a new version
+ */
+static int pf_beginrules(void *addr);
+static int pf_commitrules(void *addr);
+#ifdef ALTQ
+static int pf_beginaltqs(void *addr);
+static int pf_commitaltqs(void *addr);
+static int pf_stopaltq(void);
+#endif
+static void pf_clearstates(void);
+static int pf_clear_tables(void *addr);
+/*
+ * XXX - These are new and need to be checked when moveing to a new version
+ */
+
+#if (__FreeBSD_version < 501108)
+static int pf_check_in(void *ip, int hlen, struct ifnet *ifp, int dir,
+ struct mbuf **m);
+static int pf_check_out(void *ip, int hlen, struct ifnet *ifp, int dir,
+ struct mbuf **m);
+#ifdef INET6
+static int pf_check6_in(void *ip, int hlen, struct ifnet *ifp, int dir,
+ struct mbuf **m);
+static int pf_check6_out(void *ip, int hlen, struct ifnet *ifp, int dir,
+ struct mbuf **m);
+#endif
+#else /* (__FreeBSD_version >= 501108) */
+static int pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp,
+ int dir);
+static int pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp,
+ int dir);
+#ifdef INET6
+static int pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp,
+ int dir);
+static int pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp,
+ int dir);
+#endif
+#endif /* (__FreeBSD_version >= 501108) */
+static int hook_pf(void);
+static int dehook_pf(void);
+static int shutdown_pf(void);
+static int pf_load(void);
+static int pf_unload(void);
+
+
+
+static struct cdevsw pf_cdevsw = {
+#if (__FreeBSD_version < 500105)
+ /* open */ noopen,
+ /* close */ noclose,
+ /* read */ noread,
+ /* write */ nowrite,
+ /* ioctl */ pfioctl,
+ /* poll */ nopoll,
+ /* mmap */ nommap,
+ /* strategy */ nostrategy,
+ /* name */ PF_NAME,
+ /* maj */ PF_CDEV_MAJOR,
+ /* dump */ nodump,
+ /* psize */ nopsize,
+ /* flags */ 0,
+ /* kqfilter */ nokqfilter,
+#elif (__FreeBSD_version < 501110)
+ .d_open = noopen,
+ .d_close = noclose,
+ .d_read = noread,
+ .d_write = nowrite,
+ .d_ioctl = pfioctl,
+ .d_poll = nopoll,
+ .d_mmap = nommap,
+ .d_strategy = nostrategy,
+ .d_name = PF_NAME,
+ .d_maj = MAJOR_AUTO, /* PF_CDEV_MAJOR */
+ .d_dump = nodump,
+ .d_flags = 0,
+ .d_kqfilter = nokqfilter,
+#else
+ .d_ioctl = pfioctl,
+ .d_name = PF_NAME,
+ .d_version = D_VERSION,
#endif
-static u_int16_t tagname2tag(struct pf_tags *, char *);
-static void tag2tagname(struct pf_tags *, u_int16_t, char *);
-static void tag_unref(struct pf_tags *, u_int16_t);
+};
-#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
+static volatile int pf_pfil_hooked = 0;
+struct mtx pf_task_mtx;
+
+void
+init_pf_mutex(void)
+{
+ mtx_init(&pf_task_mtx, "pf task mtx", NULL, MTX_DEF);
+}
+
+void
+destroy_pf_mutex(void)
+{
+ mtx_destroy(&pf_task_mtx);
+}
+
+void
+init_zone_var(void)
+{
+ pf_tree_pl = pf_rule_pl = pf_addr_pl = NULL;
+ pf_state_pl = pf_altq_pl = pf_pooladdr_pl = NULL;
+ pf_frent_pl = pf_frag_pl = pf_cache_pl = pf_cent_pl = NULL;
+ pf_state_scrub_pl = NULL;
+ pfr_ktable_pl = pfr_kentry_pl = NULL;
+}
+
+void
+cleanup_pf_zone(void)
+{
+ UMA_DESTROY(pf_tree_pl);
+ UMA_DESTROY(pf_rule_pl);
+ UMA_DESTROY(pf_addr_pl);
+ UMA_DESTROY(pf_state_pl);
+ UMA_DESTROY(pf_altq_pl);
+ UMA_DESTROY(pf_pooladdr_pl);
+ UMA_DESTROY(pf_frent_pl);
+ UMA_DESTROY(pf_frag_pl);
+ UMA_DESTROY(pf_cache_pl);
+ UMA_DESTROY(pf_cent_pl);
+ UMA_DESTROY(pfr_ktable_pl);
+ UMA_DESTROY(pfr_kentry_pl);
+ UMA_DESTROY(pf_state_scrub_pl);
+}
+
+int
+pfattach(void)
+{
+ u_int32_t *my_timeout = pf_default_rule.timeout;
+ int error = 1;
+
+ do {
+ UMA_CREATE(pf_tree_pl, struct pf_tree_node, "pftrpl");
+ UMA_CREATE(pf_rule_pl, struct pf_rule, "pfrulepl");
+ UMA_CREATE(pf_addr_pl, struct pf_addr_dyn, "pfaddrpl");
+ UMA_CREATE(pf_state_pl, struct pf_state, "pfstatepl");
+ UMA_CREATE(pf_altq_pl, struct pf_altq, "pfaltqpl");
+ UMA_CREATE(pf_pooladdr_pl, struct pf_pooladdr, "pfpooladdrpl");
+ UMA_CREATE(pfr_ktable_pl, struct pfr_ktable, "pfrktable");
+ UMA_CREATE(pfr_kentry_pl, struct pfr_kentry, "pfrkentry");
+ UMA_CREATE(pf_frent_pl, struct pf_frent, "pffrent");
+ UMA_CREATE(pf_frag_pl, struct pf_fragment, "pffrag");
+ UMA_CREATE(pf_cache_pl, struct pf_fragment, "pffrcache");
+ UMA_CREATE(pf_cent_pl, struct pf_frcache, "pffrcent");
+ UMA_CREATE(pf_state_scrub_pl, struct pf_state_scrub,
+ "pfstatescrub");
+ error = 0;
+ } while(0);
+ if (error) {
+ cleanup_pf_zone();
+ return (error);
+ }
+ pfr_initialize();
+ if ( (error = pf_osfp_initialize()) ) {
+ cleanup_pf_zone();
+ pf_osfp_cleanup();
+ return (error);
+ }
+
+ pf_pool_limits[PF_LIMIT_STATES].pp = pf_state_pl;
+ pf_pool_limits[PF_LIMIT_STATES].limit = PFSTATE_HIWAT;
+ pf_pool_limits[PF_LIMIT_FRAGS].pp = pf_frent_pl;
+ pf_pool_limits[PF_LIMIT_FRAGS].limit = PFFRAG_FRENT_HIWAT;
+ uma_zone_set_max(pf_pool_limits[PF_LIMIT_STATES].pp,
+ pf_pool_limits[PF_LIMIT_STATES].limit);
+
+ RB_INIT(&tree_lan_ext);
+ RB_INIT(&tree_ext_gwy);
+ TAILQ_INIT(&pf_anchors);
+ pf_init_ruleset(&pf_main_ruleset);
+ TAILQ_INIT(&pf_altqs[0]);
+ TAILQ_INIT(&pf_altqs[1]);
+ TAILQ_INIT(&pf_pabuf);
+ pf_altqs_active = &pf_altqs[0];
+ pf_altqs_inactive = &pf_altqs[1];
+
+ /* default rule should never be garbage collected */
+ pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
+ pf_default_rule.action = PF_PASS;
+ pf_default_rule.nr = -1;
+
+ /* initialize default timeouts */
+ my_timeout[PFTM_TCP_FIRST_PACKET] = 120; /* First TCP packet */
+ my_timeout[PFTM_TCP_OPENING] = 30; /* No response yet */
+ my_timeout[PFTM_TCP_ESTABLISHED] = 24*60*60; /* Established */
+ my_timeout[PFTM_TCP_CLOSING] = 15 * 60; /* Half closed */
+ my_timeout[PFTM_TCP_FIN_WAIT] = 45; /* Got both FINs */
+ my_timeout[PFTM_TCP_CLOSED] = 90; /* Got a RST */
+ my_timeout[PFTM_UDP_FIRST_PACKET] = 60; /* First UDP packet */
+ my_timeout[PFTM_UDP_SINGLE] = 30; /* Unidirectional */
+ my_timeout[PFTM_UDP_MULTIPLE] = 60; /* Bidirectional */
+ my_timeout[PFTM_ICMP_FIRST_PACKET] = 20; /* First ICMP packet */
+ my_timeout[PFTM_ICMP_ERROR_REPLY] = 10; /* Got error response */
+ my_timeout[PFTM_OTHER_FIRST_PACKET] = 60; /* First packet */
+ my_timeout[PFTM_OTHER_SINGLE] = 30; /* Unidirectional */
+ my_timeout[PFTM_OTHER_MULTIPLE] = 60; /* Bidirectional */
+ my_timeout[PFTM_FRAG] = 30; /* Fragment expire */
+ my_timeout[PFTM_INTERVAL] = 10; /* Expire interval */
+
+ /*
+ * XXX
+ * The 2nd arg. 0 to callout_init(9) shoule be set to CALLOUT_MPSAFE
+ * if Gaint lock is removed from the network stack.
+ */
+ callout_init(&pf_expire_to, 0);
+ callout_reset(&pf_expire_to, my_timeout[PFTM_INTERVAL] * hz,
+ pf_purge_timeout, &pf_expire_to);
+ pf_normalize_init();
+ pf_status.debug = PF_DEBUG_URGENT;
+ pf_pfil_hooked = 0;
+ return (error);
+}
+#else /* !__FreeBSD__ */
void
pfattach(int num)
{
u_int32_t *timeout = pf_default_rule.timeout;
+ pool_init(&pf_tree_pl, sizeof(struct pf_tree_node), 0, 0, 0, "pftrpl",
+ NULL);
pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl",
&pool_allocator_nointr);
- pool_init(&pf_src_tree_pl, sizeof(struct pf_src_node), 0, 0, 0,
- "pfsrctrpl", NULL);
+ pool_init(&pf_addr_pl, sizeof(struct pf_addr_dyn), 0, 0, 0, "pfaddrpl",
+ &pool_allocator_nointr);
pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl",
NULL);
pool_init(&pf_altq_pl, sizeof(struct pf_altq), 0, 0, 0, "pfaltqpl",
@@ -129,13 +375,13 @@ pfattach(int num)
pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0,
"pfpooladdrpl", NULL);
pfr_initialize();
- pfi_initialize();
pf_osfp_initialize();
- pool_sethardlimit(pf_pool_limits[PF_LIMIT_STATES].pp,
- pf_pool_limits[PF_LIMIT_STATES].limit, NULL, 0);
+ pool_sethardlimit(&pf_state_pl, pf_pool_limits[PF_LIMIT_STATES].limit,
+ NULL, 0);
- RB_INIT(&tree_src_tracking);
+ RB_INIT(&tree_lan_ext);
+ RB_INIT(&tree_ext_gwy);
TAILQ_INIT(&pf_anchors);
pf_init_ruleset(&pf_main_ruleset);
TAILQ_INIT(&pf_altqs[0]);
@@ -143,7 +389,6 @@ pfattach(int num)
TAILQ_INIT(&pf_pabuf);
pf_altqs_active = &pf_altqs[0];
pf_altqs_inactive = &pf_altqs[1];
- TAILQ_INIT(&state_updates);
/* default rule should never be garbage collected */
pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
@@ -152,7 +397,7 @@ pfattach(int num)
/* initialize default timeouts */
timeout[PFTM_TCP_FIRST_PACKET] = 120; /* First TCP packet */
- timeout[PFTM_TCP_OPENING] = 30; /* No response yet */
+ timeout[PFTM_TCP_OPENING] = 30; /* No response yet */
timeout[PFTM_TCP_ESTABLISHED] = 24*60*60; /* Established */
timeout[PFTM_TCP_CLOSING] = 15 * 60; /* Half closed */
timeout[PFTM_TCP_FIN_WAIT] = 45; /* Got both FINs */
@@ -167,21 +412,16 @@ pfattach(int num)
timeout[PFTM_OTHER_MULTIPLE] = 60; /* Bidirectional */
timeout[PFTM_FRAG] = 30; /* Fragment expire */
timeout[PFTM_INTERVAL] = 10; /* Expire interval */
- timeout[PFTM_SRC_NODE] = 0; /* Source tracking */
timeout_set(&pf_expire_to, pf_purge_timeout, &pf_expire_to);
timeout_add(&pf_expire_to, timeout[PFTM_INTERVAL] * hz);
pf_normalize_init();
- bzero(&pf_status, sizeof(pf_status));
pf_status.debug = PF_DEBUG_URGENT;
-
- /* XXX do our best to avoid a conflict */
- pf_status.hostid = arc4random();
}
int
-pfopen(dev_t dev, int flags, int fmt, struct proc *p)
+pfopen(struct cdev *dev, int flags, int fmt, struct proc *p)
{
if (minor(dev) >= 1)
return (ENXIO);
@@ -189,16 +429,17 @@ pfopen(dev_t dev, int flags, int fmt, struct proc *p)
}
int
-pfclose(dev_t dev, int flags, int fmt, struct proc *p)
+pfclose(struct cdev *dev, int flags, int fmt, struct proc *p)
{
if (minor(dev) >= 1)
return (ENXIO);
return (0);
}
+#endif /* __FreeBSD__ */
struct pf_pool *
pf_get_pool(char *anchorname, char *rulesetname, u_int32_t ticket,
- u_int8_t rule_action, u_int8_t rule_number, u_int8_t r_last,
+ u_int8_t rule_action, u_int32_t rule_number, u_int8_t r_last,
u_int8_t active, u_int8_t check_ticket)
{
struct pf_ruleset *ruleset;
@@ -323,8 +564,7 @@ pf_find_ruleset(char *anchorname, char *rulesetname)
}
struct pf_ruleset *
-pf_find_or_create_ruleset(char anchorname[PF_ANCHOR_NAME_SIZE],
- char rulesetname[PF_RULESET_NAME_SIZE])
+pf_find_or_create_ruleset(char *anchorname, char *rulesetname)
{
struct pf_anchor *anchor, *a;
struct pf_ruleset *ruleset, *r;
@@ -383,8 +623,7 @@ pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
return;
for (i = 0; i < PF_RULESET_MAX; ++i)
if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) ||
- !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) ||
- ruleset->rules[i].inactive.open)
+ !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr))
return;
anchor = ruleset->anchor;
@@ -415,9 +654,8 @@ pf_empty_pool(struct pf_palist *poola)
struct pf_pooladdr *empty_pool_pa;
while ((empty_pool_pa = TAILQ_FIRST(poola)) != NULL) {
- pfi_dynaddr_remove(&empty_pool_pa->addr);
+ pf_dynaddr_remove(&empty_pool_pa->addr);
pf_tbladdr_remove(&empty_pool_pa->addr);
- pfi_detach_rule(empty_pool_pa->kif);
TAILQ_REMOVE(poola, empty_pool_pa, entries);
pool_put(&pf_pooladdr_pl, empty_pool_pa);
}
@@ -440,35 +678,27 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
rule->entries.tqe_prev = NULL;
rule->nr = -1;
}
-
- if (rule->states > 0 || rule->src_nodes > 0 ||
- rule->entries.tqe_prev != NULL)
+ if (rule->states > 0 || rule->entries.tqe_prev != NULL)
return;
pf_tag_unref(rule->tag);
pf_tag_unref(rule->match_tag);
-#ifdef ALTQ
- if (rule->pqid != rule->qid)
- pf_qid_unref(rule->pqid);
- pf_qid_unref(rule->qid);
-#endif
- pfi_dynaddr_remove(&rule->src.addr);
- pfi_dynaddr_remove(&rule->dst.addr);
+ pf_dynaddr_remove(&rule->src.addr);
+ pf_dynaddr_remove(&rule->dst.addr);
if (rulequeue == NULL) {
pf_tbladdr_remove(&rule->src.addr);
pf_tbladdr_remove(&rule->dst.addr);
}
- pfi_detach_rule(rule->kif);
pf_empty_pool(&rule->rpool.list);
pool_put(&pf_rule_pl, rule);
}
-static u_int16_t
-tagname2tag(struct pf_tags *head, char *tagname)
+u_int16_t
+pf_tagname2tag(char *tagname)
{
struct pf_tagname *tag, *p = NULL;
u_int16_t new_tagid = 1;
- TAILQ_FOREACH(tag, head, entries)
+ TAILQ_FOREACH(tag, &pf_tags, entries)
if (strcmp(tagname, tag->name) == 0) {
tag->ref++;
return (tag->tag);
@@ -481,8 +711,8 @@ tagname2tag(struct pf_tags *head, char *tagname)
*/
/* new entry */
- if (!TAILQ_EMPTY(head))
- for (p = TAILQ_FIRST(head); p != NULL &&
+ if (!TAILQ_EMPTY(&pf_tags))
+ for (p = TAILQ_FIRST(&pf_tags); p != NULL &&
p->tag == new_tagid; p = TAILQ_NEXT(p, entries))
new_tagid = p->tag + 1;
@@ -502,36 +732,36 @@ tagname2tag(struct pf_tags *head, char *tagname)
if (p != NULL) /* insert new entry before p */
TAILQ_INSERT_BEFORE(p, tag, entries);
else /* either list empty or no free slot in between */
- TAILQ_INSERT_TAIL(head, tag, entries);
+ TAILQ_INSERT_TAIL(&pf_tags, tag, entries);
return (tag->tag);
}
-static void
-tag2tagname(struct pf_tags *head, u_int16_t tagid, char *p)
+void
+pf_tag2tagname(u_int16_t tagid, char *p)
{
struct pf_tagname *tag;
- TAILQ_FOREACH(tag, head, entries)
+ TAILQ_FOREACH(tag, &pf_tags, entries)
if (tag->tag == tagid) {
strlcpy(p, tag->name, PF_TAG_NAME_SIZE);
return;
}
}
-static void
-tag_unref(struct pf_tags *head, u_int16_t tag)
+void
+pf_tag_unref(u_int16_t tag)
{
struct pf_tagname *p, *next;
if (tag == 0)
return;
- for (p = TAILQ_FIRST(head); p != NULL; p = next) {
+ for (p = TAILQ_FIRST(&pf_tags); p != NULL; p = next) {
next = TAILQ_NEXT(p, entries);
if (tag == p->tag) {
if (--p->ref == 0) {
- TAILQ_REMOVE(head, p, entries);
+ TAILQ_REMOVE(&pf_tags, p, entries);
free(p, M_TEMP);
}
break;
@@ -539,212 +769,13 @@ tag_unref(struct pf_tags *head, u_int16_t tag)
}
}
-u_int16_t
-pf_tagname2tag(char *tagname)
-{
- return (tagname2tag(&pf_tags, tagname));
-}
-
-void
-pf_tag2tagname(u_int16_t tagid, char *p)
-{
- return (tag2tagname(&pf_tags, tagid, p));
-}
-
-void
-pf_tag_unref(u_int16_t tag)
-{
- return (tag_unref(&pf_tags, tag));
-}
-
-#ifdef ALTQ
-u_int32_t
-pf_qname2qid(char *qname)
-{
- return ((u_int32_t)tagname2tag(&pf_qids, qname));
-}
-
-void
-pf_qid2qname(u_int32_t qid, char *p)
-{
- return (tag2tagname(&pf_qids, (u_int16_t)qid, p));
-}
-
-void
-pf_qid_unref(u_int32_t qid)
-{
- return (tag_unref(&pf_qids, (u_int16_t)qid));
-}
-
-int
-pf_begin_altq(u_int32_t *ticket)
-{
- struct pf_altq *altq;
- int error = 0;
-
- /* Purge the old altq list */
- while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
- TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
- if (altq->qname[0] == 0) {
- /* detach and destroy the discipline */
- error = altq_remove(altq);
- } else
- pf_qid_unref(altq->qid);
- pool_put(&pf_altq_pl, altq);
- }
- if (error)
- return (error);
- *ticket = ++ticket_altqs_inactive;
- altqs_inactive_open = 1;
- return (0);
-}
-
-int
-pf_rollback_altq(u_int32_t ticket)
-{
- struct pf_altq *altq;
- int error = 0;
-
- if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
- return (0);
- /* Purge the old altq list */
- while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
- TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
- if (altq->qname[0] == 0) {
- /* detach and destroy the discipline */
- error = altq_remove(altq);
- } else
- pf_qid_unref(altq->qid);
- pool_put(&pf_altq_pl, altq);
- }
- altqs_inactive_open = 0;
- return (error);
-}
-
-int
-pf_commit_altq(u_int32_t ticket)
-{
- struct pf_altqqueue *old_altqs;
- struct pf_altq *altq;
- int s, err, error = 0;
-
- if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
- return (EBUSY);
-
- /* swap altqs, keep the old. */
- s = splsoftnet();
- old_altqs = pf_altqs_active;
- pf_altqs_active = pf_altqs_inactive;
- pf_altqs_inactive = old_altqs;
- ticket_altqs_active = ticket_altqs_inactive;
-
- /* Attach new disciplines */
- TAILQ_FOREACH(altq, pf_altqs_active, entries) {
- if (altq->qname[0] == 0) {
- /* attach the discipline */
- error = altq_pfattach(altq);
- if (error) {
- splx(s);
- return (error);
- }
- }
- }
-
- /* Purge the old altq list */
- while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
- TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
- if (altq->qname[0] == 0) {
- /* detach and destroy the discipline */
- err = altq_pfdetach(altq);
- if (err != 0 && error == 0)
- error = err;
- err = altq_remove(altq);
- if (err != 0 && error == 0)
- error = err;
- } else
- pf_qid_unref(altq->qid);
- pool_put(&pf_altq_pl, altq);
- }
- splx(s);
-
- altqs_inactive_open = 0;
- return (error);
-}
-#endif /* ALTQ */
-
-int
-pf_begin_rules(u_int32_t *ticket, int rs_num, char *anchor, char *ruleset)
-{
- struct pf_ruleset *rs;
- struct pf_rule *rule;
-
- if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
- return (EINVAL);
- rs = pf_find_or_create_ruleset(anchor, ruleset);
- if (rs == NULL)
- return (EINVAL);
- while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL)
- pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
- *ticket = ++rs->rules[rs_num].inactive.ticket;
- rs->rules[rs_num].inactive.open = 1;
- return (0);
-}
-
-int
-pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor, char *ruleset)
-{
- struct pf_ruleset *rs;
- struct pf_rule *rule;
-
- if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
- return (EINVAL);
- rs = pf_find_ruleset(anchor, ruleset);
- if (rs == NULL || !rs->rules[rs_num].inactive.open ||
- rs->rules[rs_num].inactive.ticket != ticket)
- return (0);
- while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL)
- pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
- rs->rules[rs_num].inactive.open = 0;
- return (0);
-}
-
+#ifdef __FreeBSD__
int
-pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor, char *ruleset)
-{
- struct pf_ruleset *rs;
- struct pf_rule *rule;
- struct pf_rulequeue *old_rules;
- int s;
-
- if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
- return (EINVAL);
- rs = pf_find_ruleset(anchor, ruleset);
- if (rs == NULL || !rs->rules[rs_num].inactive.open ||
- ticket != rs->rules[rs_num].inactive.ticket)
- return (EBUSY);
-
- /* Swap rules, keep the old. */
- s = splsoftnet();
- old_rules = rs->rules[rs_num].active.ptr;
- rs->rules[rs_num].active.ptr =
- rs->rules[rs_num].inactive.ptr;
- rs->rules[rs_num].inactive.ptr = old_rules;
- rs->rules[rs_num].active.ticket =
- rs->rules[rs_num].inactive.ticket;
- pf_calc_skip_steps(rs->rules[rs_num].active.ptr);
-
- /* Purge the old rule list. */
- while ((rule = TAILQ_FIRST(old_rules)) != NULL)
- pf_rm_rule(old_rules, rule);
- rs->rules[rs_num].inactive.open = 0;
- pf_remove_if_empty_ruleset(rs);
- pf_update_anchor_rules();
- splx(s);
- return (0);
-}
-
+pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
+#else
int
-pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
+pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
+#endif
{
struct pf_pooladdr *pa = NULL;
struct pf_pool *pool = NULL;
@@ -787,19 +818,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCRCLRASTATS:
case DIOCRTSTADDRS:
case DIOCOSFPGET:
- case DIOCGETSRCNODES:
- case DIOCCLRSRCNODES:
- case DIOCIGETIFACES:
- case DIOCICLRISTATS:
- break;
- case DIOCRCLRTABLES:
- case DIOCRADDTABLES:
- case DIOCRDELTABLES:
- case DIOCRSETTFLAGS:
- if (((struct pfioc_table *)addr)->pfrio_flags &
- PFR_FLAG_DUMMY)
- break; /* dummy operation ok */
- return (EPERM);
+#ifdef __FreeBSD__
+ case DIOCGIFSPEED:
+#endif
+ break;
default:
return (EPERM);
}
@@ -828,38 +850,51 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCRGETASTATS:
case DIOCRTSTADDRS:
case DIOCOSFPGET:
- case DIOCGETSRCNODES:
- case DIOCIGETIFACES:
+#ifdef __FreeBSD__
+ case DIOCGIFSPEED:
+#endif
break;
- case DIOCRCLRTABLES:
- case DIOCRADDTABLES:
- case DIOCRDELTABLES:
- case DIOCRCLRTSTATS:
- case DIOCRCLRADDRS:
- case DIOCRADDADDRS:
- case DIOCRDELADDRS:
- case DIOCRSETADDRS:
- case DIOCRSETTFLAGS:
- if (((struct pfioc_table *)addr)->pfrio_flags &
- PFR_FLAG_DUMMY)
- break; /* dummy operation ok */
- return (EACCES);
default:
return (EACCES);
}
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+
switch (cmd) {
case DIOCSTART:
if (pf_status.running)
error = EEXIST;
else {
+ u_int32_t states = pf_status.states;
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ error = hook_pf();
+ PF_LOCK();
+ if (error) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: pfil registeration fail\n"));
+ break;
+ }
+#endif
+ bzero(&pf_status, sizeof(struct pf_status));
pf_status.running = 1;
+ pf_status.states = states;
+#ifdef __FreeBSD__
+ pf_status.since = time_second;
+#else
pf_status.since = time.tv_sec;
- if (pf_status.stateid == 0) {
- pf_status.stateid = time.tv_sec;
- pf_status.stateid = pf_status.stateid << 32;
- }
+#endif
+ if (status_ifp != NULL)
+#if defined(__FreeBSD__) && (__FreeBSD_version < 501113)
+ snprintf(pf_status.ifname, IFNAMSIZ, "%s%d",
+ status_ifp->if_name, status_ifp->if_unit);
+#else
+ strlcpy(pf_status.ifname,
+ status_ifp->if_xname, IFNAMSIZ);
+#endif
DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
}
break;
@@ -869,16 +904,40 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = ENOENT;
else {
pf_status.running = 0;
- pf_status.since = time.tv_sec;
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ error = dehook_pf();
+ PF_LOCK();
+ if (error) {
+ pf_status.running = 1;
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: pfil unregisteration failed\n"));
+ }
+#endif
DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
}
break;
case DIOCBEGINRULES: {
struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ struct pf_ruleset *ruleset;
+ struct pf_rule *rule;
+ int rs_num;
- error = pf_begin_rules(&pr->ticket, pf_get_ruleset_number(
- pr->rule.action), pr->anchor, pr->ruleset);
+ ruleset = pf_find_or_create_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ rs_num = pf_get_ruleset_number(pr->rule.action);
+ if (rs_num >= PF_RULESET_MAX) {
+ error = EINVAL;
+ break;
+ }
+ while ((rule =
+ TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr)) != NULL)
+ pf_rm_rule(ruleset->rules[rs_num].inactive.ptr, rule);
+ pr->ticket = ++ruleset->rules[rs_num].inactive.ticket;
break;
}
@@ -922,11 +981,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
bcopy(&pr->rule, rule, sizeof(struct pf_rule));
rule->anchor = NULL;
- rule->kif = NULL;
+ rule->ifp = NULL;
TAILQ_INIT(&rule->rpool.list);
/* initialize refcounting */
rule->states = 0;
- rule->src_nodes = 0;
rule->entries.tqe_prev = NULL;
#ifndef INET
if (rule->af == AF_INET) {
@@ -949,27 +1007,14 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
else
rule->nr = 0;
if (rule->ifname[0]) {
- rule->kif = pfi_attach_rule(rule->ifname);
- if (rule->kif == NULL) {
+ rule->ifp = ifunit(rule->ifname);
+ if (rule->ifp == NULL) {
pool_put(&pf_rule_pl, rule);
error = EINVAL;
break;
}
}
-#ifdef ALTQ
- /* set queue IDs */
- if (rule->qname[0] != 0) {
- if ((rule->qid = pf_qname2qid(rule->qname)) == 0)
- error = EBUSY;
- else if (rule->pqname[0] != 0) {
- if ((rule->pqid =
- pf_qname2qid(rule->pqname)) == 0)
- error = EBUSY;
- } else
- rule->pqid = rule->qid;
- }
-#endif
if (rule->tagname[0])
if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
error = EBUSY;
@@ -979,9 +1024,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EBUSY;
if (rule->rt && !rule->direction)
error = EINVAL;
- if (pfi_dynaddr_setup(&rule->src.addr, rule->af))
+ if (pf_dynaddr_setup(&rule->src.addr, rule->af))
error = EINVAL;
- if (pfi_dynaddr_setup(&rule->dst.addr, rule->af))
+ if (pf_dynaddr_setup(&rule->dst.addr, rule->af))
error = EINVAL;
if (pf_tbladdr_setup(ruleset, &rule->src.addr))
error = EINVAL;
@@ -1011,9 +1056,48 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCCOMMITRULES: {
struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ struct pf_ruleset *ruleset;
+ struct pf_rulequeue *old_rules;
+ struct pf_rule *rule;
+ int rs_num;
+
+ ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ rs_num = pf_get_ruleset_number(pr->rule.action);
+ if (rs_num >= PF_RULESET_MAX) {
+ error = EINVAL;
+ break;
+ }
+ if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) {
+ error = EBUSY;
+ break;
+ }
+
+#ifdef ALTQ
+ /* set queue IDs */
+ if (rs_num == PF_RULESET_FILTER)
+ pf_rule_set_qid(ruleset->rules[rs_num].inactive.ptr);
+#endif
+
+ /* Swap rules, keep the old. */
+ s = splsoftnet();
+ old_rules = ruleset->rules[rs_num].active.ptr;
+ ruleset->rules[rs_num].active.ptr =
+ ruleset->rules[rs_num].inactive.ptr;
+ ruleset->rules[rs_num].inactive.ptr = old_rules;
+ ruleset->rules[rs_num].active.ticket =
+ ruleset->rules[rs_num].inactive.ticket;
+ pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
- error = pf_commit_rules(pr->ticket, pf_get_ruleset_number(
- pr->rule.action), pr->anchor, pr->ruleset);
+ /* Purge the old rule list. */
+ while ((rule = TAILQ_FIRST(old_rules)) != NULL)
+ pf_rm_rule(old_rules, rule);
+ pf_remove_if_empty_ruleset(ruleset);
+ pf_update_anchor_rules();
+ splx(s);
break;
}
@@ -1075,8 +1159,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
bcopy(rule, &pr->rule, sizeof(struct pf_rule));
- pfi_dynaddr_copyout(&pr->rule.src.addr);
- pfi_dynaddr_copyout(&pr->rule.dst.addr);
+ pf_dynaddr_copyout(&pr->rule.src.addr);
+ pf_dynaddr_copyout(&pr->rule.dst.addr);
pf_tbladdr_copyout(&pr->rule.src.addr);
pf_tbladdr_copyout(&pr->rule.dst.addr);
for (i = 0; i < PF_SKIP_COUNT; ++i)
@@ -1160,26 +1244,23 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
#endif /* INET6 */
if (newrule->ifname[0]) {
- newrule->kif = pfi_attach_rule(newrule->ifname);
- if (newrule->kif == NULL) {
+ newrule->ifp = ifunit(newrule->ifname);
+ if (newrule->ifp == NULL) {
pool_put(&pf_rule_pl, newrule);
error = EINVAL;
break;
}
} else
- newrule->kif = NULL;
+ newrule->ifp = NULL;
#ifdef ALTQ
/* set queue IDs */
if (newrule->qname[0] != 0) {
- if ((newrule->qid =
- pf_qname2qid(newrule->qname)) == 0)
- error = EBUSY;
- else if (newrule->pqname[0] != 0) {
- if ((newrule->pqid =
- pf_qname2qid(newrule->pqname)) == 0)
- error = EBUSY;
- } else
+ newrule->qid = pf_qname_to_qid(newrule->qname);
+ if (newrule->pqname[0] != 0)
+ newrule->pqid =
+ pf_qname_to_qid(newrule->pqname);
+ else
newrule->pqid = newrule->qid;
}
#endif
@@ -1194,9 +1275,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
if (newrule->rt && !newrule->direction)
error = EINVAL;
- if (pfi_dynaddr_setup(&newrule->src.addr, newrule->af))
+ if (pf_dynaddr_setup(&newrule->src.addr, newrule->af))
error = EINVAL;
- if (pfi_dynaddr_setup(&newrule->dst.addr, newrule->af))
+ if (pf_dynaddr_setup(&newrule->dst.addr, newrule->af))
error = EINVAL;
if (pf_tbladdr_setup(ruleset, &newrule->src.addr))
error = EINVAL;
@@ -1274,61 +1355,45 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
case DIOCCLRSTATES: {
- struct pf_state *state;
- struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
- int killed = 0;
+ struct pf_tree_node *n;
s = splsoftnet();
- RB_FOREACH(state, pf_state_tree_id, &tree_id) {
- if (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
- state->u.s.kif->pfik_name)) {
- state->timeout = PFTM_PURGE;
-#if NPFSYNC
- /* don't send out individual delete messages */
- state->sync_flags = PFSTATE_NOSYNC;
-#endif
- killed++;
- }
- }
+ RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
+ n->state->timeout = PFTM_PURGE;
pf_purge_expired_states();
pf_status.states = 0;
- psk->psk_af = killed;
-#if NPFSYNC
- pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
-#endif
splx(s);
break;
}
case DIOCKILLSTATES: {
- struct pf_state *state;
+ struct pf_tree_node *n;
+ struct pf_state *st;
struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
int killed = 0;
s = splsoftnet();
- RB_FOREACH(state, pf_state_tree_id, &tree_id) {
- if ((!psk->psk_af || state->af == psk->psk_af)
- && (!psk->psk_proto || psk->psk_proto ==
- state->proto) &&
+ RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) {
+ st = n->state;
+ if ((!psk->psk_af || st->af == psk->psk_af) &&
+ (!psk->psk_proto || psk->psk_proto == st->proto) &&
PF_MATCHA(psk->psk_src.not,
&psk->psk_src.addr.v.a.addr,
- &psk->psk_src.addr.v.a.mask,
- &state->lan.addr, state->af) &&
+ &psk->psk_src.addr.v.a.mask, &st->lan.addr,
+ st->af) &&
PF_MATCHA(psk->psk_dst.not,
&psk->psk_dst.addr.v.a.addr,
- &psk->psk_dst.addr.v.a.mask,
- &state->ext.addr, state->af) &&
+ &psk->psk_dst.addr.v.a.mask, &st->ext.addr,
+ st->af) &&
(psk->psk_src.port_op == 0 ||
pf_match_port(psk->psk_src.port_op,
psk->psk_src.port[0], psk->psk_src.port[1],
- state->lan.port)) &&
+ st->lan.port)) &&
(psk->psk_dst.port_op == 0 ||
pf_match_port(psk->psk_dst.port_op,
psk->psk_dst.port[0], psk->psk_dst.port[1],
- state->ext.port)) &&
- (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
- state->u.s.kif->pfik_name))) {
- state->timeout = PFTM_PURGE;
+ st->ext.port))) {
+ st->timeout = PFTM_PURGE;
killed++;
}
}
@@ -1341,7 +1406,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCADDSTATE: {
struct pfioc_state *ps = (struct pfioc_state *)addr;
struct pf_state *state;
- struct pfi_kif *kif;
if (ps->state.timeout >= PFTM_MAX &&
ps->state.timeout != PFTM_UNTIL_PACKET) {
@@ -1354,26 +1418,19 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
s = splsoftnet();
- kif = pfi_lookup_create(ps->state.u.ifname);
- if (kif == NULL) {
- pool_put(&pf_state_pl, state);
- error = ENOENT;
- splx(s);
- break;
- }
bcopy(&ps->state, state, sizeof(struct pf_state));
- bzero(&state->u, sizeof(state->u));
- state->rule.ptr = &pf_default_rule;
+ state->rule.ptr = NULL;
state->nat_rule.ptr = NULL;
state->anchor.ptr = NULL;
- state->rt_kif = NULL;
+ state->rt_ifp = NULL;
+#ifdef __FreeBSD__
+ state->creation = time_second;
+#else
state->creation = time.tv_sec;
- state->pfsync_time = 0;
+#endif
state->packets[0] = state->packets[1] = 0;
state->bytes[0] = state->bytes[1] = 0;
-
- if (pf_insert_state(kif, state)) {
- pfi_maybe_destroy(kif);
+ if (pf_insert_state(state)) {
pool_put(&pf_state_pl, state);
error = ENOMEM;
}
@@ -1383,31 +1440,36 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCGETSTATE: {
struct pfioc_state *ps = (struct pfioc_state *)addr;
- struct pf_state *state;
+ struct pf_tree_node *n;
u_int32_t nr;
nr = 0;
s = splsoftnet();
- RB_FOREACH(state, pf_state_tree_id, &tree_id) {
+ RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) {
if (nr >= ps->nr)
break;
nr++;
}
- if (state == NULL) {
+ if (n == NULL) {
error = EBUSY;
splx(s);
break;
}
- bcopy(state, &ps->state, sizeof(struct pf_state));
- ps->state.rule.nr = state->rule.ptr->nr;
- ps->state.nat_rule.nr = (state->nat_rule.ptr == NULL) ?
- -1 : state->nat_rule.ptr->nr;
- ps->state.anchor.nr = (state->anchor.ptr == NULL) ?
- -1 : state->anchor.ptr->nr;
+ bcopy(n->state, &ps->state, sizeof(struct pf_state));
+ ps->state.rule.nr = n->state->rule.ptr->nr;
+ ps->state.nat_rule.nr = (n->state->nat_rule.ptr == NULL) ?
+ -1 : n->state->nat_rule.ptr->nr;
+ ps->state.anchor.nr = (n->state->anchor.ptr == NULL) ?
+ -1 : n->state->anchor.ptr->nr;
splx(s);
- ps->state.expire = pf_state_expires(state);
+ ps->state.expire = pf_state_expires(n->state);
+#ifdef __FreeBSD__
+ if (ps->state.expire > time_second)
+ ps->state.expire -= time_second;
+#else
if (ps->state.expire > time.tv_sec)
ps->state.expire -= time.tv_sec;
+#endif
else
ps->state.expire = 0;
break;
@@ -1415,53 +1477,59 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCGETSTATES: {
struct pfioc_states *ps = (struct pfioc_states *)addr;
- struct pf_state *state;
+ struct pf_tree_node *n;
struct pf_state *p, pstore;
- struct pfi_kif *kif;
u_int32_t nr = 0;
int space = ps->ps_len;
if (space == 0) {
s = splsoftnet();
- TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states)
- nr += kif->pfik_states;
+ RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
+ nr++;
splx(s);
ps->ps_len = sizeof(struct pf_state) * nr;
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
return (0);
}
s = splsoftnet();
p = ps->ps_states;
- TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states)
- RB_FOREACH(state, pf_state_tree_ext_gwy,
- &kif->pfik_ext_gwy) {
- int secs = time.tv_sec;
+ RB_FOREACH(n, pf_state_tree, &tree_ext_gwy) {
+#ifdef __FreeBSD__
+ int secs = time_second;
+#else
+ int secs = time.tv_sec;
+#endif
- if ((nr+1) * sizeof(*p) > (unsigned)ps->ps_len)
- break;
+ if ((nr + 1) * sizeof(*p) > (unsigned)ps->ps_len)
+ break;
- bcopy(state, &pstore, sizeof(pstore));
- strlcpy(pstore.u.ifname, kif->pfik_name,
- sizeof(pstore.u.ifname));
- pstore.rule.nr = state->rule.ptr->nr;
- pstore.nat_rule.nr = (state->nat_rule.ptr ==
- NULL) ? -1 : state->nat_rule.ptr->nr;
- pstore.anchor.nr = (state->anchor.ptr ==
- NULL) ? -1 : state->anchor.ptr->nr;
- pstore.creation = secs - pstore.creation;
- pstore.expire = pf_state_expires(state);
- if (pstore.expire > secs)
- pstore.expire -= secs;
- else
- pstore.expire = 0;
- error = copyout(&pstore, p, sizeof(*p));
- if (error) {
- splx(s);
- goto fail;
- }
- p++;
- nr++;
+ bcopy(n->state, &pstore, sizeof(pstore));
+ pstore.rule.nr = n->state->rule.ptr->nr;
+ pstore.nat_rule.nr = (n->state->nat_rule.ptr == NULL) ?
+ -1 : n->state->nat_rule.ptr->nr;
+ pstore.anchor.nr = (n->state->anchor.ptr == NULL) ?
+ -1 : n->state->anchor.ptr->nr;
+ pstore.creation = secs - pstore.creation;
+ pstore.expire = pf_state_expires(n->state);
+ if (pstore.expire > secs)
+ pstore.expire -= secs;
+ else
+ pstore.expire = 0;
+#ifdef __FreeBSD__
+ PF_COPYOUT(&pstore, p, sizeof(*p), error);
+#else
+ error = copyout(&pstore, p, sizeof(*p));
+#endif
+ if (error) {
+ splx(s);
+ goto fail;
}
+ p++;
+ nr++;
+ }
ps->ps_len = sizeof(struct pf_state) * nr;
splx(s);
break;
@@ -1470,44 +1538,68 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCGETSTATUS: {
struct pf_status *s = (struct pf_status *)addr;
bcopy(&pf_status, s, sizeof(struct pf_status));
- pfi_fill_oldstatus(s);
break;
}
case DIOCSETSTATUSIF: {
struct pfioc_if *pi = (struct pfioc_if *)addr;
+ struct ifnet *ifp;
if (pi->ifname[0] == 0) {
+ status_ifp = NULL;
bzero(pf_status.ifname, IFNAMSIZ);
break;
}
- if (ifunit(pi->ifname) == NULL) {
+ if ((ifp = ifunit(pi->ifname)) == NULL) {
error = EINVAL;
break;
- }
- strlcpy(pf_status.ifname, pi->ifname, IFNAMSIZ);
- break;
+ } else if (ifp == status_ifp)
+ break;
+ status_ifp = ifp;
+ /* fallthrough into DIOCCLRSTATUS */
}
case DIOCCLRSTATUS: {
- bzero(pf_status.counters, sizeof(pf_status.counters));
- bzero(pf_status.fcounters, sizeof(pf_status.fcounters));
- bzero(pf_status.scounters, sizeof(pf_status.scounters));
- if (*pf_status.ifname)
- pfi_clr_istats(pf_status.ifname, NULL,
- PFI_FLAG_INSTANCE);
+ u_int32_t running = pf_status.running;
+ u_int32_t states = pf_status.states;
+ u_int32_t since = pf_status.since;
+ u_int32_t debug = pf_status.debug;
+
+ bzero(&pf_status, sizeof(struct pf_status));
+ pf_status.running = running;
+ pf_status.states = states;
+ pf_status.since = since;
+ pf_status.debug = debug;
+ if (status_ifp != NULL)
+#if defined(__FreeBSD__) && (__FreeBSD_version < 501113)
+ snprintf(pf_status.ifname, IFNAMSIZ, "%s%d",
+ status_ifp->if_name, status_ifp->if_unit);
+#else
+ strlcpy(pf_status.ifname,
+ status_ifp->if_xname, IFNAMSIZ);
+#endif
break;
}
case DIOCNATLOOK: {
struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr;
- struct pf_state *state;
- struct pf_state key;
- int m = 0, direction = pnl->direction;
+ struct pf_state *st;
+ struct pf_tree_node key;
+ int direction = pnl->direction;
key.af = pnl->af;
key.proto = pnl->proto;
+ /*
+ * userland gives us source and dest of connection, reverse
+ * the lookup so we ask for what happens with the return
+ * traffic, enabling us to find it in the state tree.
+ */
+ PF_ACPY(&key.addr[1], &pnl->saddr, pnl->af);
+ key.port[1] = pnl->sport;
+ PF_ACPY(&key.addr[0], &pnl->daddr, pnl->af);
+ key.port[0] = pnl->dport;
+
if (!pnl->proto ||
PF_AZERO(&pnl->saddr, pnl->af) ||
PF_AZERO(&pnl->daddr, pnl->af) ||
@@ -1515,40 +1607,22 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
else {
s = splsoftnet();
-
- /*
- * userland gives us source and dest of connection,
- * reverse the lookup so we ask for what happens with
- * the return traffic, enabling us to find it in the
- * state tree.
- */
- if (direction == PF_IN) {
- PF_ACPY(&key.ext.addr, &pnl->daddr, pnl->af);
- key.ext.port = pnl->dport;
- PF_ACPY(&key.gwy.addr, &pnl->saddr, pnl->af);
- key.gwy.port = pnl->sport;
- state = pf_find_state_all(&key, PF_EXT_GWY, &m);
- } else {
- PF_ACPY(&key.lan.addr, &pnl->daddr, pnl->af);
- key.lan.port = pnl->dport;
- PF_ACPY(&key.ext.addr, &pnl->saddr, pnl->af);
- key.ext.port = pnl->sport;
- state = pf_find_state_all(&key, PF_LAN_EXT, &m);
- }
- if (m > 1)
- error = E2BIG; /* more than one state */
- else if (state != NULL) {
+ if (direction == PF_IN)
+ st = pf_find_state(&tree_ext_gwy, &key);
+ else
+ st = pf_find_state(&tree_lan_ext, &key);
+ if (st != NULL) {
if (direction == PF_IN) {
- PF_ACPY(&pnl->rsaddr, &state->lan.addr,
- state->af);
- pnl->rsport = state->lan.port;
+ PF_ACPY(&pnl->rsaddr, &st->lan.addr,
+ st->af);
+ pnl->rsport = st->lan.port;
PF_ACPY(&pnl->rdaddr, &pnl->daddr,
pnl->af);
pnl->rdport = pnl->dport;
} else {
- PF_ACPY(&pnl->rdaddr, &state->gwy.addr,
- state->af);
- pnl->rdport = state->gwy.port;
+ PF_ACPY(&pnl->rdaddr, &st->gwy.addr,
+ st->af);
+ pnl->rdport = st->gwy.port;
PF_ACPY(&pnl->rsaddr, &pnl->saddr,
pnl->af);
pnl->rsport = pnl->sport;
@@ -1601,16 +1675,19 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
struct pfioc_limit *pl = (struct pfioc_limit *)addr;
int old_limit;
- if (pl->index < 0 || pl->index >= PF_LIMIT_MAX ||
- pf_pool_limits[pl->index].pp == NULL) {
+ if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
error = EINVAL;
goto fail;
}
+#ifdef __FreeBSD__
+ uma_zone_set_max(pf_pool_limits[pl->index].pp, pl->limit);
+#else
if (pool_sethardlimit(pf_pool_limits[pl->index].pp,
pl->limit, NULL, 0) != 0) {
error = EBUSY;
goto fail;
}
+#endif
old_limit = pf_pool_limits[pl->index].limit;
pf_pool_limits[pl->index].limit = pl->limit;
pl->limit = old_limit;
@@ -1637,6 +1714,26 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
+#ifdef __FreeBSD__
+ case DIOCGIFSPEED: {
+ struct pf_ifspeed *psp = (struct pf_ifspeed *)addr;
+ struct pf_ifspeed ps;
+ struct ifnet *ifp;
+
+ if (psp->ifname[0] != 0) {
+ /* Can we completely trust user-land? */
+ strlcpy(ps.ifname, psp->ifname, IFNAMSIZ);
+ ifp = ifunit(ps.ifname);
+ if (ifp )
+ psp->baudrate = ifp->if_baudrate;
+ else
+ error = EINVAL;
+ } else
+ error = EINVAL;
+ break;
+ }
+#endif /* __FreeBSD__ */
+
#ifdef ALTQ
case DIOCSTARTALTQ: {
struct pf_altq *altq;
@@ -1705,8 +1802,24 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case DIOCBEGINALTQS: {
u_int32_t *ticket = (u_int32_t *)addr;
+ struct pf_altq *altq;
- error = pf_begin_altq(ticket);
+ /* Purge the old altq list */
+ while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
+ TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
+ if (altq->qname[0] == 0) {
+ /* detach and destroy the discipline */
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ error = altq_remove(altq);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ }
+ pool_put(&pf_altq_pl, altq);
+ }
+ *ticket = ++ticket_altqs_inactive;
break;
}
@@ -1730,11 +1843,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
* copy the necessary fields
*/
if (altq->qname[0] != 0) {
- if ((altq->qid = pf_qname2qid(altq->qname)) == 0) {
- error = EBUSY;
- pool_put(&pf_altq_pl, altq);
- break;
- }
TAILQ_FOREACH(a, pf_altqs_inactive, entries) {
if (strncmp(a->ifname, altq->ifname,
IFNAMSIZ) == 0 && a->qname[0] == 0) {
@@ -1744,7 +1852,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
}
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
error = altq_add(altq);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
if (error) {
pool_put(&pf_altq_pl, altq);
break;
@@ -1756,9 +1870,75 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
case DIOCCOMMITALTQS: {
- u_int32_t ticket = *(u_int32_t *)addr;
+ u_int32_t *ticket = (u_int32_t *)addr;
+ struct pf_altqqueue *old_altqs;
+ struct pf_altq *altq;
+ struct pf_anchor *anchor;
+ struct pf_ruleset *ruleset;
+ int err;
- error = pf_commit_altq(ticket);
+ if (*ticket != ticket_altqs_inactive) {
+ error = EBUSY;
+ break;
+ }
+
+ /* Swap altqs, keep the old. */
+ s = splsoftnet();
+ old_altqs = pf_altqs_active;
+ pf_altqs_active = pf_altqs_inactive;
+ pf_altqs_inactive = old_altqs;
+ ticket_altqs_active = ticket_altqs_inactive;
+
+ /* Attach new disciplines */
+ TAILQ_FOREACH(altq, pf_altqs_active, entries) {
+ if (altq->qname[0] == 0) {
+ /* attach the discipline */
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ error = altq_pfattach(altq);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ if (error) {
+ splx(s);
+ goto fail;
+ }
+ }
+ }
+
+ /* Purge the old altq list */
+ while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
+ TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
+ if (altq->qname[0] == 0) {
+ /* detach and destroy the discipline */
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ err = altq_pfdetach(altq);
+ if (err != 0 && error == 0)
+ error = err;
+ err = altq_remove(altq);
+ if (err != 0 && error == 0)
+ error = err;
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ }
+ pool_put(&pf_altq_pl, altq);
+ }
+ splx(s);
+
+ /* update queue IDs */
+ pf_rule_set_qid(
+ pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
+ TAILQ_FOREACH(anchor, &pf_anchors, entries) {
+ TAILQ_FOREACH(ruleset, &anchor->rulesets, entries) {
+ pf_rule_set_qid(
+ ruleset->rules[PF_RULESET_FILTER].active.ptr
+ );
+ }
+ }
break;
}
@@ -1829,7 +2009,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
splx(s);
break;
}
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
error = altq_getqstats(altq, pq->buf, &nbytes);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
splx(s);
if (error == 0) {
pq->scheduler = altq->scheduler;
@@ -1875,16 +2061,15 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr));
if (pa->ifname[0]) {
- pa->kif = pfi_attach_rule(pa->ifname);
- if (pa->kif == NULL) {
+ pa->ifp = ifunit(pa->ifname);
+ if (pa->ifp == NULL) {
pool_put(&pf_pooladdr_pl, pa);
error = EINVAL;
break;
}
}
- if (pfi_dynaddr_setup(&pa->addr, pp->af)) {
- pfi_dynaddr_remove(&pa->addr);
- pfi_detach_rule(pa->kif);
+ if (pf_dynaddr_setup(&pa->addr, pp->af)) {
+ pf_dynaddr_remove(&pa->addr);
pool_put(&pf_pooladdr_pl, pa);
error = EINVAL;
break;
@@ -1934,7 +2119,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr));
- pfi_dynaddr_copyout(&pp->addr.addr);
+ pf_dynaddr_copyout(&pp->addr.addr);
pf_tbladdr_copyout(&pp->addr.addr);
splx(s);
break;
@@ -1990,18 +2175,17 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
#endif /* INET6 */
if (newpa->ifname[0]) {
- newpa->kif = pfi_attach_rule(newpa->ifname);
- if (newpa->kif == NULL) {
+ newpa->ifp = ifunit(newpa->ifname);
+ if (newpa->ifp == NULL) {
pool_put(&pf_pooladdr_pl, newpa);
error = EINVAL;
break;
}
} else
- newpa->kif = NULL;
- if (pfi_dynaddr_setup(&newpa->addr, pca->af) ||
+ newpa->ifp = NULL;
+ if (pf_dynaddr_setup(&newpa->addr, pca->af) ||
pf_tbladdr_setup(ruleset, &newpa->addr)) {
- pfi_dynaddr_remove(&newpa->addr);
- pfi_detach_rule(newpa->kif);
+ pf_dynaddr_remove(&newpa->addr);
pool_put(&pf_pooladdr_pl, newpa);
error = EINVAL;
break;
@@ -2031,9 +2215,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
if (pca->action == PF_CHANGE_REMOVE) {
TAILQ_REMOVE(&pool->list, oldpa, entries);
- pfi_dynaddr_remove(&oldpa->addr);
+ pf_dynaddr_remove(&oldpa->addr);
pf_tbladdr_remove(&oldpa->addr);
- pfi_detach_rule(oldpa->kif);
pool_put(&pf_pooladdr_pl, oldpa);
} else {
if (oldpa == NULL)
@@ -2126,7 +2309,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
- io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ io->pfrio_flags);
break;
}
@@ -2138,7 +2321,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size,
- &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ &io->pfrio_nadd, io->pfrio_flags);
break;
}
@@ -2150,7 +2333,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size,
- &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ &io->pfrio_ndel, io->pfrio_flags);
break;
}
@@ -2162,7 +2345,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer,
- &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ &io->pfrio_size, io->pfrio_flags);
break;
}
@@ -2174,7 +2357,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer,
- &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ &io->pfrio_size, io->pfrio_flags);
break;
}
@@ -2186,7 +2369,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size,
- &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ &io->pfrio_nzero, io->pfrio_flags);
break;
}
@@ -2199,7 +2382,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size,
io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
- &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ &io->pfrio_ndel, io->pfrio_flags);
break;
}
@@ -2211,7 +2394,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
- io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ io->pfrio_flags);
break;
}
@@ -2223,8 +2406,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer,
- io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
- PFR_FLAG_USERIOCTL);
+ io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags);
break;
}
@@ -2236,8 +2418,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer,
- io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
- PFR_FLAG_USERIOCTL);
+ io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags);
break;
}
@@ -2250,8 +2431,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer,
io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
- &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
- PFR_FLAG_USERIOCTL);
+ &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags);
break;
}
@@ -2263,7 +2443,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer,
- &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ &io->pfrio_size, io->pfrio_flags);
break;
}
@@ -2275,7 +2455,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer,
- &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ &io->pfrio_size, io->pfrio_flags);
break;
}
@@ -2287,8 +2467,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer,
- io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags |
- PFR_FLAG_USERIOCTL);
+ io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags);
break;
}
@@ -2300,8 +2479,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer,
- io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags |
- PFR_FLAG_USERIOCTL);
+ io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags);
break;
}
@@ -2313,7 +2491,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_ina_begin(&io->pfrio_table, &io->pfrio_ticket,
- &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ &io->pfrio_ndel, io->pfrio_flags);
break;
}
@@ -2325,8 +2503,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
error = pfr_ina_commit(&io->pfrio_table, io->pfrio_ticket,
- &io->pfrio_nadd, &io->pfrio_nchange, io->pfrio_flags |
- PFR_FLAG_USERIOCTL);
+ &io->pfrio_nadd, &io->pfrio_nchange, io->pfrio_flags);
break;
}
@@ -2339,10 +2516,16 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer,
io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr,
- io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ io->pfrio_ticket, io->pfrio_flags);
break;
}
+ case DIOCOSFPFLUSH:
+ s = splsoftnet();
+ pf_osfp_flush();
+ splx(s);
+ break;
+
case DIOCOSFPADD: {
struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
s = splsoftnet();
@@ -2359,297 +2542,696 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
- case DIOCXBEGIN: {
- struct pfioc_trans *io = (struct pfioc_trans *)addr;
- struct pfioc_trans_e ioe;
- struct pfr_table table;
- int i;
+ default:
+ error = ENODEV;
+ break;
+ }
+fail:
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ return (error);
+}
+
+#ifdef __FreeBSD__
+/*
+ * XXX - Check for version missmatch!!!
+ */
+static int
+pf_beginrules(void *addr)
+{
+ struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ struct pf_ruleset *ruleset;
+ struct pf_rule *rule;
+ int rs_num;
+ int error = 0;
- if (io->esize != sizeof(ioe)) {
- error = ENODEV;
- goto fail;
+ do {
+ ruleset = pf_find_or_create_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
}
- for (i = 0; i < io->size; i++) {
- if (copyin(io->array+i, &ioe, sizeof(ioe))) {
- error = EFAULT;
- goto fail;
- }
- switch (ioe.rs_num) {
+ rs_num = pf_get_ruleset_number(pr->rule.action);
+ if (rs_num >= PF_RULESET_MAX) {
+ error = EINVAL;
+ break;
+ }
+ while ((rule =
+ TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr)) != NULL)
+ pf_rm_rule(ruleset->rules[rs_num].inactive.ptr, rule);
+ pr->ticket = ++ruleset->rules[rs_num].inactive.ticket;
+ } while(0);
+
+ return (error);
+}
+
+static int
+pf_commitrules(void *addr)
+{
+ struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ struct pf_ruleset *ruleset;
+ struct pf_rulequeue *old_rules;
+ struct pf_rule *rule;
+ int rs_num, s;
+ int error = 0;
+
+ do {
+ ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ rs_num = pf_get_ruleset_number(pr->rule.action);
+ if (rs_num >= PF_RULESET_MAX) {
+ error = EINVAL;
+ break;
+ }
+ if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) {
+ error = EBUSY;
+ break;
+ }
+
#ifdef ALTQ
- case PF_RULESET_ALTQ:
- if (ioe.anchor[0] || ioe.ruleset[0]) {
- error = EINVAL;
- goto fail;
- }
- if ((error = pf_begin_altq(&ioe.ticket)))
- goto fail;
- break;
-#endif /* ALTQ */
- case PF_RULESET_TABLE:
- bzero(&table, sizeof(table));
- strlcpy(table.pfrt_anchor, ioe.anchor,
- sizeof(table.pfrt_anchor));
- strlcpy(table.pfrt_ruleset, ioe.ruleset,
- sizeof(table.pfrt_ruleset));
- if ((error = pfr_ina_begin(&table,
- &ioe.ticket, NULL, 0)))
- goto fail;
- break;
- default:
- if ((error = pf_begin_rules(&ioe.ticket,
- ioe.rs_num, ioe.anchor, ioe.ruleset)))
- goto fail;
- break;
- }
- if (copyout(&ioe, io->array+i, sizeof(io->array[i]))) {
- error = EFAULT;
- goto fail;
- }
+ /* set queue IDs */
+ if (rs_num == PF_RULESET_FILTER)
+ pf_rule_set_qid(ruleset->rules[rs_num].inactive.ptr);
+#endif
+
+ /* Swap rules, keep the old. */
+ s = splsoftnet();
+ old_rules = ruleset->rules[rs_num].active.ptr;
+ ruleset->rules[rs_num].active.ptr =
+ ruleset->rules[rs_num].inactive.ptr;
+ ruleset->rules[rs_num].inactive.ptr = old_rules;
+ ruleset->rules[rs_num].active.ticket =
+ ruleset->rules[rs_num].inactive.ticket;
+ pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
+
+ /* Purge the old rule list. */
+ while ((rule = TAILQ_FIRST(old_rules)) != NULL)
+ pf_rm_rule(old_rules, rule);
+ pf_remove_if_empty_ruleset(ruleset);
+ pf_update_anchor_rules();
+ splx(s);
+ } while (0);
+
+ return (error);
+}
+
+#ifdef ALTQ
+static int
+pf_beginaltqs(void *addr)
+{
+ u_int32_t *ticket = (u_int32_t *)addr;
+ struct pf_altq *altq;
+ int error = 0;
+
+ /* Purge the old altq list */
+ while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
+ TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
+ if (altq->qname[0] == 0) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ /* detach and destroy the discipline */
+ error = altq_remove(altq);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
}
- break;
+ uma_zfree(pf_altq_pl, altq);
}
+ *ticket = ++ticket_altqs_inactive;
- case DIOCXROLLBACK: {
- struct pfioc_trans *io = (struct pfioc_trans *)addr;
- struct pfioc_trans_e ioe;
- struct pfr_table table;
- int i;
+ return (error);
+}
- if (io->esize != sizeof(ioe)) {
- error = ENODEV;
- goto fail;
+static int
+pf_commitaltqs(void *addr)
+{
+ u_int32_t *ticket = (u_int32_t *)addr;
+ struct pf_altqqueue *old_altqs;
+ struct pf_altq *altq;
+ struct pf_anchor *anchor;
+ struct pf_ruleset *ruleset;
+ int err;
+ int s;
+ int error = 0;
+
+ do {
+ if (*ticket != ticket_altqs_inactive) {
+ error = EBUSY;
+ break;
}
- for (i = 0; i < io->size; i++) {
- if (copyin(io->array+i, &ioe, sizeof(ioe))) {
- error = EFAULT;
- goto fail;
- }
- switch (ioe.rs_num) {
-#ifdef ALTQ
- case PF_RULESET_ALTQ:
- if (ioe.anchor[0] || ioe.ruleset[0]) {
- error = EINVAL;
- goto fail;
+
+ /* Swap altqs, keep the old. */
+ s = splsoftnet();
+ old_altqs = pf_altqs_active;
+ pf_altqs_active = pf_altqs_inactive;
+ pf_altqs_inactive = old_altqs;
+ ticket_altqs_active = ticket_altqs_inactive;
+
+ /* Attach new disciplines */
+ TAILQ_FOREACH(altq, pf_altqs_active, entries) {
+ if (altq->qname[0] == 0) {
+ /* attach the discipline */
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ error = altq_pfattach(altq);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ if (error) {
+ splx(s);
+ goto altq_fail;
}
- if ((error = pf_rollback_altq(ioe.ticket)))
- goto fail; /* really bad */
- break;
-#endif /* ALTQ */
- case PF_RULESET_TABLE:
- bzero(&table, sizeof(table));
- strlcpy(table.pfrt_anchor, ioe.anchor,
- sizeof(table.pfrt_anchor));
- strlcpy(table.pfrt_ruleset, ioe.ruleset,
- sizeof(table.pfrt_ruleset));
- if ((error = pfr_ina_rollback(&table,
- ioe.ticket, NULL, 0)))
- goto fail; /* really bad */
- break;
- default:
- if ((error = pf_rollback_rules(ioe.ticket,
- ioe.rs_num, ioe.anchor, ioe.ruleset)))
- goto fail; /* really bad */
- break;
}
}
- break;
- }
-
- case DIOCXCOMMIT: {
- struct pfioc_trans *io = (struct pfioc_trans *)addr;
- struct pfioc_trans_e ioe;
- struct pfr_table table;
- struct pf_ruleset *rs;
- int i;
- if (io->esize != sizeof(ioe)) {
- error = ENODEV;
- goto fail;
+ /* Purge the old altq list */
+ while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
+ TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
+ if (altq->qname[0] == 0) {
+ /* detach and destroy the discipline */
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ err = altq_pfdetach(altq);
+ if (err != 0 && error == 0)
+ error = err;
+ err = altq_remove(altq);
+ if (err != 0 && error == 0)
+ error = err;
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ }
+ uma_zfree(pf_altq_pl, altq);
}
- /* first makes sure everything will succeed */
- for (i = 0; i < io->size; i++) {
- if (copyin(io->array+i, &ioe, sizeof(ioe))) {
- error = EFAULT;
- goto fail;
+ splx(s);
+
+ /* update queue IDs */
+ pf_rule_set_qid(
+ pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
+ TAILQ_FOREACH(anchor, &pf_anchors, entries) {
+ TAILQ_FOREACH(ruleset, &anchor->rulesets, entries) {
+ pf_rule_set_qid(
+ ruleset->rules[PF_RULESET_FILTER].active.ptr
+ );
}
- switch (ioe.rs_num) {
-#ifdef ALTQ
- case PF_RULESET_ALTQ:
- if (ioe.anchor[0] || ioe.ruleset[0]) {
- error = EINVAL;
- goto fail;
- }
- if (!altqs_inactive_open || ioe.ticket !=
- ticket_altqs_inactive) {
- error = EBUSY;
- goto fail;
- }
- break;
-#endif /* ALTQ */
- case PF_RULESET_TABLE:
- rs = pf_find_ruleset(ioe.anchor, ioe.ruleset);
- if (rs == NULL || !rs->topen || ioe.ticket !=
- rs->tticket) {
- error = EBUSY;
- goto fail;
- }
- break;
- default:
- if (ioe.rs_num < 0 || ioe.rs_num >=
- PF_RULESET_MAX) {
+ }
+ } while (0);
+
+altq_fail:
+
+ return (error);
+}
+
+static int
+pf_stopaltq(void)
+{
+ struct pf_altq *altq;
+ struct ifnet *ifp;
+ struct tb_profile tb;
+ int err;
+ int s;
+ int error = 0;
+
+ do {
+ /* disable all altq interfaces on active list */
+ s = splsoftnet();
+ TAILQ_FOREACH(altq, pf_altqs_active, entries) {
+ if (altq->qname[0] == 0) {
+ if ((ifp = ifunit(altq->ifname)) == NULL) {
error = EINVAL;
- goto fail;
+ break;
}
- rs = pf_find_ruleset(ioe.anchor, ioe.ruleset);
- if (rs == NULL ||
- !rs->rules[ioe.rs_num].inactive.open ||
- rs->rules[ioe.rs_num].inactive.ticket !=
- ioe.ticket) {
- error = EBUSY;
- goto fail;
+ if (ifp->if_snd.altq_type != ALTQT_NONE) {
+ err = altq_disable(&ifp->if_snd);
+ if (err != 0 && error == 0)
+ error = err;
}
- break;
+ /* clear tokenbucket regulator */
+ tb.rate = 0;
+ err = tbr_set(&ifp->if_snd, &tb);
+ if (err != 0 && error == 0)
+ error = err;
}
}
- /* now do the commit - no errors should happen here */
- for (i = 0; i < io->size; i++) {
- if (copyin(io->array+i, &ioe, sizeof(ioe))) {
- error = EFAULT;
- goto fail;
- }
- switch (ioe.rs_num) {
+ if (error == 0)
+ pfaltq_running = 0;
+ splx(s);
+ } while (0);
+
+ return (error);
+}
+#endif
+
+static void
+pf_clearstates(void)
+{
+ struct pf_tree_node *n;
+ int s;
+
+ s = splsoftnet();
+ RB_FOREACH(n, pf_state_tree, &tree_ext_gwy)
+ n->state->timeout = PFTM_PURGE;
+ pf_purge_expired_states();
+ pf_status.states = 0;
+ splx(s);
+}
+
+static int
+pf_clear_tables(void *addr)
+{
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+ int error;
+
+ error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
+ io->pfrio_flags);
+
+ return (error);
+}
+
+static int
+shutdown_pf(void)
+{
+ struct pfioc_rule pr;
#ifdef ALTQ
- case PF_RULESET_ALTQ:
- if ((error = pf_commit_altq(ioe.ticket)))
- goto fail; /* really bad */
- break;
-#endif /* ALTQ */
- case PF_RULESET_TABLE:
- bzero(&table, sizeof(table));
- strlcpy(table.pfrt_anchor, ioe.anchor,
- sizeof(table.pfrt_anchor));
- strlcpy(table.pfrt_ruleset, ioe.ruleset,
- sizeof(table.pfrt_ruleset));
- if ((error = pfr_ina_commit(&table, ioe.ticket,
- NULL, NULL, 0)))
- goto fail; /* really bad */
- break;
- default:
- if ((error = pf_commit_rules(ioe.ticket,
- ioe.rs_num, ioe.anchor, ioe.ruleset)))
- goto fail; /* really bad */
- break;
- }
- }
- break;
- }
+ struct pfioc_altq pa;
+#endif
+ struct pfioc_table io;
+ int error = 0;
- case DIOCGETSRCNODES: {
- struct pfioc_src_nodes *psn = (struct pfioc_src_nodes *)addr;
- struct pf_src_node *n;
- struct pf_src_node *p, pstore;
- u_int32_t nr = 0;
- int space = psn->psn_len;
+ callout_stop(&pf_expire_to);
- if (space == 0) {
- s = splsoftnet();
- RB_FOREACH(n, pf_src_tree, &tree_src_tracking)
- nr++;
- splx(s);
- psn->psn_len = sizeof(struct pf_src_node) * nr;
- return (0);
+ PF_LOCK();
+ pf_status.running = 0;
+ do {
+#ifdef ALTQ
+ if ((error = pf_stopaltq())) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("ALTQ: stop(%i)\n", error));
+ break;
+ }
+#endif
+ bzero(&pr, sizeof(pr));
+ pr.rule.action = PF_SCRUB;
+ if ((error = pf_beginrules(&pr))) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("PF_SCRUB: begin(%i)\n", error));
+ break;
+ }
+ if ((error = pf_commitrules(&pr))) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("PF_SCRUB: commit(%i)\n", error));
+ break;
}
- s = splsoftnet();
- p = psn->psn_src_nodes;
- RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
- int secs = time.tv_sec;
+ pr.rule.action = PF_PASS;
+ if ((error = pf_beginrules(&pr))) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("PF_PASS: begin(%i)\n", error));
+ break;
+ }
+ if ((error = pf_commitrules(&pr))) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("PF_PASS: commit(%i)\n", error));
+ break;
+ }
- if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len)
- break;
+/*
+ * XXX not sure, but can't hurt:
+ */
+ bzero(&pr, sizeof(pr));
+ pr.rule.action = PF_NAT;
+ if ((error = pf_beginrules(&pr))) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("PF_NAT: begin(%i)\n", error));
+ break;
+ }
+ if ((error = pf_commitrules(&pr))) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("PF_NAT: commit(%i)\n", error));
+ break;
+ }
- bcopy(n, &pstore, sizeof(pstore));
- if (n->rule.ptr != NULL)
- pstore.rule.nr = n->rule.ptr->nr;
- pstore.creation = secs - pstore.creation;
- if (pstore.expire > secs)
- pstore.expire -= secs;
- else
- pstore.expire = 0;
- error = copyout(&pstore, p, sizeof(*p));
- if (error) {
- splx(s);
- goto fail;
- }
- p++;
- nr++;
+ pr.rule.action = PF_BINAT;
+ if ((error = pf_beginrules(&pr))) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("PF_BINAT: begin(%i)\n", error));
+ break;
+ }
+ if ((error = pf_commitrules(&pr))) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("PF_BINAT: begin(%i)\n", error));
+ break;
}
- psn->psn_len = sizeof(struct pf_src_node) * nr;
- splx(s);
- break;
- }
- case DIOCCLRSRCNODES: {
- struct pf_src_node *n;
- struct pf_state *state;
+ pr.rule.action = PF_RDR;
+ if ((error = pf_beginrules(&pr))) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("PF_RDR: begin(%i)\n", error));
+ break;
+ }
+ if ((error = pf_commitrules(&pr))) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("PF_RDR: commit(%i)\n", error));
+ break;
+ }
- s = splsoftnet();
- RB_FOREACH(state, pf_state_tree_id, &tree_id) {
- state->src_node = NULL;
- state->nat_src_node = NULL;
+#ifdef ALTQ
+ bzero(&pa, sizeof(pa));
+ if ((error = pf_beginaltqs(&pa))) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("ALTQ: begin(%i)\n", error));
+ break;
}
- RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
- n->expire = 1;
- n->states = 0;
+ if ((error = pf_commitaltqs(&pa))) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("ALTQ: commit(%i)\n", error));
+ break;
}
- pf_purge_expired_src_nodes();
- pf_status.src_nodes = 0;
- splx(s);
- break;
+#endif
+ pf_clearstates();
+
+ bzero(&io, sizeof(io));
+ if ((error = pf_clear_tables(&io))) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("TABLES: clear(%i)\n", error));
+ break;
+ }
+ pf_osfp_flush();
+ } while(0);
+
+ PF_UNLOCK();
+ return (error);
+}
+
+static int
+#if (__FreeBSD_version < 501108)
+pf_check_in(void *ip, int hlen, struct ifnet *ifp, int dir, struct mbuf **m)
+#else
+pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
+#endif
+{
+ /*
+ * XXX Wed Jul 9 22:03:16 2003 UTC
+ * OpenBSD has changed its byte ordering convention on ip_len/ip_off
+ * in network stack. OpenBSD's network stack have converted
+ * ip_len/ip_off to host byte order frist as FreeBSD.
+ * Now this is not true anymore , so we should convert back to network
+ * byte order.
+ */
+ struct ip *h = NULL;
+ int chk;
+
+ if ((*m)->m_pkthdr.len >= (int)sizeof(struct ip)) {
+ /* if m_pkthdr.len is less than ip header, pf will handle. */
+ h = mtod(*m, struct ip *);
+ HTONS(h->ip_len);
+ HTONS(h->ip_off);
+ }
+ chk = pf_test(PF_IN, ifp, m);
+ if (chk && *m) {
+ m_freem(*m);
+ *m = NULL;
+ }
+ if (*m != NULL) {
+ /* pf_test can change ip header location */
+ h = mtod(*m, struct ip *);
+ NTOHS(h->ip_len);
+ NTOHS(h->ip_off);
+ }
+ return chk;
+}
+
+static int
+#if (__FreeBSD_version < 501108)
+pf_check_out(void *ip, int hlen, struct ifnet *ifp, int dir, struct mbuf **m)
+#else
+pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
+#endif
+{
+ /*
+ * XXX Wed Jul 9 22:03:16 2003 UTC
+ * OpenBSD has changed its byte ordering convention on ip_len/ip_off
+ * in network stack. OpenBSD's network stack have converted
+ * ip_len/ip_off to host byte order frist as FreeBSD.
+ * Now this is not true anymore , so we should convert back to network
+ * byte order.
+ */
+ struct ip *h = NULL;
+ int chk;
+
+ /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
+ if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ in_delayed_cksum(*m);
+ (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+ }
+ if ((*m)->m_pkthdr.len >= (int)sizeof(*h)) {
+ /* if m_pkthdr.len is less than ip header, pf will handle. */
+ h = mtod(*m, struct ip *);
+ HTONS(h->ip_len);
+ HTONS(h->ip_off);
+ }
+ chk = pf_test(PF_OUT, ifp, m);
+ if (chk && *m) {
+ m_freem(*m);
+ *m = NULL;
+ }
+ if (*m != NULL) {
+ /* pf_test can change ip header location */
+ h = mtod(*m, struct ip *);
+ NTOHS(h->ip_len);
+ NTOHS(h->ip_off);
+ }
+ return chk;
+}
+
+#ifdef INET6
+static int
+#if (__FreeBSD_version < 501108)
+pf_check6_in(void *ip, int hlen, struct ifnet *ifp, int dir, struct mbuf **m)
+#else
+pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
+#endif
+{
+ /*
+ * IPv6 does not affected ip_len/ip_off byte order changes.
+ */
+ int chk;
+
+ chk = pf_test6(PF_IN, ifp, m);
+ if (chk && *m) {
+ m_freem(*m);
+ *m = NULL;
}
+ return chk;
+}
- case DIOCSETHOSTID: {
- u_int32_t *hostid = (u_int32_t *)addr;
+static int
+#if (__FreeBSD_version < 501108)
+pf_check6_out(void *ip, int hlen, struct ifnet *ifp, int dir, struct mbuf **m)
+#else
+pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
+#endif
+{
+ /*
+ * IPv6 does not affected ip_len/ip_off byte order changes.
+ */
+ int chk;
- if (*hostid == 0) {
- error = EINVAL;
- goto fail;
- }
- pf_status.hostid = *hostid;
- break;
+ /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
+ if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ in_delayed_cksum(*m);
+ (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
}
+ chk = pf_test6(PF_OUT, ifp, m);
+ if (chk && *m) {
+ m_freem(*m);
+ *m = NULL;
+ }
+ return chk;
+}
+#endif /* INET6 */
- case DIOCOSFPFLUSH:
- s = splsoftnet();
- pf_osfp_flush();
- splx(s);
- break;
+static int
+hook_pf(void)
+{
+#if (__FreeBSD_version >= 501108)
+ struct pfil_head *pfh_inet;
+#ifdef INET6
+ struct pfil_head *pfh_inet6;
+#endif
+#endif
+
+ PF_ASSERT(MA_NOTOWNED);
- case DIOCIGETIFACES: {
- struct pfioc_iface *io = (struct pfioc_iface *)addr;
+ if (pf_pfil_hooked)
+ return (0);
+
+#if (__FreeBSD_version < 501108)
+ /*
+ * XXX
+ * There is no easy way to get pfil header pointer with address
+ * family such as AF_INET, AF_INET6.
+ * Needs direct variable reference.
+ */
- if (io->pfiio_esize != sizeof(struct pfi_if)) {
- error = ENODEV;
- break;
- }
- error = pfi_get_ifaces(io->pfiio_name, io->pfiio_buffer,
- &io->pfiio_size, io->pfiio_flags);
- break;
+ pfil_add_hook(pf_check_in, PFIL_IN,
+ &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+ pfil_add_hook(pf_check_out, PFIL_OUT,
+ &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+#ifdef INET6
+ pfil_add_hook(pf_check6_in, PFIL_IN,
+ &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
+ pfil_add_hook(pf_check6_out, PFIL_OUT,
+ &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
+#endif
+#else /* __FreeBSD_version >= 501108 */
+ pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
+ if (pfh_inet == NULL)
+ return (ESRCH); /* XXX */
+ pfil_add_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
+ pfil_add_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
+#ifdef INET6
+ pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
+ if (pfh_inet6 == NULL) {
+ pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet);
+ pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet);
+ return (ESRCH); /* XXX */
+ }
+ pfil_add_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6);
+ pfil_add_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6);
+#endif
+#endif /* __FreeBSD_version >= 501108 */
+
+ pf_pfil_hooked = 1;
+ return (0);
+}
+
+static int
+dehook_pf(void)
+{
+#if (__FreeBSD_version >= 501108)
+ struct pfil_head *pfh_inet;
+#ifdef INET6
+ struct pfil_head *pfh_inet6;
+#endif
+#endif
+
+ PF_ASSERT(MA_NOTOWNED);
+
+ if (pf_pfil_hooked == 0)
+ return (0);
+
+#if (__FreeBSD_version < 501108)
+ pfil_remove_hook(pf_check_in, PFIL_IN,
+ &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+ pfil_remove_hook(pf_check_out, PFIL_OUT,
+ &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
+#ifdef INET6
+ pfil_remove_hook(pf_check6_in, PFIL_IN,
+ &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
+ pfil_remove_hook(pf_check6_out, PFIL_OUT,
+ &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
+#endif
+#else /* __FreeBSD_version >= 501108 */
+ pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
+ if (pfh_inet == NULL)
+ return (ESRCH); /* XXX */
+ pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet);
+ pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet);
+#ifdef INET6
+ pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
+ if (pfh_inet6 == NULL)
+ return (ESRCH); /* XXX */
+ pfil_remove_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet6);
+ pfil_remove_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet6);
+#endif
+#endif /* __FreeBSD_version >= 501108 */
+
+ pf_pfil_hooked = 0;
+ return (0);
+}
+
+static int
+pf_load(void)
+{
+ init_zone_var();
+ init_pf_mutex();
+ pf_dev = make_dev(&pf_cdevsw, 0, 0, 0, 0600, PF_NAME);
+ if (pfattach() < 0) {
+ destroy_dev(pf_dev);
+ destroy_pf_mutex();
+ return (ENOMEM);
}
+ return (0);
+}
- case DIOCICLRISTATS: {
- struct pfioc_iface *io = (struct pfioc_iface *)addr;
+static int
+pf_unload(void)
+{
+ int error = 0;
- error = pfi_clr_istats(io->pfiio_name, &io->pfiio_nzero,
- io->pfiio_flags);
+ PF_LOCK();
+ pf_status.running = 0;
+ PF_UNLOCK();
+ error = dehook_pf();
+ if (error) {
+ /*
+ * Should not happen!
+ * XXX Due to error code ESRCH, kldunload will show
+ * a message like 'No such process'.
+ */
+ printf("%s : pfil unregisteration fail\n", __FUNCTION__);
+ return error;
+ }
+ shutdown_pf();
+ cleanup_pf_zone();
+ pf_osfp_cleanup();
+ destroy_dev(pf_dev);
+ destroy_pf_mutex();
+ return error;
+}
+
+static int
+pf_modevent(module_t mod, int type, void *data)
+{
+ int error = 0;
+
+ switch(type) {
+ case MOD_LOAD:
+ error = pf_load();
break;
- }
+ case MOD_UNLOAD:
+ error = pf_unload();
+ break;
default:
- error = ENODEV;
+ error = EINVAL;
break;
}
-fail:
-
- return (error);
+ return error;
}
+
+static moduledata_t pf_mod = {
+ "pf",
+ pf_modevent,
+ 0
+};
+
+DECLARE_MODULE(pf, pf_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+MODULE_DEPEND(pf, pflog, PFLOG_MINVER, PFLOG_PREFVER, PFLOG_MAXVER);
+MODULE_DEPEND(pf, pfsync, PFSYNC_MINVER, PFSYNC_PREFVER, PFSYNC_MAXVER);
+MODULE_VERSION(pf, PF_MODVER);
+#endif /* __FreeBSD__ */
diff --git a/sys/contrib/pf/net/pf_norm.c b/sys/contrib/pf/net/pf_norm.c
index d2c6456..10f066e 100644
--- a/sys/contrib/pf/net/pf_norm.c
+++ b/sys/contrib/pf/net/pf_norm.c
@@ -1,4 +1,5 @@
-/* $OpenBSD: pf_norm.c,v 1.80 2004/03/09 21:44:41 mcbride Exp $ */
+/* $FreeBSD$ */
+/* $OpenBSD: pf_norm.c,v 1.75.2.1 2004/04/30 23:28:36 brad Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -25,7 +26,15 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifdef __FreeBSD__
+#include "opt_inet.h"
+#include "opt_inet6.h"
+#include "opt_random_ip_id.h" /* or ip_var does not export it */
+#include "opt_pf.h"
+#define NPFLOG DEV_PFLOG
+#else
#include "pflog.h"
+#endif
#include <sys/param.h>
#include <sys/systm.h>
@@ -35,9 +44,11 @@
#include <sys/socket.h>
#include <sys/kernel.h>
#include <sys/time.h>
+#ifndef __FreeBSD__
#include <sys/pool.h>
#include <dev/rndvar.h>
+#endif
#include <net/if.h>
#include <net/if_types.h>
#include <net/bpf.h>
@@ -60,6 +71,49 @@
#include <net/pfvar.h>
+#if defined(__FreeBSD__) && defined(INET6)
+/*
+ * XXX: This should go to netinet/ip6.h (KAME)
+ */
+/* IPv6 options: common part */
+struct ip6_opt {
+ u_int8_t ip6o_type;
+ u_int8_t ip6o_len;
+} __packed;
+
+/* Jumbo Payload Option */
+struct ip6_opt_jumbo {
+ u_int8_t ip6oj_type;
+ u_int8_t ip6oj_len;
+ u_int8_t ip6oj_jumbo_len[4];
+} __packed;
+
+/* NSAP Address Option */
+struct ip6_opt_nsap {
+ u_int8_t ip6on_type;
+ u_int8_t ip6on_len;
+ u_int8_t ip6on_src_nsap_len;
+ u_int8_t ip6on_dst_nsap_len;
+ /* followed by source NSAP */
+ /* followed by destination NSAP */
+} __packed;
+
+/* Tunnel Limit Option */
+struct ip6_opt_tunnel {
+ u_int8_t ip6ot_type;
+ u_int8_t ip6ot_len;
+ u_int8_t ip6ot_encap_limit;
+} __packed;
+
+/* Router Alert Option */
+struct ip6_opt_router {
+ u_int8_t ip6or_type;
+ u_int8_t ip6or_len;
+ u_int8_t ip6or_value[2];
+} __packed;
+#endif /* __FreeBSD__ && INET6 */
+
+#ifndef __FreeBSD__
struct pf_frent {
LIST_ENTRY(pf_frent) fr_next;
struct ip *fr_ip;
@@ -71,12 +125,14 @@ struct pf_frcache {
uint16_t fr_off;
uint16_t fr_end;
};
+#endif
#define PFFRAG_SEENLAST 0x0001 /* Seen the last fragment for this */
#define PFFRAG_NOBUFFER 0x0002 /* Non-buffering fragment cache */
#define PFFRAG_DROP 0x0004 /* Drop all fragments */
#define BUFFER_FRAGMENTS(fr) (!((fr)->fr_flags & PFFRAG_NOBUFFER))
+#ifndef __FreeBSD__
struct pf_fragment {
RB_ENTRY(pf_fragment) fr_entry;
TAILQ_ENTRY(pf_fragment) frag_next;
@@ -94,6 +150,7 @@ struct pf_fragment {
LIST_HEAD(pf_cacheq, pf_frcache) fru_cache; /* non-buf */
} fr_u;
};
+#endif
TAILQ_HEAD(pf_fragqueue, pf_fragment) pf_fragqueue;
TAILQ_HEAD(pf_cachequeue, pf_fragment) pf_cachequeue;
@@ -105,6 +162,9 @@ RB_PROTOTYPE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
RB_GENERATE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
/* Private prototypes */
+#ifndef RANDOM_IP_ID
+extern u_int16_t ip_randomid(void);
+#endif
void pf_ip2key(struct pf_fragment *, struct ip *);
void pf_remove_fragment(struct pf_fragment *);
void pf_flush_fragments(void);
@@ -122,13 +182,28 @@ int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *,
{ printf("%s: ", __func__); printf x ;}
/* Globals */
+#ifdef __FreeBSD__
+uma_zone_t pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
+uma_zone_t pf_state_scrub_pl;
+#else
struct pool pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
struct pool pf_state_scrub_pl;
+#endif
int pf_nfrents, pf_ncache;
void
pf_normalize_init(void)
{
+#ifdef __FreeBSD__
+ /*
+ * XXX
+ * No high water mark support(It's hint not hard limit).
+ * uma_zone_set_max(pf_frag_pl, PFFRAG_FRAG_HIWAT);
+ */
+ uma_zone_set_max(pf_frent_pl, PFFRAG_FRENT_HIWAT);
+ uma_zone_set_max(pf_cache_pl, PFFRAG_FRCACHE_HIWAT);
+ uma_zone_set_max(pf_cent_pl, PFFRAG_FRCENT_HIWAT);
+#else
pool_init(&pf_frent_pl, sizeof(struct pf_frent), 0, 0, 0, "pffrent",
NULL);
pool_init(&pf_frag_pl, sizeof(struct pf_fragment), 0, 0, 0, "pffrag",
@@ -144,12 +219,17 @@ pf_normalize_init(void)
pool_sethardlimit(&pf_frent_pl, PFFRAG_FRENT_HIWAT, NULL, 0);
pool_sethardlimit(&pf_cache_pl, PFFRAG_FRCACHE_HIWAT, NULL, 0);
pool_sethardlimit(&pf_cent_pl, PFFRAG_FRCENT_HIWAT, NULL, 0);
+#endif
TAILQ_INIT(&pf_fragqueue);
TAILQ_INIT(&pf_cachequeue);
}
+#ifdef __FreeBSD__
+static int
+#else
static __inline int
+#endif
pf_frag_compare(struct pf_fragment *a, struct pf_fragment *b)
{
int diff;
@@ -173,11 +253,21 @@ void
pf_purge_expired_fragments(void)
{
struct pf_fragment *frag;
+#ifdef __FreeBSD__
+ u_int32_t expire = time_second -
+ pf_default_rule.timeout[PFTM_FRAG];
+#else
u_int32_t expire = time.tv_sec -
pf_default_rule.timeout[PFTM_FRAG];
+#endif
while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) {
+#ifdef __FreeBSD__
+ KASSERT((BUFFER_FRAGMENTS(frag)),
+ ("BUFFER_FRAGMENTS(frag) == 0: %s", __FUNCTION__));
+#else
KASSERT(BUFFER_FRAGMENTS(frag));
+#endif
if (frag->fr_timeout > expire)
break;
@@ -186,14 +276,26 @@ pf_purge_expired_fragments(void)
}
while ((frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue)) != NULL) {
+#ifdef __FreeBSD__
+ KASSERT((!BUFFER_FRAGMENTS(frag)),
+ ("BUFFER_FRAGMENTS(frag) != 0: %s", __FUNCTION__));
+#else
KASSERT(!BUFFER_FRAGMENTS(frag));
+#endif
if (frag->fr_timeout > expire)
break;
DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag));
pf_free_fragment(frag);
+#ifdef __FreeBSD__
+ KASSERT((TAILQ_EMPTY(&pf_cachequeue) ||
+ TAILQ_LAST(&pf_cachequeue, pf_cachequeue) != frag),
+ ("!(TAILQ_EMPTY() || TAILQ_LAST() == farg): %s",
+ __FUNCTION__));
+#else
KASSERT(TAILQ_EMPTY(&pf_cachequeue) ||
TAILQ_LAST(&pf_cachequeue, pf_cachequeue) != frag);
+#endif
}
}
@@ -252,9 +354,17 @@ pf_free_fragment(struct pf_fragment *frag)
frcache = LIST_FIRST(&frag->fr_cache)) {
LIST_REMOVE(frcache, fr_next);
+#ifdef __FreeBSD__
+ KASSERT((LIST_EMPTY(&frag->fr_cache) ||
+ LIST_FIRST(&frag->fr_cache)->fr_off >
+ frcache->fr_end),
+ ("! (LIST_EMPTY() || LIST_FIRST()->fr_off >"
+ " frcache->fr_end): %s", __FUNCTION__));
+#else
KASSERT(LIST_EMPTY(&frag->fr_cache) ||
LIST_FIRST(&frag->fr_cache)->fr_off >
frcache->fr_end);
+#endif
pool_put(&pf_cent_pl, frcache);
pf_ncache--;
@@ -284,7 +394,11 @@ pf_find_fragment(struct ip *ip, struct pf_frag_tree *tree)
frag = RB_FIND(pf_frag_tree, tree, &key);
if (frag != NULL) {
/* XXX Are we sure we want to update the timeout? */
+#ifdef __FreeBSD__
+ frag->fr_timeout = time_second;
+#else
frag->fr_timeout = time.tv_sec;
+#endif
if (BUFFER_FRAGMENTS(frag)) {
TAILQ_REMOVE(&pf_fragqueue, frag, frag_next);
TAILQ_INSERT_HEAD(&pf_fragqueue, frag, frag_next);
@@ -327,7 +441,12 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
u_int16_t ip_len = ntohs(ip->ip_len) - ip->ip_hl * 4;
u_int16_t max = ip_len + off;
+#ifdef __FreeBSD__
+ KASSERT((*frag == NULL || BUFFER_FRAGMENTS(*frag)),
+ ("! (*frag == NULL || BUFFER_FRAGMENTS(*frag)): %s", __FUNCTION__));
+#else
KASSERT(*frag == NULL || BUFFER_FRAGMENTS(*frag));
+#endif
/* Strip off ip header */
m->m_data += hlen;
@@ -349,7 +468,11 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
(*frag)->fr_dst = frent->fr_ip->ip_dst;
(*frag)->fr_p = frent->fr_ip->ip_p;
(*frag)->fr_id = frent->fr_ip->ip_id;
+#ifdef __FreeBSD__
+ (*frag)->fr_timeout = time_second;
+#else
(*frag)->fr_timeout = time.tv_sec;
+#endif
LIST_INIT(&(*frag)->fr_queue);
RB_INSERT(pf_frag_tree, &pf_frag_tree, *frag);
@@ -370,11 +493,16 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
frep = frea;
}
+#ifdef __FreeBSD__
+ KASSERT((frep != NULL || frea != NULL),
+ ("!(frep != NULL || frea != NULL): %s", __FUNCTION__));;
+#else
KASSERT(frep != NULL || frea != NULL);
+#endif
if (frep != NULL &&
FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) - frep->fr_ip->ip_hl *
- 4 > off)
+ 4 > off)
{
u_int16_t precut;
@@ -455,7 +583,11 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
/* We have all the data */
frent = LIST_FIRST(&(*frag)->fr_queue);
+#ifdef __FreeBSD__
+ KASSERT((frent != NULL), ("frent == NULL: %s", __FUNCTION__));
+#else
KASSERT(frent != NULL);
+#endif
if ((frent->fr_ip->ip_hl << 2) + off > IP_MAXPACKET) {
DPFPRINTF(("drop: too big: %d\n", off));
pf_free_fragment(*frag);
@@ -524,7 +656,12 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
u_int16_t max = ip_len + off;
int hosed = 0;
+#ifdef __FreeBSD__
+ KASSERT((*frag == NULL || !BUFFER_FRAGMENTS(*frag)),
+ ("!(*frag == NULL || !BUFFER_FRAGMENTS(*frag)): %s", __FUNCTION__));
+#else
KASSERT(*frag == NULL || !BUFFER_FRAGMENTS(*frag));
+#endif
/* Create a new range queue for this packet */
if (*frag == NULL) {
@@ -551,7 +688,11 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
(*frag)->fr_dst = h->ip_dst;
(*frag)->fr_p = h->ip_p;
(*frag)->fr_id = h->ip_id;
+#ifdef __FreeBSD__
+ (*frag)->fr_timeout = time_second;
+#else
(*frag)->fr_timeout = time.tv_sec;
+#endif
cur->fr_off = off;
cur->fr_end = max;
@@ -577,7 +718,12 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
frp = fra;
}
+#ifdef __FreeBSD__
+ KASSERT((frp != NULL || fra != NULL),
+ ("!(frp != NULL || fra != NULL): %s", __FUNCTION__));
+#else
KASSERT(frp != NULL || fra != NULL);
+#endif
if (frp != NULL) {
int precut;
@@ -619,10 +765,23 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
* than this mbuf magic. For my next trick,
* I'll pull a rabbit out of my laptop.
*/
+#ifdef __FreeBSD__
+ *m0 = m_dup(m, M_DONTWAIT);
+ /* From KAME Project : We have missed this! */
+ m_adj(*m0, (h->ip_hl << 2) -
+ (*m0)->m_pkthdr.len);
+#else
*m0 = m_copym2(m, 0, h->ip_hl << 2, M_NOWAIT);
+#endif
if (*m0 == NULL)
goto no_mem;
+#ifdef __FreeBSD__
+ KASSERT(((*m0)->m_next == NULL),
+ ("(*m0)->m_next != NULL: %s",
+ __FUNCTION__));
+#else
KASSERT((*m0)->m_next == NULL);
+#endif
m_adj(m, precut + (h->ip_hl << 2));
m_cat(*m0, m);
m = *m0;
@@ -637,11 +796,14 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
h = mtod(m, struct ip *);
-
- KASSERT((int)m->m_len ==
- ntohs(h->ip_len) - precut);
- h->ip_off = htons(ntohs(h->ip_off) +
- (precut >> 3));
+#ifdef __FreeBSD__
+ KASSERT(((int)m->m_len == ntohs(h->ip_len) - precut),
+ ("m->m_len != ntohs(h->ip_len) - precut: %s",
+ __FUNCTION__));
+#else
+ KASSERT((int)m->m_len == ntohs(h->ip_len) - precut);
+#endif
+ h->ip_off = htons(ntohs(h->ip_off) + (precut >> 3));
h->ip_len = htons(ntohs(h->ip_len) - precut);
} else {
hosed++;
@@ -695,8 +857,13 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
m->m_pkthdr.len = plen;
}
h = mtod(m, struct ip *);
- KASSERT((int)m->m_len ==
- ntohs(h->ip_len) - aftercut);
+#ifdef __FreeBSD__
+ KASSERT(((int)m->m_len == ntohs(h->ip_len) - aftercut),
+ ("m->m_len != ntohs(h->ip_len) - aftercut: %s",
+ __FUNCTION__));
+#else
+ KASSERT((int)m->m_len == ntohs(h->ip_len) - aftercut);
+#endif
h->ip_len = htons(ntohs(h->ip_len) - aftercut);
} else {
hosed++;
@@ -734,7 +901,12 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
} else if (frp && fra->fr_off <= frp->fr_end) {
/* Need to merge in a modified 'frp' */
+#ifdef __FreeBSD__
+ KASSERT((cur == NULL), ("cur != NULL: %s",
+ __FUNCTION__));
+#else
KASSERT(cur == NULL);
+#endif
DPFPRINTF(("fragcache[%d]: adjacent(merge "
"%d-%d) %d-%d (%d-%d)\n",
h->ip_id, frp->fr_off, frp->fr_end, off,
@@ -810,7 +982,7 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
}
int
-pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
+pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
{
struct mbuf *m = *m0;
struct pf_rule *r;
@@ -827,8 +999,7 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
while (r != NULL) {
r->evaluations++;
- if (r->kif != NULL &&
- (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+ if (r->ifp != NULL && r->ifp != ifp)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -991,13 +1162,13 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
no_mem:
REASON_SET(reason, PFRES_MEMORY);
if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL);
return (PF_DROP);
drop:
REASON_SET(reason, PFRES_NORM);
if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL);
return (PF_DROP);
bad:
@@ -1009,15 +1180,14 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
REASON_SET(reason, PFRES_FRAG);
if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL);
return (PF_DROP);
}
#ifdef INET6
int
-pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
- u_short *reason)
+pf_normalize_ip6(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
{
struct mbuf *m = *m0;
struct pf_rule *r;
@@ -1037,8 +1207,7 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
while (r != NULL) {
r->evaluations++;
- if (r->kif != NULL &&
- (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+ if (r->ifp != NULL && r->ifp != ifp)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -1172,25 +1341,25 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
shortpkt:
REASON_SET(reason, PFRES_SHORT);
if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
return (PF_DROP);
drop:
REASON_SET(reason, PFRES_NORM);
if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
return (PF_DROP);
badfrag:
REASON_SET(reason, PFRES_FRAG);
if (r != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
+ PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
return (PF_DROP);
}
#endif
int
-pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
+pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff,
int off, void *h, struct pf_pdesc *pd)
{
struct pf_rule *r, *rm = NULL;
@@ -1203,8 +1372,7 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
while (r != NULL) {
r->evaluations++;
- if (r->kif != NULL &&
- (r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
+ if (r->ifp != NULL && r->ifp != ifp)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@@ -1290,14 +1458,14 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
/* copy back packet headers if we sanitized */
if (rewrite)
- m_copyback(m, off, sizeof(*th), th);
+ m_copyback(m, off, sizeof(*th), (caddr_t)th);
return (PF_PASS);
tcp_drop:
REASON_SET(&reason, PFRES_NORM);
if (rm != NULL && r->log)
- PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, NULL, NULL);
+ PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, NULL, NULL);
return (PF_DROP);
}
@@ -1308,7 +1476,12 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
u_int8_t hdr[60];
u_int8_t *opt;
+#ifdef __FreeBSD__
+ KASSERT((src->scrub == NULL),
+ ("pf_normalize_tcp_init: src->scrub != NULL"));
+#else
KASSERT(src->scrub == NULL);
+#endif
src->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT);
if (src->scrub == NULL)
@@ -1338,7 +1511,7 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
* the connections. They must all set an enabled bit in pfss_flags
*/
if ((th->th_flags & TH_SYN) == 0)
- return (0);
+ return 0;
if (th->th_off > (sizeof(struct tcphdr) >> 2) && src->scrub &&
@@ -1362,8 +1535,8 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
}
/* FALLTHROUGH */
default:
- hlen -= opt[1];
- opt += opt[1];
+ hlen -= MAX(opt[1], 2);
+ opt += MAX(opt[1], 2);
break;
}
}
@@ -1392,7 +1565,12 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
u_int8_t *opt;
int copyback = 0;
+#ifdef __FreeBSD__
+ KASSERT((src->scrub || dst->scrub),
+ ("pf_normalize_tcp_statefull: src->scrub && dst->scrub!"));
+#else
KASSERT(src->scrub || dst->scrub);
+#endif
/*
* Enforce the minimum TTL seen for this connection. Negate a common
@@ -1413,7 +1591,7 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
#endif /* INET */
#ifdef INET6
case AF_INET6: {
- if (src->scrub) {
+ if (dst->scrub) {
struct ip6_hdr *h = mtod(m, struct ip6_hdr *);
if (h->ip6_hlim > src->scrub->pfss_ttl)
src->scrub->pfss_ttl = h->ip6_hlim;
@@ -1457,13 +1635,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
&th->th_sum, ts_value, 0);
copyback = 1;
}
-
- /* Modulate TS reply iff valid (!0) */
- memcpy(&ts_value, &opt[6],
- sizeof(u_int32_t));
- if (ts_value && dst->scrub &&
+ if (dst->scrub &&
(dst->scrub->pfss_flags &
PFSS_TIMESTAMP)) {
+ memcpy(&ts_value, &opt[6],
+ sizeof(u_int32_t));
ts_value = htonl(ntohl(ts_value)
- dst->scrub->pfss_ts_mod);
pf_change_a(&opt[6],
@@ -1473,8 +1649,8 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
}
/* FALLTHROUGH */
default:
- hlen -= opt[1];
- opt += opt[1];
+ hlen -= MAX(opt[1], 2);
+ opt += MAX(opt[1], 2);
break;
}
}
diff --git a/sys/contrib/pf/net/pf_osfp.c b/sys/contrib/pf/net/pf_osfp.c
index 98cc01a..8687cb0 100644
--- a/sys/contrib/pf/net/pf_osfp.c
+++ b/sys/contrib/pf/net/pf_osfp.c
@@ -1,4 +1,5 @@
-/* $OpenBSD: pf_osfp.c,v 1.9 2004/01/04 20:08:42 pvalchev Exp $ */
+/* $FreeBSD$ */
+/* $OpenBSD: pf_osfp.c,v 1.3 2003/08/27 18:23:36 frantzen Exp $ */
/*
* Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
@@ -36,12 +37,15 @@
#include <netinet/ip6.h>
#endif /* INET6 */
-
#ifdef _KERNEL
# define DPFPRINTF(format, x...) \
if (pf_status.debug >= PF_DEBUG_NOISY) \
printf(format , ##x)
+#ifdef __FreeBSD__
+typedef uma_zone_t pool_t;
+#else
typedef struct pool pool_t;
+#endif
#else
/* Userland equivalents so we can lend code to tcpdump et al. */
@@ -50,14 +54,17 @@ typedef struct pool pool_t;
# include <errno.h>
# include <stdio.h>
# include <stdlib.h>
-# include <string.h>
# define pool_t int
# define pool_get(pool, flags) malloc(*(pool))
# define pool_put(pool, item) free(item)
# define pool_init(pool, size, a, ao, f, m, p) (*(pool)) = (size)
+# ifdef __FreeBSD__
+# define NTOHS(x) (x) = ntohs((u_int16_t)(x))
+# endif
+
# ifdef PFDEBUG
-# include <sys/stdarg.h>
+# include <stdarg.h>
# define DPFPRINTF(format, x...) fprintf(stderr, format , ##x)
# else
# define DPFPRINTF(format, x...) ((void)0)
@@ -229,15 +236,46 @@ pf_osfp_match(struct pf_osfp_enlist *list, pf_osfp_t os)
}
/* Initialize the OS fingerprint system */
+#ifdef __FreeBSD__
+int
+#else
void
+#endif
pf_osfp_initialize(void)
{
+#if defined(__FreeBSD__) && defined(_KERNEL)
+ int error = ENOMEM;
+
+ do {
+ pf_osfp_entry_pl = pf_osfp_pl = NULL;
+ UMA_CREATE(pf_osfp_entry_pl, struct pf_osfp_entry, "pfospfen");
+ UMA_CREATE(pf_osfp_pl, struct pf_os_fingerprint, "pfosfp");
+ error = 0;
+ } while(0);
+#else
pool_init(&pf_osfp_entry_pl, sizeof(struct pf_osfp_entry), 0, 0, 0,
"pfosfpen", NULL);
pool_init(&pf_osfp_pl, sizeof(struct pf_os_fingerprint), 0, 0, 0,
"pfosfp", NULL);
+#endif
SLIST_INIT(&pf_osfp_list);
+#ifdef __FreeBSD__
+#ifdef _KERNEL
+ return (error);
+#else
+ return (0);
+#endif
+#endif
+}
+
+#if defined(__FreeBSD__) && (_KERNEL)
+void
+pf_osfp_cleanup(void)
+{
+ UMA_DESTROY(pf_osfp_entry_pl);
+ UMA_DESTROY(pf_osfp_pl);
}
+#endif
/* Flush the fingerprint list */
void
diff --git a/sys/contrib/pf/net/pf_table.c b/sys/contrib/pf/net/pf_table.c
index 42d4cee..fb10915 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.47 2004/03/09 21:44:41 mcbride Exp $ */
+/* $FreeBSD$ */
+/* $OpenBSD: pf_table.c,v 1.41 2003/08/22 15:19:23 henning 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,16 +61,6 @@
return (EINVAL); \
} while (0)
-#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))
-
#define FILLIN_SIN(sin, addr) \
do { \
(sin).sin_len = sizeof(sin); \
@@ -81,8 +83,8 @@
} while (0)
#define SUNION2PF(su, af) (((af)==AF_INET) ? \
- (struct pf_addr *)&(su)->sin.sin_addr : \
- (struct pf_addr *)&(su)->sin6.sin6_addr)
+ (struct pf_addr *)&(su)->sin.sin_addr : \
+ (struct pf_addr *)&(su)->sin6.sin6_addr)
#define AF_BITS(af) (((af)==AF_INET)?32:128)
#define ADDR_NETWORK(ad) ((ad)->pfra_net < AF_BITS((ad)->pfra_af))
@@ -101,33 +103,34 @@ struct pfr_walktree {
PFRW_ENQUEUE,
PFRW_GET_ADDRS,
PFRW_GET_ASTATS,
- PFRW_POOL_GET,
- PFRW_DYNADDR_UPDATE
+ PFRW_POOL_GET
} pfrw_op;
union {
struct pfr_addr *pfrw1_addr;
struct pfr_astats *pfrw1_astats;
struct pfr_kentryworkq *pfrw1_workq;
struct pfr_kentry *pfrw1_kentry;
- struct pfi_dynaddr *pfrw1_dyn;
} pfrw_1;
int pfrw_free;
- int pfrw_flags;
};
#define pfrw_addr pfrw_1.pfrw1_addr
#define pfrw_astats pfrw_1.pfrw1_astats
#define pfrw_workq pfrw_1.pfrw1_workq
#define pfrw_kentry pfrw_1.pfrw1_kentry
-#define pfrw_dyn pfrw_1.pfrw1_dyn
#define pfrw_cnt pfrw_free
#define senderr(e) do { rv = (e); goto _bad; } while (0)
+#ifdef __FreeBSD__
+uma_zone_t pfr_ktable_pl;
+uma_zone_t pfr_kentry_pl;
+#else
struct pool pfr_ktable_pl;
struct pool pfr_kentry_pl;
+#endif
struct sockaddr_in pfr_sin;
struct sockaddr_in6 pfr_sin6;
-union sockaddr_union pfr_mask;
+union sockaddr_union pfr_mask;
struct pf_addr pfr_ffaddr;
void pfr_copyout_addr(struct pfr_addr *,
@@ -147,14 +150,14 @@ void pfr_remove_kentries(struct pfr_ktable *,
struct pfr_kentryworkq *);
void pfr_clstats_kentries(struct pfr_kentryworkq *, long,
int);
-void pfr_reset_feedback(struct pfr_addr *, int, int);
+void pfr_reset_feedback(struct pfr_addr *, int);
void pfr_prepare_network(union sockaddr_union *, int, int);
int pfr_route_kentry(struct pfr_ktable *,
struct pfr_kentry *);
int pfr_unroute_kentry(struct pfr_ktable *,
struct pfr_kentry *);
int pfr_walktree(struct radix_node *, void *);
-int pfr_validate_table(struct pfr_table *, int, int);
+int pfr_validate_table(struct pfr_table *, int);
void pfr_commit_ktable(struct pfr_ktable *, long);
void pfr_insert_ktables(struct pfr_ktableworkq *);
void pfr_insert_ktable(struct pfr_ktable *);
@@ -169,12 +172,12 @@ void pfr_destroy_ktable(struct pfr_ktable *, int);
int pfr_ktable_compare(struct pfr_ktable *,
struct pfr_ktable *);
struct pfr_ktable *pfr_lookup_table(struct pfr_table *);
-void pfr_clean_node_mask(struct pfr_ktable *,
+void pfr_clean_node_mask(struct pfr_ktable *,
struct pfr_kentryworkq *);
int pfr_table_count(struct pfr_table *, int);
int pfr_skip_table(struct pfr_table *,
struct pfr_ktable *, int);
-struct pfr_kentry *pfr_kentry_byidx(struct pfr_ktable *, int, int);
+struct pfr_kentry *pfr_kentry_byidx(struct pfr_ktable *, int, int);
RB_PROTOTYPE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
RB_GENERATE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
@@ -186,10 +189,12 @@ int pfr_ktable_cnt;
void
pfr_initialize(void)
{
+#ifndef __FreeBSD__
pool_init(&pfr_ktable_pl, sizeof(struct pfr_ktable), 0, 0, 0,
"pfrktable", NULL);
pool_init(&pfr_kentry_pl, sizeof(struct pfr_kentry), 0, 0, 0,
"pfrkentry", NULL);
+#endif
pfr_sin.sin_len = sizeof(pfr_sin);
pfr_sin.sin_family = AF_INET;
@@ -207,7 +212,7 @@ pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
int s;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
- if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
+ if (pfr_validate_table(tbl, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -240,10 +245,18 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfr_kentry *p, *q;
struct pfr_addr ad;
int i, rv, s, xadd = 0;
+#ifdef __FreeBSD__
+ int ec;
+ /*
+ * XXX Is it OK under LP64 environments?
+ */
+ long tzero = (long)time_second;
+#else
long tzero = time.tv_sec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
- if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
+ if (pfr_validate_table(tbl, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -255,8 +268,14 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (ENOMEM);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
- if (COPYIN(addr+i, &ad, sizeof(ad)))
+#ifdef __FreeBSD__
+ PF_COPYIN(addr+i, &ad, sizeof(ad), ec);
+ if (ec)
+ senderr(EFAULT);
+#else
+ if (copyin(addr+i, &ad, sizeof(ad)))
senderr(EFAULT);
+#endif
if (pfr_validate_addr(&ad))
senderr(EINVAL);
p = pfr_lookup_addr(kt, &ad, 1);
@@ -283,9 +302,17 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
xadd++;
}
}
+#ifdef __FreeBSD__
+ if (flags & PFR_FLAG_FEEDBACK) {
+ PF_COPYOUT(&ad, addr+i, sizeof(ad), ec);
+ if (ec)
+ senderr(EFAULT);
+ }
+#else
if (flags & PFR_FLAG_FEEDBACK)
- if (COPYOUT(&ad, addr+i, sizeof(ad)))
+ if (copyout(&ad, addr+i, sizeof(ad)))
senderr(EFAULT);
+#endif
}
pfr_clean_node_mask(tmpkt, &workq);
if (!(flags & PFR_FLAG_DUMMY)) {
@@ -304,7 +331,7 @@ _bad:
pfr_clean_node_mask(tmpkt, &workq);
pfr_destroy_kentries(&workq);
if (flags & PFR_FLAG_FEEDBACK)
- pfr_reset_feedback(addr, size, flags);
+ pfr_reset_feedback(addr, size);
pfr_destroy_ktable(tmpkt, 0);
return (rv);
}
@@ -318,9 +345,12 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfr_kentry *p;
struct pfr_addr ad;
int i, rv, s, xdel = 0;
+#ifdef __FreeBSD__
+ int ec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
- if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
+ if (pfr_validate_table(tbl, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -330,8 +360,14 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
pfr_mark_addrs(kt);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
- if (COPYIN(addr+i, &ad, sizeof(ad)))
+#ifdef __FreeBSD__
+ PF_COPYIN(addr+i, &ad, sizeof(ad), ec);
+ if (ec)
+ senderr(EFAULT);
+#else
+ if (copyin(addr+i, &ad, sizeof(ad)))
senderr(EFAULT);
+#endif
if (pfr_validate_addr(&ad))
senderr(EINVAL);
p = pfr_lookup_addr(kt, &ad, 1);
@@ -351,9 +387,17 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
xdel++;
}
+#ifdef __FreeBSD__
+ if (flags & PFR_FLAG_FEEDBACK) {
+ PF_COPYOUT(&ad, addr+i, sizeof(ad), ec);
+ if (ec)
+ senderr(EFAULT);
+ }
+#else
if (flags & PFR_FLAG_FEEDBACK)
- if (COPYOUT(&ad, addr+i, sizeof(ad)))
+ if (copyout(&ad, addr+i, sizeof(ad)))
senderr(EFAULT);
+#endif
}
if (!(flags & PFR_FLAG_DUMMY)) {
if (flags & PFR_FLAG_ATOMIC)
@@ -367,7 +411,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (0);
_bad:
if (flags & PFR_FLAG_FEEDBACK)
- pfr_reset_feedback(addr, size, flags);
+ pfr_reset_feedback(addr, size);
return (rv);
}
@@ -380,10 +424,18 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfr_kentry *p, *q;
struct pfr_addr ad;
int i, rv, s, xadd = 0, xdel = 0, xchange = 0;
+#ifdef __FreeBSD__
+ int ec;
+ /*
+ * XXX Is it OK under LP64 environments?
+ */
+ long tzero = (long)time_second;
+#else
long tzero = time.tv_sec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
- if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
+ if (pfr_validate_table(tbl, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -398,8 +450,14 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
SLIST_INIT(&delq);
SLIST_INIT(&changeq);
for (i = 0; i < size; i++) {
- if (COPYIN(addr+i, &ad, sizeof(ad)))
+#ifdef __FreeBSD__
+ PF_COPYIN(addr+i, &ad, sizeof(ad), ec);
+ if (ec)
senderr(EFAULT);
+#else
+ if (copyin(addr+i, &ad, sizeof(ad)))
+ senderr(EFAULT);
+#endif
if (pfr_validate_addr(&ad))
senderr(EINVAL);
ad.pfra_fback = PFR_FB_NONE;
@@ -434,9 +492,17 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
}
}
_skip:
+#ifdef __FreeBSD__
+ if (flags & PFR_FLAG_FEEDBACK) {
+ PF_COPYOUT(&ad, addr+i, sizeof(ad), ec);
+ if (ec)
+ senderr(EFAULT);
+ }
+#else
if (flags & PFR_FLAG_FEEDBACK)
- if (COPYOUT(&ad, addr+i, sizeof(ad)))
+ if (copyout(&ad, addr+i, sizeof(ad)))
senderr(EFAULT);
+#endif
}
pfr_enqueue_addrs(kt, &delq, &xdel, ENQUEUE_UNMARKED_ONLY);
if ((flags & PFR_FLAG_FEEDBACK) && *size2) {
@@ -448,8 +514,14 @@ _skip:
SLIST_FOREACH(p, &delq, pfrke_workq) {
pfr_copyout_addr(&ad, p);
ad.pfra_fback = PFR_FB_DELETED;
- if (COPYOUT(&ad, addr+size+i, sizeof(ad)))
+#ifdef __FreeBSD__
+ PF_COPYOUT(&ad, addr+size+i, sizeof(ad), ec);
+ if (ec)
+ senderr(EFAULT);
+#else
+ if (copyout(&ad, addr+size+i, sizeof(ad)))
senderr(EFAULT);
+#endif
i++;
}
}
@@ -470,7 +542,7 @@ _skip:
*ndel = xdel;
if (nchange != NULL)
*nchange = xchange;
- if ((flags & PFR_FLAG_FEEDBACK) && size2)
+ if ((flags & PFR_FLAG_FEEDBACK) && *size2)
*size2 = size+xdel;
pfr_destroy_ktable(tmpkt, 0);
return (0);
@@ -478,7 +550,7 @@ _bad:
pfr_clean_node_mask(tmpkt, &addq);
pfr_destroy_kentries(&addq);
if (flags & PFR_FLAG_FEEDBACK)
- pfr_reset_feedback(addr, size, flags);
+ pfr_reset_feedback(addr, size);
pfr_destroy_ktable(tmpkt, 0);
return (rv);
}
@@ -491,17 +563,26 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfr_kentry *p;
struct pfr_addr ad;
int i, xmatch = 0;
+#ifdef __FreeBSD__
+ int ec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_REPLACE);
- if (pfr_validate_table(tbl, 0, 0))
+ if (pfr_validate_table(tbl, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
return (ESRCH);
for (i = 0; i < size; i++) {
- if (COPYIN(addr+i, &ad, sizeof(ad)))
+#ifdef __FreeBSD__
+ PF_COPYIN(addr+i, &ad, sizeof(ad), ec);
+ if (ec)
+ return (EFAULT);
+#else
+ if (copyin(addr+i, &ad, sizeof(ad)))
return (EFAULT);
+#endif
if (pfr_validate_addr(&ad))
return (EINVAL);
if (ADDR_NETWORK(&ad))
@@ -513,8 +594,14 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
(p->pfrke_not ? PFR_FB_NOTMATCH : PFR_FB_MATCH);
if (p != NULL && !p->pfrke_not)
xmatch++;
- if (COPYOUT(&ad, addr+i, sizeof(ad)))
+#ifdef __FreeBSD__
+ PF_COPYOUT(&ad, addr+i, sizeof(ad), ec);
+ if (ec)
return (EFAULT);
+#else
+ if (copyout(&ad, addr+i, sizeof(ad)))
+ return (EFAULT);
+#endif
}
if (nmatch != NULL)
*nmatch = xmatch;
@@ -530,7 +617,7 @@ pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
int rv;
ACCEPT_FLAGS(0);
- if (pfr_validate_table(tbl, 0, 0))
+ if (pfr_validate_table(tbl, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -544,10 +631,18 @@ pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
w.pfrw_op = PFRW_GET_ADDRS;
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);
@@ -568,10 +663,17 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
struct pfr_walktree w;
struct pfr_kentryworkq workq;
int rv, s;
+#ifdef __FreeBSD__
+ /*
+ * XXX Is it OK under LP64 environments?
+ */
+ long tzero = (long)time_second;
+#else
long tzero = time.tv_sec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC); /* XXX PFR_FLAG_CLSTATS disabled */
- if (pfr_validate_table(tbl, 0, 0))
+ if (pfr_validate_table(tbl, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -585,12 +687,20 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
w.pfrw_op = PFRW_GET_ASTATS;
w.pfrw_astats = addr;
w.pfrw_free = kt->pfrkt_cnt;
- 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);
@@ -618,25 +728,40 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfr_kentry *p;
struct pfr_addr ad;
int i, rv, s, xzero = 0;
+#ifdef __FreeBSD__
+ int ec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
- if (pfr_validate_table(tbl, 0, 0))
+ if (pfr_validate_table(tbl, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
return (ESRCH);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
- if (COPYIN(addr+i, &ad, sizeof(ad)))
+#ifdef __FreeBSD__
+ PF_COPYIN(addr+i, &ad, sizeof(ad), ec);
+ if (ec)
+ senderr(EFAULT);
+#else
+ if (copyin(addr+i, &ad, sizeof(ad)))
senderr(EFAULT);
+#endif
if (pfr_validate_addr(&ad))
senderr(EINVAL);
p = pfr_lookup_addr(kt, &ad, 1);
if (flags & PFR_FLAG_FEEDBACK) {
ad.pfra_fback = (p != NULL) ?
PFR_FB_CLEARED : PFR_FB_NONE;
- if (COPYOUT(&ad, addr+i, sizeof(ad)))
+#ifdef __FreeBSD__
+ PF_COPYOUT(&ad, addr+i, sizeof(ad), ec);
+ if (ec)
+ senderr(EFAULT);
+#else
+ if (copyout(&ad, addr+i, sizeof(ad)))
senderr(EFAULT);
+#endif
}
if (p != NULL) {
SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
@@ -656,7 +781,7 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (0);
_bad:
if (flags & PFR_FLAG_FEEDBACK)
- pfr_reset_feedback(addr, size, flags);
+ pfr_reset_feedback(addr, size);
return (rv);
}
@@ -701,10 +826,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;
@@ -717,9 +852,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");
}
@@ -743,7 +886,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;
@@ -833,10 +982,10 @@ void
pfr_clean_node_mask(struct pfr_ktable *kt,
struct pfr_kentryworkq *workq)
{
- struct pfr_kentry *p;
+ struct pfr_kentry *p;
- SLIST_FOREACH(p, workq, pfrke_workq)
- pfr_unroute_kentry(kt, p);
+ SLIST_FOREACH(p, workq, pfrke_workq)
+ pfr_unroute_kentry(kt, p);
}
void
@@ -857,17 +1006,32 @@ pfr_clstats_kentries(struct pfr_kentryworkq *workq, long tzero, int negchange)
}
void
-pfr_reset_feedback(struct pfr_addr *addr, int size, int flags)
+pfr_reset_feedback(struct pfr_addr *addr, int size)
{
struct pfr_addr ad;
int i;
+#ifdef __FreeBSD__
+ int ec;
+#endif
for (i = 0; i < size; i++) {
- if (COPYIN(addr+i, &ad, sizeof(ad)))
+#ifdef __FreeBSD__
+ PF_COPYIN(addr+i, &ad, sizeof(ad), ec);
+ if (ec)
+ break;
+#else
+ if (copyin(addr+i, &ad, sizeof(ad)))
break;
+#endif
ad.pfra_fback = PFR_FB_NONE;
- if (COPYOUT(&ad, addr+i, sizeof(ad)))
+#ifdef __FreeBSD__
+ PF_COPYOUT(&ad, addr+i, sizeof(ad), ec);
+ if (ec)
break;
+#else
+ if (copyout(&ad, addr+i, sizeof(ad)))
+ break;
+#endif
}
}
@@ -911,11 +1075,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);
@@ -935,11 +1105,17 @@ 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);
rn = rn_delete(&ke->pfrke_sa, &mask, head);
} else
rn = rn_delete(&ke->pfrke_sa, NULL, head);
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 500100)
+ RADIX_NODE_HEAD_UNLOCK(head);
+#endif
splx(s);
if (rn == NULL) {
@@ -969,7 +1145,10 @@ pfr_walktree(struct radix_node *rn, void *arg)
{
struct pfr_kentry *ke = (struct pfr_kentry *)rn;
struct pfr_walktree *w = arg;
- int s, flags = w->pfrw_flags;
+ int s;
+#ifdef __FreeBSD__
+ int ec;
+#endif
switch (w->pfrw_op) {
case PFRW_MARK:
@@ -978,7 +1157,7 @@ pfr_walktree(struct radix_node *rn, void *arg)
case PFRW_SWEEP:
if (ke->pfrke_mark)
break;
- /* FALLTHROUGH */
+ /* fall trough */
case PFRW_ENQUEUE:
SLIST_INSERT_HEAD(w->pfrw_workq, ke, pfrke_workq);
w->pfrw_cnt++;
@@ -988,8 +1167,14 @@ pfr_walktree(struct radix_node *rn, void *arg)
struct pfr_addr ad;
pfr_copyout_addr(&ad, ke);
+#ifdef __FreeBSD__
+ PF_COPYOUT(&ad, w->pfrw_addr, sizeof(ad), ec);
+ if (ec)
+ return (EFAULT);
+#else
if (copyout(&ad, w->pfrw_addr, sizeof(ad)))
return (EFAULT);
+#endif
w->pfrw_addr++;
}
break;
@@ -1007,8 +1192,14 @@ pfr_walktree(struct radix_node *rn, void *arg)
splx(s);
as.pfras_tzero = ke->pfrke_tzero;
- if (COPYOUT(&as, w->pfrw_astats, sizeof(as)))
+#ifdef __FreeBSD__
+ PF_COPYOUT(&as, w->pfrw_astats, sizeof(as), ec);
+ if (ec)
return (EFAULT);
+#else
+ if (copyout(&as, w->pfrw_astats, sizeof(as)))
+ return (EFAULT);
+#endif
w->pfrw_astats++;
}
break;
@@ -1020,25 +1211,6 @@ pfr_walktree(struct radix_node *rn, void *arg)
return (1); /* finish search */
}
break;
- case PFRW_DYNADDR_UPDATE:
- if (ke->pfrke_af == AF_INET) {
- if (w->pfrw_dyn->pfid_acnt4++ > 0)
- break;
- pfr_prepare_network(&pfr_mask, AF_INET, ke->pfrke_net);
- w->pfrw_dyn->pfid_addr4 = *SUNION2PF(
- &ke->pfrke_sa, AF_INET);
- w->pfrw_dyn->pfid_mask4 = *SUNION2PF(
- &pfr_mask, AF_INET);
- } else {
- if (w->pfrw_dyn->pfid_acnt6++ > 0)
- break;
- pfr_prepare_network(&pfr_mask, AF_INET6, ke->pfrke_net);
- w->pfrw_dyn->pfid_addr6 = *SUNION2PF(
- &ke->pfrke_sa, AF_INET6);
- w->pfrw_dyn->pfid_mask6 = *SUNION2PF(
- &pfr_mask, AF_INET6);
- }
- break;
}
return (0);
}
@@ -1058,8 +1230,6 @@ pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
if (pfr_skip_table(filter, p, flags))
continue;
- if (!strcmp(p->pfrkt_anchor, PF_RESERVED_ANCHOR))
- continue;
if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE))
continue;
p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE;
@@ -1084,16 +1254,29 @@ 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;
+#ifdef __FreeBSD__
+ int ec;
+ /*
+ * XXX Is it OK under LP64 environments?
+ */
+ long tzero = (long)time_second;
+#else
long tzero = time.tv_sec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
SLIST_INIT(&addq);
SLIST_INIT(&changeq);
for (i = 0; i < size; i++) {
- if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+#ifdef __FreeBSD__
+ PF_COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), ec);
+ if (ec)
+ senderr(EFAULT);
+#else
+ if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
senderr(EFAULT);
- if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK,
- flags & PFR_FLAG_USERIOCTL))
+#endif
+ if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK))
senderr(EINVAL);
key.pfrkt_flags |= PFR_TFLAG_ACTIVE;
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
@@ -1165,14 +1348,22 @@ 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;
+#ifdef __FreeBSD__
+ int ec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
- if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+#ifdef __FreeBSD__
+ PF_COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), ec);
+ if (ec)
+ return (EFAULT);
+#else
+ if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
return (EFAULT);
- if (pfr_validate_table(&key.pfrkt_t, 0,
- flags & PFR_FLAG_USERIOCTL))
+#endif
+ if (pfr_validate_table(&key.pfrkt_t, 0))
return (EINVAL);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
@@ -1205,6 +1396,9 @@ pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
{
struct pfr_ktable *p;
int n, nn;
+#ifdef __FreeBSD__
+ int ec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_ALLRSETS);
n = nn = pfr_table_count(filter, flags);
@@ -1219,8 +1413,14 @@ pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
continue;
if (n-- <= 0)
continue;
- if (COPYOUT(&p->pfrkt_t, tbl++, sizeof(*tbl)))
+#ifdef __FreeBSD__
+ PF_COPYOUT(&p->pfrkt_t, tbl++, sizeof(*tbl), ec);
+ if (ec)
return (EFAULT);
+#else
+ if (copyout(&p->pfrkt_t, tbl++, sizeof(*tbl)))
+ return (EFAULT);
+#endif
}
if (n) {
printf("pfr_get_tables: corruption detected (%d).\n", n);
@@ -1237,7 +1437,15 @@ 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;
+#ifdef __FreeBSD__
+ int ec;
+ /*
+ * XXX Is it OK under LP64 environments?
+ */
+ long tzero = (long)time_second;
+#else
long tzero = time.tv_sec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC|PFR_FLAG_ALLRSETS);
/* XXX PFR_FLAG_CLSTATS disabled */
@@ -1258,10 +1466,18 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
continue;
if (!(flags & PFR_FLAG_ATOMIC))
s = splsoftnet();
- if (COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl))) {
+#ifdef __FreeBSD__
+ PF_COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl), ec);
+ if (ec) {
+ splx(s);
+ return (EFAULT);
+ }
+#else
+ if (copyout(&p->pfrkt_ts, tbl++, sizeof(*tbl))) {
splx(s);
return (EFAULT);
}
+#endif
if (!(flags & PFR_FLAG_ATOMIC))
splx(s);
SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
@@ -1285,14 +1501,28 @@ 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;
+#ifdef __FreeBSD__
+ int ec;
+ /*
+ * XXX Is it OK under LP64 environments?
+ */
+ long tzero = (long)time_second;
+#else
long tzero = time.tv_sec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ADDRSTOO);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
- if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+#ifdef __FreeBSD__
+ PF_COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), ec);
+ if (ec)
+ return (EFAULT);
+#else
+ if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
return (EFAULT);
- if (pfr_validate_table(&key.pfrkt_t, 0, 0))
+#endif
+ if (pfr_validate_table(&key.pfrkt_t, 0))
return (EINVAL);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (p != NULL) {
@@ -1319,6 +1549,9 @@ 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;
+#ifdef __FreeBSD__
+ int ec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
if ((setflag & ~PFR_TFLAG_USRMASK) ||
@@ -1327,10 +1560,15 @@ pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
return (EINVAL);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
- if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+#ifdef __FreeBSD__
+ PF_COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), ec);
+ if (ec)
+ return (EFAULT);
+#else
+ if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
return (EFAULT);
- if (pfr_validate_table(&key.pfrkt_t, 0,
- flags & PFR_FLAG_USERIOCTL))
+#endif
+ if (pfr_validate_table(&key.pfrkt_t, 0))
return (EINVAL);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
@@ -1410,12 +1648,14 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfr_addr ad;
struct pf_ruleset *rs;
int i, rv, xadd = 0, xaddr = 0;
+#ifdef __FreeBSD__
+ int ec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_DUMMY|PFR_FLAG_ADDRSTOO);
if (size && !(flags & PFR_FLAG_ADDRSTOO))
return (EINVAL);
- if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK,
- flags & PFR_FLAG_USERIOCTL))
+ if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK))
return (EINVAL);
rs = pf_find_ruleset(tbl->pfrt_anchor, tbl->pfrt_ruleset);
if (rs == NULL || !rs->topen || ticket != rs->tticket)
@@ -1457,8 +1697,14 @@ _skip:
}
SLIST_INIT(&addrq);
for (i = 0; i < size; i++) {
- if (COPYIN(addr+i, &ad, sizeof(ad)))
+#ifdef __FreeBSD__
+ PF_COPYIN(addr+i, &ad, sizeof(ad), ec);
+ if (ec)
senderr(EFAULT);
+#else
+ if (copyin(addr+i, &ad, sizeof(ad)))
+ senderr(EFAULT);
+#endif
if (pfr_validate_addr(&ad))
senderr(EINVAL);
if (pfr_lookup_addr(shadow, &ad, 1) != NULL)
@@ -1500,37 +1746,6 @@ _bad:
}
int
-pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
-{
- struct pfr_ktableworkq workq;
- struct pfr_ktable *p;
- struct pf_ruleset *rs;
- int xdel = 0;
-
- ACCEPT_FLAGS(PFR_FLAG_DUMMY);
- rs = pf_find_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
- if (rs == NULL || !rs->topen || ticket != rs->tticket)
- return (0);
- SLIST_INIT(&workq);
- RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
- if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
- pfr_skip_table(trs, p, 0))
- continue;
- p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE;
- SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
- xdel++;
- }
- if (!(flags & PFR_FLAG_DUMMY)) {
- pfr_setflags_ktables(&workq);
- rs->topen = 0;
- pf_remove_if_empty_ruleset(rs);
- }
- if (ndel != NULL)
- *ndel = xdel;
- return (0);
-}
-
-int
pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
int *nchange, int flags)
{
@@ -1538,7 +1753,14 @@ pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
struct pfr_ktableworkq workq;
struct pf_ruleset *rs;
int s, xadd = 0, xchange = 0;
+#ifdef __FreeBSD__
+ /*
+ * XXX Is it OK under LP64 environments?
+ */
+ long tzero = (long)time_second;
+#else
long tzero = time.tv_sec;
+#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
rs = pf_find_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
@@ -1635,14 +1857,12 @@ pfr_commit_ktable(struct pfr_ktable *kt, long tzero)
}
int
-pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved)
+pfr_validate_table(struct pfr_table *tbl, int allowedflags)
{
int i;
if (!tbl->pfrt_name[0])
return (-1);
- if (no_reserved && !strcmp(tbl->pfrt_anchor, PF_RESERVED_ANCHOR))
- return (-1);
if (tbl->pfrt_name[PF_TABLE_NAME_SIZE-1])
return (-1);
for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++)
@@ -1835,10 +2055,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) {
@@ -1860,16 +2091,15 @@ pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q)
if ((d = strncmp(p->pfrkt_anchor, q->pfrkt_anchor,
PF_ANCHOR_NAME_SIZE)))
return (d);
- return (strncmp(p->pfrkt_ruleset, q->pfrkt_ruleset,
- PF_RULESET_NAME_SIZE));
+ return strncmp(p->pfrkt_ruleset, q->pfrkt_ruleset,
+ PF_RULESET_NAME_SIZE);
}
struct pfr_ktable *
pfr_lookup_table(struct pfr_table *tbl)
{
/* struct pfr_ktable start like a struct pfr_table */
- return (RB_FIND(pfr_ktablehead, &pfr_ktables,
- (struct pfr_ktable *)tbl));
+ return RB_FIND(pfr_ktablehead, &pfr_ktables, (struct pfr_ktable *)tbl);
}
int
@@ -1881,7 +2111,7 @@ pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
kt = kt->pfrkt_root;
if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
- return (0);
+ return 0;
switch (af) {
case AF_INET:
@@ -1958,7 +2188,14 @@ pfr_attach_table(struct pf_ruleset *rs, char *name)
}
kt = pfr_lookup_table(&tbl);
if (kt == NULL) {
+#ifdef __FreeBSD__
+ /*
+ * XXX Is it OK under LP64 environments?
+ */
+ kt = pfr_create_ktable(&tbl, (long)time_second, 1);
+#else
kt = pfr_create_ktable(&tbl, time.tv_sec, 1);
+#endif
if (kt == NULL)
return (NULL);
if (ac != NULL) {
@@ -1979,7 +2216,7 @@ pfr_attach_table(struct pf_ruleset *rs, char *name)
}
if (!kt->pfrkt_refcnt[PFR_REFCNT_RULE]++)
pfr_setflags_ktable(kt, kt->pfrkt_flags|PFR_TFLAG_REFERENCED);
- return (kt);
+ return kt;
}
void
@@ -1992,6 +2229,7 @@ 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)
@@ -2045,7 +2283,7 @@ _next_block:
}
for (;;) {
/* we don't want to use a nested block */
- ke2 = (struct pfr_kentry *)(af == AF_INET ?
+ ke2 = (struct pfr_kentry *)(af == AF_INET ?
rn_match(&pfr_sin, kt->pfrkt_ip4) :
rn_match(&pfr_sin6, kt->pfrkt_ip6));
/* no need to check KENTRY_RNF_ROOT() here */
@@ -2075,38 +2313,26 @@ pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
{
struct pfr_walktree w;
- bzero(&w, sizeof(w));
- w.pfrw_op = PFRW_POOL_GET;
- w.pfrw_cnt = idx;
+ bzero(&w, sizeof(w));
+ w.pfrw_op = PFRW_POOL_GET;
+ w.pfrw_cnt = idx;
- switch (af) {
+ switch(af) {
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);
- return (w.pfrw_kentry);
+#endif
+ return w.pfrw_kentry;
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);
- return (w.pfrw_kentry);
+#endif
+ return w.pfrw_kentry;
default:
- return (NULL);
+ return NULL;
}
}
-
-void
-pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn)
-{
- struct pfr_walktree w;
- int s;
-
- bzero(&w, sizeof(w));
- w.pfrw_op = PFRW_DYNADDR_UPDATE;
- w.pfrw_dyn = dyn;
-
- s = splsoftnet();
- dyn->pfid_acnt4 = 0;
- dyn->pfid_acnt6 = 0;
- if (!dyn->pfid_af || dyn->pfid_af == AF_INET)
- rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
- if (!dyn->pfid_af || dyn->pfid_af == AF_INET6)
- rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
- splx(s);
-}
diff --git a/sys/contrib/pf/net/pfvar.h b/sys/contrib/pf/net/pfvar.h
index d3dda46..9012227 100644
--- a/sys/contrib/pf/net/pfvar.h
+++ b/sys/contrib/pf/net/pfvar.h
@@ -1,4 +1,5 @@
-/* $OpenBSD: pfvar.h,v 1.187 2004/03/22 04:54:18 mcbride Exp $ */
+/* $FreeBSD$ */
+/* $OpenBSD: pfvar.h,v 1.170 2003/08/22 21:50:34 david Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -38,7 +39,26 @@
#include <sys/tree.h>
#include <net/radix.h>
+#ifdef __FreeBSD__
+#include <vm/uma.h>
+#else
#include <netinet/ip_ipsp.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <netinet/in.h>
+/*
+ * XXX
+ * If we include <netipsec/keydb.h>, we need _KERNEL definition.
+ * This makes pfctl compilation difficult.
+ */
+union sockaddr_union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+};
+#endif
+
#include <netinet/tcp_fsm.h>
struct ip;
@@ -47,7 +67,6 @@ struct ip;
#define PF_TCPS_PROXY_DST ((TCP_NSTATES)+1)
enum { PF_INOUT, PF_IN, PF_OUT };
-enum { PF_LAN_EXT, PF_EXT_GWY, PF_ID };
enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NAT, PF_NONAT,
PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP };
enum { PF_RULESET_SCRUB, PF_RULESET_FILTER, PF_RULESET_NAT,
@@ -68,17 +87,16 @@ enum { PFTM_TCP_FIRST_PACKET, PFTM_TCP_OPENING, PFTM_TCP_ESTABLISHED,
PFTM_ICMP_FIRST_PACKET, PFTM_ICMP_ERROR_REPLY,
PFTM_OTHER_FIRST_PACKET, PFTM_OTHER_SINGLE,
PFTM_OTHER_MULTIPLE, PFTM_FRAG, PFTM_INTERVAL,
- PFTM_ADAPTIVE_START, PFTM_ADAPTIVE_END, PFTM_SRC_NODE,
- PFTM_MAX, PFTM_PURGE, PFTM_UNTIL_PACKET };
+ PFTM_ADAPTIVE_START, PFTM_ADAPTIVE_END, PFTM_MAX,
+ PFTM_PURGE, PFTM_UNTIL_PACKET };
enum { PF_NOPFROUTE, PF_FASTROUTE, PF_ROUTETO, PF_DUPTO, PF_REPLYTO };
-enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS, PF_LIMIT_MAX };
+enum { PF_LIMIT_STATES, PF_LIMIT_FRAGS, PF_LIMIT_MAX };
#define PF_POOL_IDMASK 0x0f
enum { PF_POOL_NONE, PF_POOL_BITMASK, PF_POOL_RANDOM,
PF_POOL_SRCHASH, PF_POOL_ROUNDROBIN };
enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL,
PF_ADDR_TABLE };
#define PF_POOL_TYPEMASK 0x0f
-#define PF_POOL_STICKYADDR 0x20
#define PF_WSCALE_FLAG 0x80
#define PF_WSCALE_MASK 0x0f
@@ -99,12 +117,6 @@ struct pf_addr {
#define PF_TABLE_NAME_SIZE 32
-#define PFI_AFLAG_NETWORK 0x01
-#define PFI_AFLAG_BROADCAST 0x02
-#define PFI_AFLAG_PEER 0x04
-#define PFI_AFLAG_MODEMASK 0x07
-#define PFI_AFLAG_NOALIAS 0x08
-
struct pf_addr_wrap {
union {
struct {
@@ -115,36 +127,93 @@ struct pf_addr_wrap {
char tblname[PF_TABLE_NAME_SIZE];
} v;
union {
- struct pfi_dynaddr *dyn;
+ struct pf_addr_dyn *dyn;
struct pfr_ktable *tbl;
- int dyncnt;
int tblcnt;
} p;
u_int8_t type; /* PF_ADDR_* */
- u_int8_t iflags; /* PFI_AFLAG_* */
};
#ifdef _KERNEL
-struct pfi_dynaddr {
- struct pf_addr pfid_addr4;
- struct pf_addr pfid_mask4;
- struct pf_addr pfid_addr6;
- struct pf_addr pfid_mask6;
- struct pfr_ktable *pfid_kt;
- struct pfi_kif *pfid_kif;
- void *pfid_hook_cookie;
- int pfid_net; /* optional mask, or 128 */
- int pfid_acnt4; /* address count, IPv4 */
- int pfid_acnt6; /* address count, IPv6 */
- sa_family_t pfid_af; /* rule address family */
- u_int8_t pfid_iflags; /* PFI_AFLAG_* */
+struct pf_addr_dyn {
+ char ifname[IFNAMSIZ];
+ struct ifnet *ifp;
+ struct pf_addr *addr;
+ sa_family_t af;
+#ifdef __FreeBSD__
+ eventhandler_tag hook_cookie;
+#else
+ void *hook_cookie;
+#endif
+ u_int8_t undefined;
};
/*
* Address manipulation macros
*/
+#ifdef __FreeBSD__
+#define splsoftnet() splnet()
+
+#define HTONL(x) (x) = htonl((__uint32_t)(x))
+#define HTONS(x) (x) = htons((__uint16_t)(x))
+#define NTOHL(x) (x) = ntohl((__uint32_t)(x))
+#define NTOHS(x) (x) = ntohs((__uint16_t)(x))
+
+#define PF_NAME "pf"
+
+#define PR_NOWAIT M_NOWAIT
+#define pool_get(p, f) uma_zalloc(*(p), (f))
+#define pool_put(p, o) uma_zfree(*(p), (o))
+
+#define UMA_CREATE(var, type, desc) \
+ var = uma_zcreate(desc, sizeof(type), \
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); \
+ if (var == NULL) break
+#define UMA_DESTROY(var) \
+ if(var) uma_zdestroy(var)
+
+extern struct mtx pf_task_mtx;
+
+#define PF_ASSERT(h) mtx_assert(&pf_task_mtx, (h))
+
+#define PF_LOCK() do { \
+ PF_ASSERT(MA_NOTOWNED); \
+ mtx_lock(&pf_task_mtx); \
+} while(0)
+#define PF_UNLOCK() do { \
+ PF_ASSERT(MA_OWNED); \
+ mtx_unlock(&pf_task_mtx); \
+} while(0)
+
+#define PF_COPYIN(uaddr, kaddr, len, r) do { \
+ PF_UNLOCK(); \
+ r = copyin((uaddr), (kaddr), (len)); \
+ PF_LOCK(); \
+} while(0)
+
+#define PF_COPYOUT(kaddr, uaddr, len, r) do { \
+ PF_UNLOCK(); \
+ r = copyout((kaddr), (uaddr), (len)); \
+ PF_LOCK(); \
+} while(0)
+
+extern void init_pf_mutex(void);
+extern void destroy_pf_mutex(void);
+
+#define PF_MODVER 1
+#define PFLOG_MODVER 1
+#define PFSYNC_MODVER 1
+
+#define PFLOG_MINVER 1
+#define PFLOG_PREFVER PFLOG_MODVER
+#define PFLOG_MAXVER 1
+#define PFSYNC_MINVER 1
+#define PFSYNC_PREFVER PFSYNC_MODVER
+#define PFSYNC_MAXVER 1
+#endif
+
#ifdef INET
#ifndef INET6
#define PF_INET_ONLY
@@ -281,7 +350,10 @@ struct pfi_dynaddr {
((aw)->type == PF_ADDR_TABLE && \
!pfr_match_addr((aw)->p.tbl, (x), (af))) || \
((aw)->type == PF_ADDR_DYNIFTL && \
- !pfi_match_addr((aw)->p.dyn, (x), (af))) || \
+ ((aw)->p.dyn->undefined || \
+ (!PF_AZERO(&(aw)->v.a.mask, (af)) && \
+ !PF_MATCHA(0, &(aw)->v.a.addr, \
+ &(aw)->v.a.mask, (x), (af))))) || \
((aw)->type == PF_ADDR_ADDRMASK && \
!PF_AZERO(&(aw)->v.a.mask, (af)) && \
!PF_MATCHA(0, &(aw)->v.a.addr, \
@@ -310,7 +382,7 @@ struct pf_pooladdr {
struct pf_addr_wrap addr;
TAILQ_ENTRY(pf_pooladdr) entries;
char ifname[IFNAMSIZ];
- struct pfi_kif *kif;
+ struct ifnet *ifp;
};
TAILQ_HEAD(pf_palist, pf_pooladdr);
@@ -459,6 +531,7 @@ struct pf_rule {
union pf_rule_ptr skip[PF_SKIP_COUNT];
#define PF_RULE_LABEL_SIZE 64
char label[PF_RULE_LABEL_SIZE];
+ u_int32_t timeout[PFTM_MAX];
#define PF_QNAME_SIZE 16
char ifname[IFNAMSIZ];
char qname[PF_QNAME_SIZE];
@@ -476,17 +549,12 @@ struct pf_rule {
u_int64_t packets;
u_int64_t bytes;
- struct pfi_kif *kif;
+ struct ifnet *ifp;
struct pf_anchor *anchor;
pf_osfp_t os_fingerprint;
-
- u_int32_t timeout[PFTM_MAX];
u_int32_t states;
u_int32_t max_states;
- u_int32_t src_nodes;
- u_int32_t max_src_nodes;
- u_int32_t max_src_states;
u_int32_t qid;
u_int32_t pqid;
u_int32_t rt_listid;
@@ -533,9 +601,6 @@ struct pf_rule {
#define PFRULE_FRAGMENT 0x0002
#define PFRULE_RETURNICMP 0x0004
#define PFRULE_RETURN 0x0008
-#define PFRULE_NOSYNC 0x0010
-#define PFRULE_SRCTRACK 0x0020 /* track source states */
-#define PFRULE_RULESRCTRACK 0x0040 /* per rule */
/* scrub flags */
#define PFRULE_NODF 0x0100
@@ -544,28 +609,8 @@ struct pf_rule {
#define PFRULE_RANDOMID 0x0800
#define PFRULE_REASSEMBLE_TCP 0x1000
-/* rule flags again */
-#define PFRULE_IFBOUND 0x00010000 /* if-bound */
-#define PFRULE_GRBOUND 0x00020000 /* group-bound */
-
#define PFSTATE_HIWAT 10000 /* default state table size */
-struct pf_src_node {
- RB_ENTRY(pf_src_node) entry;
- struct pf_addr addr;
- struct pf_addr raddr;
- union pf_rule_ptr rule;
- struct pfi_kif *kif;
- u_int32_t bytes;
- u_int32_t packets;
- u_int32_t states;
- u_int32_t creation;
- u_int32_t expire;
- sa_family_t af;
- u_int8_t ruletype;
-};
-
-#define PFSNODE_HIWAT 10000 /* default source node table size */
struct pf_state_scrub {
u_int16_t pfss_flags;
@@ -592,20 +637,7 @@ struct pf_state_peer {
struct pf_state_scrub *scrub; /* state is scrubbed */
};
-TAILQ_HEAD(pf_state_queue, pf_state);
-
struct pf_state {
- u_int64_t id;
- union {
- struct {
- RB_ENTRY(pf_state) entry_lan_ext;
- RB_ENTRY(pf_state) entry_ext_gwy;
- RB_ENTRY(pf_state) entry_id;
- TAILQ_ENTRY(pf_state) entry_updates;
- struct pfi_kif *kif;
- } s;
- char ifname[IFNAMSIZ];
- } u;
struct pf_state_host lan;
struct pf_state_host gwy;
struct pf_state_host ext;
@@ -615,25 +647,27 @@ struct pf_state {
union pf_rule_ptr anchor;
union pf_rule_ptr nat_rule;
struct pf_addr rt_addr;
- struct pfi_kif *rt_kif;
- struct pf_src_node *src_node;
- struct pf_src_node *nat_src_node;
+ struct ifnet *rt_ifp;
u_int32_t creation;
u_int32_t expire;
- u_int32_t pfsync_time;
u_int32_t packets[2];
u_int32_t bytes[2];
- u_int32_t creatorid;
sa_family_t af;
u_int8_t proto;
u_int8_t direction;
u_int8_t log;
u_int8_t allow_opts;
u_int8_t timeout;
- u_int8_t sync_flags;
-#define PFSTATE_NOSYNC 0x01
-#define PFSTATE_FROMSYNC 0x02
- u_int8_t pad;
+ u_int8_t pad[2];
+};
+
+struct pf_tree_node {
+ RB_ENTRY(pf_tree_node) entry;
+ struct pf_state *state;
+ struct pf_addr addr[2];
+ u_int16_t port[2];
+ sa_family_t af;
+ u_int8_t proto;
};
TAILQ_HEAD(pf_rulequeue, pf_rule);
@@ -649,7 +683,6 @@ struct pf_ruleset {
struct {
struct pf_rulequeue *ptr;
u_int32_t ticket;
- int open;
} active, inactive;
} rules[PF_RULESET_MAX];
struct pf_anchor *anchor;
@@ -669,9 +702,6 @@ struct pf_anchor {
TAILQ_HEAD(pf_anchorqueue, pf_anchor);
-#define PF_RESERVED_ANCHOR "_pf"
-#define PF_INTERFACE_RULESET "_if"
-
#define PFR_TFLAG_PERSIST 0x00000001
#define PFR_TFLAG_CONST 0x00000002
#define PFR_TFLAG_ACTIVE 0x00000004
@@ -758,13 +788,12 @@ struct pfr_ktable {
struct pfr_ktable *pfrkt_shadow;
struct pfr_ktable *pfrkt_root;
struct pf_ruleset *pfrkt_rs;
- long pfrkt_larg;
int pfrkt_nflags;
};
#define pfrkt_t pfrkt_ts.pfrts_t
#define pfrkt_name pfrkt_t.pfrt_name
-#define pfrkt_anchor pfrkt_t.pfrt_anchor
-#define pfrkt_ruleset pfrkt_t.pfrt_ruleset
+#define pfrkt_anchor pfrkt_t.pfrt_anchor
+#define pfrkt_ruleset pfrkt_t.pfrt_ruleset
#define pfrkt_flags pfrkt_t.pfrt_flags
#define pfrkt_cnt pfrkt_ts.pfrts_cnt
#define pfrkt_refcnt pfrkt_ts.pfrts_refcnt
@@ -774,60 +803,6 @@ struct pfr_ktable {
#define pfrkt_nomatch pfrkt_ts.pfrts_nomatch
#define pfrkt_tzero pfrkt_ts.pfrts_tzero
-RB_HEAD(pf_state_tree_lan_ext, pf_state);
-RB_PROTOTYPE(pf_state_tree_lan_ext, pf_state,
- u.s.entry_lan_ext, pf_state_compare_lan_ext);
-
-RB_HEAD(pf_state_tree_ext_gwy, pf_state);
-RB_PROTOTYPE(pf_state_tree_ext_gwy, pf_state,
- u.s.entry_ext_gwy, pf_state_compare_ext_gwy);
-
-struct pfi_if {
- char pfif_name[IFNAMSIZ];
- u_int64_t pfif_packets[2][2][2];
- u_int64_t pfif_bytes[2][2][2];
- u_int64_t pfif_addcnt;
- u_int64_t pfif_delcnt;
- long pfif_tzero;
- int pfif_states;
- int pfif_rules;
- int pfif_flags;
-};
-
-TAILQ_HEAD(pfi_grouphead, pfi_kif);
-TAILQ_HEAD(pfi_statehead, pfi_kif);
-RB_HEAD(pfi_ifhead, pfi_kif);
-struct pfi_kif {
- struct pfi_if pfik_if;
- RB_ENTRY(pfi_kif) pfik_tree;
- struct pf_state_tree_lan_ext pfik_lan_ext;
- struct pf_state_tree_ext_gwy pfik_ext_gwy;
- struct pfi_grouphead pfik_grouphead;
- TAILQ_ENTRY(pfi_kif) pfik_instances;
- TAILQ_ENTRY(pfi_kif) pfik_w_states;
- struct hook_desc_head *pfik_ah_head;
- void *pfik_ah_cookie;
- struct pfi_kif *pfik_parent;
- struct ifnet *pfik_ifp;
- int pfik_states;
- int pfik_rules;
-};
-#define pfik_name pfik_if.pfif_name
-#define pfik_packets pfik_if.pfif_packets
-#define pfik_bytes pfik_if.pfif_bytes
-#define pfik_tzero pfik_if.pfif_tzero
-#define pfik_flags pfik_if.pfif_flags
-#define pfik_addcnt pfik_if.pfif_addcnt
-#define pfik_delcnt pfik_if.pfif_delcnt
-#define pfik_states pfik_if.pfif_states
-#define pfik_rules pfik_if.pfif_rules
-
-#define PFI_IFLAG_GROUP 0x0001 /* group of interfaces */
-#define PFI_IFLAG_INSTANCE 0x0002 /* single instance */
-#define PFI_IFLAG_CLONABLE 0x0010 /* clonable group */
-#define PFI_IFLAG_DYNAMIC 0x0020 /* dynamic group */
-#define PFI_IFLAG_ATTACHED 0x0040 /* interface attached */
-
struct pf_pdesc {
u_int64_t tot_len; /* Make Mickey money */
union {
@@ -839,9 +814,6 @@ struct pf_pdesc {
#endif /* INET6 */
void *any;
} hdr;
- struct pf_addr baddr; /* address before translation */
- struct pf_addr naddr; /* address after translation */
- struct pf_rule *nat_rule; /* nat/rdr rule applied to packet */
struct pf_addr *src;
struct pf_addr *dst;
u_int16_t *ip_sum;
@@ -910,10 +882,6 @@ struct pf_pdesc {
#define FCNT_STATE_REMOVALS 2
#define FCNT_MAX 3
-#define SCNT_SRC_NODE_SEARCH 0
-#define SCNT_SRC_NODE_INSERT 1
-#define SCNT_SRC_NODE_REMOVALS 2
-#define SCNT_MAX 3
#define ACTION_SET(a, x) \
do { \
@@ -932,16 +900,12 @@ struct pf_pdesc {
struct pf_status {
u_int64_t counters[PFRES_MAX];
u_int64_t fcounters[FCNT_MAX];
- u_int64_t scounters[SCNT_MAX];
u_int64_t pcounters[2][2][3];
u_int64_t bcounters[2][2];
- u_int64_t stateid;
u_int32_t running;
u_int32_t states;
- u_int32_t src_nodes;
u_int32_t since;
u_int32_t debug;
- u_int32_t hostid;
char ifname[IFNAMSIZ];
};
@@ -1073,7 +1037,6 @@ struct pfioc_state_kill {
int psk_proto;
struct pf_rule_addr psk_src;
struct pf_rule_addr psk_dst;
- char psk_ifname[IFNAMSIZ];
};
struct pfioc_states {
@@ -1086,16 +1049,6 @@ struct pfioc_states {
#define ps_states ps_u.psu_states
};
-struct pfioc_src_nodes {
- int psn_len;
- union {
- caddr_t psu_buf;
- struct pf_src_node *psu_src_nodes;
- } psn_u;
-#define psn_buf psn_u.psu_buf
-#define psn_src_nodes psn_u.psu_src_nodes
-};
-
struct pfioc_if {
char ifname[IFNAMSIZ];
};
@@ -1136,19 +1089,6 @@ struct pfioc_ruleset {
char name[PF_RULESET_NAME_SIZE];
};
-#define PF_RULESET_ALTQ (PF_RULESET_MAX)
-#define PF_RULESET_TABLE (PF_RULESET_MAX+1)
-struct pfioc_trans {
- int size; /* number of elements */
- int esize; /* size of each element in bytes */
- struct pfioc_trans_e {
- int rs_num;
- char anchor[PF_ANCHOR_NAME_SIZE];
- char ruleset[PF_RULESET_NAME_SIZE];
- u_int32_t ticket;
- } *array;
-};
-
#define PFR_FLAG_ATOMIC 0x00000001
#define PFR_FLAG_DUMMY 0x00000002
#define PFR_FLAG_FEEDBACK 0x00000004
@@ -1157,9 +1097,6 @@ struct pfioc_trans {
#define PFR_FLAG_REPLACE 0x00000020
#define PFR_FLAG_ALLRSETS 0x00000040
#define PFR_FLAG_ALLMASK 0x0000007F
-#ifdef _KERNEL
-#define PFR_FLAG_USERIOCTL 0x10000000
-#endif
struct pfioc_table {
struct pfr_table pfrio_table;
@@ -1181,20 +1118,6 @@ struct pfioc_table {
#define pfrio_clrflag pfrio_nadd
-#define PFI_FLAG_GROUP 0x0001 /* gets groups of interfaces */
-#define PFI_FLAG_INSTANCE 0x0002 /* gets single interfaces */
-#define PFI_FLAG_ALLMASK 0x0003
-
-struct pfioc_iface {
- char pfiio_name[IFNAMSIZ];
- void *pfiio_buffer;
- int pfiio_esize;
- int pfiio_size;
- int pfiio_nzero;
- int pfiio_flags;
-};
-
-
/*
* ioctl operations
*/
@@ -1207,7 +1130,7 @@ struct pfioc_iface {
#define DIOCGETRULES _IOWR('D', 6, struct pfioc_rule)
#define DIOCGETRULE _IOWR('D', 7, struct pfioc_rule)
/* XXX cut 8 - 17 */
-#define DIOCCLRSTATES _IOWR('D', 18, struct pfioc_state_kill)
+#define DIOCCLRSTATES _IO ('D', 18)
#define DIOCGETSTATE _IOWR('D', 19, struct pfioc_state)
#define DIOCSETSTATUSIF _IOWR('D', 20, struct pfioc_if)
#define DIOCGETSTATUS _IOWR('D', 21, struct pf_status)
@@ -1263,38 +1186,30 @@ struct pfioc_iface {
#define DIOCOSFPFLUSH _IO('D', 78)
#define DIOCOSFPADD _IOWR('D', 79, struct pf_osfp_ioctl)
#define DIOCOSFPGET _IOWR('D', 80, struct pf_osfp_ioctl)
-#define DIOCXBEGIN _IOWR('D', 81, struct pfioc_trans)
-#define DIOCXCOMMIT _IOWR('D', 82, struct pfioc_trans)
-#define DIOCXROLLBACK _IOWR('D', 83, struct pfioc_trans)
-#define DIOCGETSRCNODES _IOWR('D', 84, struct pfioc_src_nodes)
-#define DIOCCLRSRCNODES _IO('D', 85)
-#define DIOCSETHOSTID _IOWR('D', 86, u_int32_t)
-#define DIOCIGETIFACES _IOWR('D', 87, struct pfioc_iface)
-#define DIOCICLRISTATS _IOWR('D', 88, struct pfioc_iface)
+#ifdef __FreeBSD__
+struct pf_ifspeed {
+ char ifname[IFNAMSIZ];
+ u_int32_t baudrate;
+};
+#define DIOCGIFSPEED _IOWR('D', 81, struct pf_ifspeed)
+#endif
#ifdef _KERNEL
-RB_HEAD(pf_src_tree, pf_src_node);
-RB_PROTOTYPE(pf_src_tree, pf_src_node, entry, pf_src_compare);
-extern struct pf_src_tree tree_src_tracking;
-
-RB_HEAD(pf_state_tree_id, pf_state);
-RB_PROTOTYPE(pf_state_tree_id, pf_state,
- entry_id, pf_state_compare_id);
-extern struct pf_state_tree_id tree_id;
-extern struct pf_state_queue state_updates;
-
-extern struct pf_anchorqueue pf_anchors;
-extern struct pf_ruleset pf_main_ruleset;
+RB_HEAD(pf_state_tree, pf_tree_node);
+RB_PROTOTYPE(pf_state_tree, pf_tree_node, entry, pf_state_compare);
+extern struct pf_state_tree tree_lan_ext, tree_ext_gwy;
+
+extern struct pf_anchorqueue pf_anchors;
+extern struct pf_ruleset pf_main_ruleset;
TAILQ_HEAD(pf_poolqueue, pf_pool);
-extern struct pf_poolqueue pf_pools[2];
+extern struct pf_poolqueue pf_pools[2];
TAILQ_HEAD(pf_altqqueue, pf_altq);
-extern struct pf_altqqueue pf_altqs[2];
-extern struct pf_palist pf_pabuf;
-extern struct pfi_kif **pfi_index2kif;
+extern struct pf_altqqueue pf_altqs[2];
+extern struct pf_palist pf_pabuf;
+
extern u_int32_t ticket_altqs_active;
extern u_int32_t ticket_altqs_inactive;
-extern int altqs_inactive_open;
extern u_int32_t ticket_pabuf;
extern struct pf_altqqueue *pf_altqs_active;
extern struct pf_altqqueue *pf_altqs_inactive;
@@ -1304,32 +1219,37 @@ extern int pf_tbladdr_setup(struct pf_ruleset *,
struct pf_addr_wrap *);
extern void pf_tbladdr_remove(struct pf_addr_wrap *);
extern void pf_tbladdr_copyout(struct pf_addr_wrap *);
+extern int pf_dynaddr_setup(struct pf_addr_wrap *,
+ sa_family_t);
+extern void pf_dynaddr_copyout(struct pf_addr_wrap *);
+extern void pf_dynaddr_remove(struct pf_addr_wrap *);
extern void pf_calc_skip_steps(struct pf_rulequeue *);
+extern void pf_rule_set_qid(struct pf_rulequeue *);
+extern u_int32_t pf_qname_to_qid(char *);
extern void pf_update_anchor_rules(void);
-extern struct pool pf_src_tree_pl, pf_rule_pl;
+#ifdef __FreeBSD__
+extern uma_zone_t pf_tree_pl, pf_rule_pl, pf_addr_pl;
+extern uma_zone_t pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
+extern uma_zone_t pfr_ktable_pl, pfr_kentry_pl;
+extern uma_zone_t pf_cache_pl, pf_cent_pl;
+extern uma_zone_t pf_state_scrub_pl;
+#else
+extern struct pool pf_tree_pl, pf_rule_pl, pf_addr_pl;
extern struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
extern struct pool pf_state_scrub_pl;
+#endif
extern void pf_purge_timeout(void *);
-extern void pf_purge_expired_src_nodes(void);
extern void pf_purge_expired_states(void);
-extern int pf_insert_state(struct pfi_kif *,
- struct pf_state *);
-extern int pf_insert_src_node(struct pf_src_node **,
- struct pf_rule *, struct pf_addr *,
- sa_family_t);
-void pf_src_tree_remove_state(struct pf_state *);
-extern struct pf_state *pf_find_state_byid(struct pf_state *);
-extern struct pf_state *pf_find_state_all(struct pf_state *key,
- u_int8_t tree, int *more);
+extern int pf_insert_state(struct pf_state *);
+extern struct pf_state *pf_find_state(struct pf_state_tree *,
+ struct pf_tree_node *);
extern struct pf_anchor *pf_find_anchor(const char *);
extern struct pf_ruleset *pf_find_ruleset(char *, char *);
-extern struct pf_ruleset *pf_find_or_create_ruleset(
- char[PF_ANCHOR_NAME_SIZE],
- char[PF_RULESET_NAME_SIZE]);
+extern struct pf_ruleset *pf_find_or_create_ruleset(char *, char *);
extern void pf_remove_if_empty_ruleset(
struct pf_ruleset *);
-extern struct ifnet *sync_ifp;
+extern struct ifnet *status_ifp;
extern struct pf_rule pf_default_rule;
extern void pf_addrcpy(struct pf_addr *, struct pf_addr *,
u_int8_t);
@@ -1350,7 +1270,7 @@ void pf_addr_inc(struct pf_addr *, sa_family_t);
void *pf_pull_hdr(struct mbuf *, int, void *, int, u_short *, u_short *,
sa_family_t);
void pf_change_a(void *, u_int16_t *, u_int32_t, u_int8_t);
-int pflog_packet(struct pfi_kif *, struct mbuf *, sa_family_t, u_int8_t,
+int pflog_packet(struct ifnet *, struct mbuf *, sa_family_t, u_int8_t,
u_int8_t, struct pf_rule *, struct pf_rule *, struct pf_ruleset *);
int pf_match_addr(u_int8_t, struct pf_addr *, struct pf_addr *,
struct pf_addr *, sa_family_t);
@@ -1360,9 +1280,9 @@ int pf_match_uid(u_int8_t, uid_t, uid_t, uid_t);
int pf_match_gid(u_int8_t, gid_t, gid_t, gid_t);
void pf_normalize_init(void);
-int pf_normalize_ip(struct mbuf **, int, struct pfi_kif *, u_short *);
-int pf_normalize_ip6(struct mbuf **, int, struct pfi_kif *, u_short *);
-int pf_normalize_tcp(int, struct pfi_kif *, struct mbuf *, int, int, void *,
+int pf_normalize_ip(struct mbuf **, int, struct ifnet *, u_short *);
+int pf_normalize_ip6(struct mbuf **, int, struct ifnet *, u_short *);
+int pf_normalize_tcp(int, struct ifnet *, struct mbuf *, int, int, void *,
struct pf_pdesc *);
void pf_normalize_tcp_cleanup(struct pf_state *);
int pf_normalize_tcp_init(struct mbuf *, int, struct pf_pdesc *,
@@ -1380,7 +1300,6 @@ void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t,
u_int64_t, int, int, int);
int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *,
struct pf_addr **, struct pf_addr **, sa_family_t);
-void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *);
struct pfr_ktable *
pfr_attach_table(struct pf_ruleset *, char *);
void pfr_detach_table(struct pfr_ktable *);
@@ -1405,43 +1324,22 @@ int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *,
int pfr_tst_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
int);
int pfr_ina_begin(struct pfr_table *, u_int32_t *, int *, int);
-int pfr_ina_rollback(struct pfr_table *, u_int32_t, int *, int);
int pfr_ina_commit(struct pfr_table *, u_int32_t, int *, int *, int);
int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
int *, u_int32_t, int);
-void pfi_initialize(void);
-void pfi_attach_clone(struct if_clone *);
-void pfi_attach_ifnet(struct ifnet *);
-void pfi_detach_ifnet(struct ifnet *);
-struct pfi_kif *pfi_lookup_create(const char *);
-struct pfi_kif *pfi_lookup_if(const char *);
-int pfi_maybe_destroy(struct pfi_kif *);
-struct pfi_kif *pfi_attach_rule(const char *);
-void pfi_detach_rule(struct pfi_kif *);
-void pfi_attach_state(struct pfi_kif *);
-void pfi_detach_state(struct pfi_kif *);
-int pfi_dynaddr_setup(struct pf_addr_wrap *, sa_family_t);
-void pfi_dynaddr_copyout(struct pf_addr_wrap *);
-void pfi_dynaddr_remove(struct pf_addr_wrap *);
-void pfi_fill_oldstatus(struct pf_status *);
-int pfi_clr_istats(const char *, int *, int);
-int pfi_get_ifaces(const char *, struct pfi_if *, int *, int);
-int pfi_match_addr(struct pfi_dynaddr *, struct pf_addr *,
- sa_family_t);
-
-extern struct pfi_statehead pfi_statehead;
-
u_int16_t pf_tagname2tag(char *);
void pf_tag2tagname(u_int16_t, char *);
void pf_tag_unref(u_int16_t);
int pf_tag_packet(struct mbuf *, struct pf_tag *, int);
-u_int32_t pf_qname2qid(char *);
-void pf_qid2qname(u_int32_t, char *);
-void pf_qid_unref(u_int32_t);
extern struct pf_status pf_status;
+
+#ifdef __FreeBSD__
+extern uma_zone_t pf_frent_pl, pf_frag_pl;
+#else
extern struct pool pf_frent_pl, pf_frag_pl;
+#endif
struct pf_pool_limit {
void *pp;
@@ -1449,6 +1347,38 @@ struct pf_pool_limit {
};
extern struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX];
+#ifdef __FreeBSD__
+struct pf_frent {
+ LIST_ENTRY(pf_frent) fr_next;
+ struct ip *fr_ip;
+ struct mbuf *fr_m;
+};
+
+struct pf_frcache {
+ LIST_ENTRY(pf_frcache) fr_next;
+ uint16_t fr_off;
+ uint16_t fr_end;
+};
+
+struct pf_fragment {
+ RB_ENTRY(pf_fragment) fr_entry;
+ TAILQ_ENTRY(pf_fragment) frag_next;
+ struct in_addr fr_src;
+ struct in_addr fr_dst;
+ u_int8_t fr_p; /* protocol of this fragment */
+ u_int8_t fr_flags; /* status flags */
+ u_int16_t fr_id; /* fragment id for reassemble */
+ u_int16_t fr_max; /* fragment data max */
+ u_int32_t fr_timeout;
+#define fr_queue fr_u.fru_queue
+#define fr_cache fr_u.fru_cache
+ union {
+ LIST_HEAD(pf_fragq, pf_frent) fru_queue; /* buffering */
+ LIST_HEAD(pf_cacheq, pf_frcache) fru_cache; /* non-buf */
+ } fr_u;
+};
+#endif /* (__FreeBSD__) */
+
#endif /* _KERNEL */
/* The fingerprint functions can be linked into userland programs (tcpdump) */
@@ -1462,7 +1392,12 @@ struct pf_osfp_enlist *
pf_osfp_fingerprint_hdr(const struct ip *, const struct tcphdr *);
void pf_osfp_flush(void);
int pf_osfp_get(struct pf_osfp_ioctl *);
+#ifdef __FreeBSD__
+int pf_osfp_initialize(void);
+void pf_osfp_cleanup(void);
+#else
void pf_osfp_initialize(void);
+#endif
int pf_osfp_match(struct pf_osfp_enlist *, pf_osfp_t);
struct pf_os_fingerprint *
pf_osfp_validate(void);
diff --git a/sys/contrib/pf/netinet/in4_cksum.c b/sys/contrib/pf/netinet/in4_cksum.c
index 1c40f2e..ca2256f 100644
--- a/sys/contrib/pf/netinet/in4_cksum.c
+++ b/sys/contrib/pf/netinet/in4_cksum.c
@@ -1,3 +1,4 @@
+/* $FreeBSD$ */
/* $OpenBSD: in4_cksum.c,v 1.7 2003/06/02 23:28:13 millert Exp $ */
/* $KAME: in4_cksum.c,v 1.10 2001/11/30 10:06:15 itojun Exp $ */
/* $NetBSD: in_cksum.c,v 1.13 1996/10/13 02:03:03 christos Exp $ */
@@ -72,6 +73,39 @@
#include <netinet/ip.h>
#include <netinet/ip_var.h>
+#if defined(__FreeBSD__) && defined(__i386__)
+/*
+ * Copied from FreeBSD 5.0 sys/i386/i386/in_cksum.c
+ * XXX
+ * Currently support I386 processor only.
+ * In the long run, we need an optimized cksum routines for each Tier1
+ * architecture. Due to the lack of available hardware except I386 I
+ * can't support other processors now. For those users which use Sparc64,
+ * Alpha processors can use more optimized version in FreeBSD.
+ * See sys/$ARCH/$ARCH/in_cksum.c where $ARCH=`uname -p`
+ */
+
+/*
+ * These asm statements require __volatile because they pass information
+ * via the condition codes. GCC does not currently provide a way to specify
+ * the condition codes as an input or output operand.
+ *
+ * The LOAD macro below is effectively a prefetch into cache. GCC will
+ * load the value into a register but will not use it. Since modern CPUs
+ * reorder operations, this will generally take place in parallel with
+ * other calculations.
+ */
+#define ADD(n) __asm __volatile \
+ ("addl %1, %0" : "+r" (sum) : \
+ "g" (((const u_int32_t *)w)[n / 4]))
+#define ADDC(n) __asm __volatile \
+ ("adcl %1, %0" : "+r" (sum) : \
+ "g" (((const u_int32_t *)w)[n / 4]))
+#define LOAD(n) __asm __volatile \
+ ("" : : "r" (((const u_int32_t *)w)[n / 4]))
+#define MOP __asm __volatile \
+ ("adcl $0, %0" : "+r" (sum))
+#endif
/*
* Checksum routine for Internet Protocol family headers (Portable Version).
* This is only for IPv4 pseudo header checksum.
@@ -86,6 +120,11 @@
#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
+#if defined(__FreeBSD__)
+int
+in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len);
+#endif
+
int
in4_cksum(m, nxt, off, len)
struct mbuf *m;
@@ -158,6 +197,134 @@ in4_cksum(m, nxt, off, len)
if (len < mlen)
mlen = len;
len -= mlen;
+#if defined(__FreeBSD__) && defined(__i386__)
+ /*
+ * Force to long boundary so we do longword aligned
+ * memory operations
+ */
+ if (3 & (int) w) {
+ REDUCE;
+ if ((1 & (int) w) && (mlen > 0)) {
+ sum <<= 8;
+ s_util.c[0] = *(char *)w;
+ w = (u_short *)((char *)w + 1);
+ mlen--;
+ byte_swapped = 1;
+ }
+ if ((2 & (int) w) && (mlen >= 2)) {
+ sum += *w++;
+ mlen -= 2;
+ }
+ }
+ /*
+ * Advance to a 486 cache line boundary.
+ */
+ if (4 & (int) w && mlen >= 4) {
+ ADD(0);
+ MOP;
+ w += 2;
+ mlen -= 4;
+ }
+ if (8 & (int) w && mlen >= 8) {
+ ADD(0);
+ ADDC(4);
+ MOP;
+ w += 4;
+ mlen -= 8;
+ }
+ /*
+ * Do as much of the checksum as possible 32 bits at at time.
+ * In fact, this loop is unrolled to make overhead from
+ * branches &c small.
+ */
+ mlen -= 1;
+ while ((mlen -= 32) >= 0) {
+ /*
+ * Add with carry 16 words and fold in the last
+ * carry by adding a 0 with carry.
+ *
+ * The early ADD(16) and the LOAD(32) are to load
+ * the next 2 cache lines in advance on 486's. The
+ * 486 has a penalty of 2 clock cycles for loading
+ * a cache line, plus whatever time the external
+ * memory takes to load the first word(s) addressed.
+ * These penalties are unavoidable. Subsequent
+ * accesses to a cache line being loaded (and to
+ * other external memory?) are delayed until the
+ * whole load finishes. These penalties are mostly
+ * avoided by not accessing external memory for
+ * 8 cycles after the ADD(16) and 12 cycles after
+ * the LOAD(32). The loop terminates when mlen
+ * is initially 33 (not 32) to guaranteed that
+ * the LOAD(32) is within bounds.
+ */
+ ADD(16);
+ ADDC(0);
+ ADDC(4);
+ ADDC(8);
+ ADDC(12);
+ LOAD(32);
+ ADDC(20);
+ ADDC(24);
+ ADDC(28);
+ MOP;
+ w += 16;
+ }
+ mlen += 32 + 1;
+ if (mlen >= 32) {
+ ADD(16);
+ ADDC(0);
+ ADDC(4);
+ ADDC(8);
+ ADDC(12);
+ ADDC(20);
+ ADDC(24);
+ ADDC(28);
+ MOP;
+ w += 16;
+ mlen -= 32;
+ }
+ if (mlen >= 16) {
+ ADD(0);
+ ADDC(4);
+ ADDC(8);
+ ADDC(12);
+ MOP;
+ w += 8;
+ mlen -= 16;
+ }
+ if (mlen >= 8) {
+ ADD(0);
+ ADDC(4);
+ MOP;
+ w += 4;
+ mlen -= 8;
+ }
+ if (mlen == 0 && byte_swapped == 0)
+ continue; /* worth 1% maybe ?? */
+ REDUCE;
+ while ((mlen -= 2) >= 0) {
+ sum += *w++;
+ }
+ if (byte_swapped) {
+ REDUCE;
+ sum <<= 8;
+ byte_swapped = 0;
+ if (mlen == -1) {
+ s_util.c[1] = *(char *)w;
+ sum += s_util.s;
+ mlen = 0;
+ } else
+ mlen = -1;
+ } else if (mlen == -1)
+ /*
+ * This mbuf has odd number of bytes.
+ * There could be a word split betwen
+ * this mbuf and the next mbuf.
+ * Save the last byte (to prepend to next mbuf).
+ */
+ s_util.c[0] = *(char *)w;
+#else
/*
* Force to even boundary.
*/
@@ -204,6 +371,7 @@ in4_cksum(m, nxt, off, len)
mlen = -1;
} else if (mlen == -1)
s_util.c[0] = *(u_int8_t *)w;
+#endif
}
if (len)
printf("cksum4: out of data\n");
OpenPOWER on IntegriCloud