Bring diff from the security/pf port. This has code been tested as a port

for a long time and is run in production use. This is the code present in
portversion 2.03 with some additional tweaks.

The rather extensive diff accounts for:
 - locking (to enable pf to work with a giant-free netstack)
 - byte order difference between OpenBSD and FreeBSD for ip_len/ip_off
 - conversion from pool(9) to zone(9)
 - api differences etc.

Approved by: bms(mentor) (in general)
This commit is contained in:
Max Laier 2004-02-26 02:34:12 +00:00
parent 3ef891af51
commit 2bbe8ffc9d
11 changed files with 3207 additions and 52 deletions

View File

@ -1,3 +1,4 @@
/* $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),
@ -33,14 +34,32 @@
* PURPOSE.
*/
#if defined(__FreeBSD__)
#include "opt_inet.h"
#include "opt_inet6.h"
#endif
#if !defined(__FreeBSD__)
#include "bpfilter.h"
#include "pflog.h"
#elif __FreeBSD__ >= 5
#include "opt_bpf.h"
#define NBPFILTER DEV_BPF
#include "opt_pf.h"
#define NPFLOG DEV_PFLOG
#endif
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#if defined(__FreeBSD__)
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/sockio.h>
#else
#include <sys/ioctl.h>
#endif
#include <net/if.h>
#include <net/if_types.h>
@ -54,6 +73,10 @@
#include <netinet/ip.h>
#endif
#if defined(__FreeBSD__)
#include <machine/in_cksum.h>
#endif
#ifdef INET6
#ifndef INET
#include <netinet/in.h>
@ -64,6 +87,10 @@
#include <net/pfvar.h>
#include <net/if_pflog.h>
#if defined(__FreeBSD__)
#define PFLOGNAME "pflog"
#endif
#define PFLOGMTU (32768 + MHLEN + MLEN)
#ifdef PFLOGDEBUG
@ -72,17 +99,89 @@
#define DPRINTF(x)
#endif
#if !defined(__FreeBSD__)
struct pflog_softc pflogif[NPFLOG];
#endif
#if defined(__FreeBSD__)
void pflog_clone_destroy(struct ifnet *);
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 *);
#if !defined(__FreeBSD__)
extern int ifqmaxlen;
#endif
#if defined(__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);
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);
}
#endif /* __FreeBSD__ */
#if defined(__FreeBSD__)
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 +210,7 @@ pflogattach(int npflog)
#endif
}
}
#endif /* __FreeBSD__ */
/*
* Start output on the pflog interface.
@ -119,14 +219,28 @@ void
pflogstart(struct ifnet *ifp)
{
struct mbuf *m;
#if defined(__FreeBSD__) && defined(ALTQ)
struct ifaltq *ifq;
#else
struct ifqueue *ifq;
#endif
int s;
#if defined(__FreeBSD__)
ifq = &ifp->if_snd;
#endif
for (;;) {
s = splimp();
#if defined(__FreeBSD__)
IF_LOCK(ifq);
_IF_DROP(ifq);
_IF_DEQUEUE(ifq, m);
IF_UNLOCK(ifq);
#else
IF_DROP(&ifp->if_snd);
IF_DEQUEUE(&ifp->if_snd, m);
#endif
splx(s);
if (m == NULL)
return;
else
@ -188,7 +302,11 @@ pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir,
hdr.af = af;
hdr.action = rm->action;
hdr.reason = reason;
#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);
@ -221,7 +339,12 @@ pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir,
m1.m_len = PFLOG_HDRLEN;
m1.m_data = (char *) &hdr;
#if defined(__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);
@ -229,3 +352,43 @@ pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir,
return (0);
}
#if defined(__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);
printf("pflog: $Name: $\n");
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__ */

View File

@ -1,3 +1,4 @@
/* $FreeBSD$ */
/* $OpenBSD: if_pflog.h,v 1.9 2003/07/15 20:27:27 dhartmei Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@ -29,6 +30,9 @@
struct pflog_softc {
struct ifnet sc_if; /* the interface */
#if defined(__FreeBSD__)
LIST_ENTRY(pflog_softc) sc_next;
#endif
};
/* XXX keep in sync with pfvar.h */

View File

@ -1,3 +1,4 @@
/* $FreeBSD$ */
/* $OpenBSD: if_pfsync.c,v 1.6 2003/06/21 09:07:01 djm Exp $ */
/*
@ -26,16 +27,34 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(__FreeBSD__) && __FreeBSD__ >= 5
#include "opt_inet.h"
#include "opt_inet6.h"
#endif
#if !defined(__FreeBSD__)
#include "bpfilter.h"
#include "pfsync.h"
#elif __FreeBSD__ >= 5
#include "opt_bpf.h"
#define NBPFILTER DEV_BPF
#include "opt_pf.h"
#define NPFSYNC DEV_PFSYNC
#endif
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/time.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#if defined(__FreeBSD__)
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/sockio.h>
#else
#include <sys/ioctl.h>
#include <sys/timeout.h>
#endif
#include <net/if.h>
#include <net/if_types.h>
@ -57,6 +76,10 @@
#include <net/pfvar.h>
#include <net/if_pfsync.h>
#if defined(__FreeBSD__)
#define PFSYNCNAME "pfsync"
#endif
#define PFSYNC_MINMTU \
(sizeof(struct pfsync_header) + sizeof(struct pf_state))
@ -67,9 +90,16 @@ int pfsyncdebug;
#define DPRINTF(x)
#endif
#if !defined(__FreeBSD__)
struct pfsync_softc pfsyncif;
#endif
#if defined(__FreeBSD__)
void pfsync_clone_destroy(struct ifnet *);
int pfsync_clone_create(struct if_clone *, int);
#else
void pfsyncattach(int);
#endif
void pfsync_setmtu(struct pfsync_softc *sc, int);
int pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);
@ -80,8 +110,79 @@ 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);
#if !defined(__FreeBSD__)
extern int ifqmaxlen;
#endif
#if defined(__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);
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);
}
#endif /* __FreeBSD__ */
#if defined(__FreeBSD__)
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)
{
@ -109,6 +210,7 @@ pfsyncattach(int npfsync)
bpfattach(&pfsyncif.sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
#endif
}
#endif
/*
* Start output on the pfsync interface.
@ -117,12 +219,27 @@ void
pfsyncstart(struct ifnet *ifp)
{
struct mbuf *m;
#if defined(__FreeBSD__) && defined(ALTQ)
struct ifaltq *ifq;
#else
struct ifqueue *ifq;
#endif
int s;
#if defined(__FreeBSD__)
ifq = &ifp->if_snd;
#endif
for (;;) {
s = splimp();
#if defined(__FreeBSD__)
IF_LOCK(ifq);
_IF_DROP(ifq);
_IF_DEQUEUE(ifq, m);
IF_UNLOCK(ifq);
#else
IF_DROP(&ifp->if_snd);
IF_DEQUEUE(&ifp->if_snd, m);
#endif
splx(s);
if (m == NULL)
@ -192,7 +309,9 @@ pfsync_get_mbuf(sc, action)
struct pfsync_softc *sc;
u_int8_t action;
{
#if !defined(__FreeBSD__)
extern int hz;
#endif
struct pfsync_header *h;
struct mbuf *m;
int len;
@ -223,19 +342,32 @@ pfsync_get_mbuf(sc, action)
sc->sc_mbuf = m;
sc->sc_ptr = (struct pf_state *)((char *)h + PFSYNC_HDRLEN);
#if defined(__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(action, st)
u_int8_t action;
struct pf_state *st;
{
#if defined(__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;
#endif
struct pfsync_header *h;
struct pf_state *sp;
struct pf_rule *r = st->rule.ptr;
@ -246,6 +378,16 @@ pfsync_pack_state(action, st)
if (action >= PFSYNC_ACT_MAX)
return (EINVAL);
#if defined(__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();
m = sc->sc_mbuf;
if (m == NULL) {
@ -278,7 +420,11 @@ pfsync_pack_state(action, st)
pf_state_peer_hton(&st->dst, &sp->dst);
bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
#if defined(__FreeBSD__)
secs = time_second;
#else
secs = time.tv_sec;
#endif
sp->creation = htonl(secs - st->creation);
if (st->expire <= secs)
sp->expire = htonl(0);
@ -310,8 +456,12 @@ int
pfsync_clear_state(st)
struct pf_state *st;
{
#if defined(__FreeBSD__)
struct pfsync_softc *sc = LIST_FIRST(&pfsync_list);
#else
struct ifnet *ifp = &pfsyncif.sc_if;
struct pfsync_softc *sc = ifp->if_softc;
#endif
struct mbuf *m = sc->sc_mbuf;
int s, ret;
@ -332,6 +482,7 @@ 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);
@ -344,10 +495,17 @@ pfsync_sendout(sc)
struct ifnet *ifp = &sc->sc_if;
struct mbuf *m = sc->sc_mbuf;
#if defined(__FreeBSD__)
callout_stop(&sc->sc_tmo);
#else
timeout_del(&sc->sc_tmo);
#endif
sc->sc_mbuf = NULL;
sc->sc_ptr = NULL;
#if defined(__FreeBSD__)
KASSERT(m != NULL, ("pfsync_sendout: null mbuf"));
#endif
#if NBPFILTER > 0
if (ifp->if_bpf)
bpf_mtap(ifp->if_bpf, m);
@ -357,3 +515,44 @@ pfsync_sendout(sc)
return (0);
}
#if defined(__FreeBSD__)
static int
pfsync_modevent(module_t mod, int type, void *data)
{
int error = 0;
switch (type) {
case MOD_LOAD:
LIST_INIT(&pfsync_list);
if_clone_attach(&pfsync_cloner);
printf("pfsync: $Name: $\n");
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__ */

View File

@ -1,3 +1,4 @@
/* $FreeBSD$ */
/* $OpenBSD: if_pfsync.h,v 1.2 2002/12/11 18:31:26 mickey Exp $ */
/*
@ -33,10 +34,17 @@
struct pfsync_softc {
struct ifnet sc_if;
#if defined(__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 */
#if defined(__FreeBSD__)
LIST_ENTRY(pfsync_softc) sc_next;
#endif
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,4 @@
/* $FreeBSD$ */
/* $OpenBSD: pf_norm.c,v 1.75 2003/08/29 01:49:08 dhartmei Exp $ */
/*
@ -25,7 +26,15 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(__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,13 @@
#include <sys/socket.h>
#include <sys/kernel.h>
#include <sys/time.h>
#if !defined(__FreeBSD__)
#include <sys/pool.h>
#endif
#if !defined(__FreeBSD__)
#include <dev/rndvar.h>
#endif
#include <net/if.h>
#include <net/if_types.h>
#include <net/bpf.h>
@ -60,6 +73,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 */
#if !defined(__FreeBSD__)
struct pf_frent {
LIST_ENTRY(pf_frent) fr_next;
struct ip *fr_ip;
@ -71,12 +127,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))
#if !defined(__FreeBSD__)
struct pf_fragment {
RB_ENTRY(pf_fragment) fr_entry;
TAILQ_ENTRY(pf_fragment) frag_next;
@ -94,6 +152,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 +164,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 +184,28 @@ int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *,
{ printf("%s: ", __func__); printf x ;}
/* Globals */
#if defined(__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)
{
#if defined(__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,6 +221,7 @@ 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);
@ -173,11 +251,21 @@ void
pf_purge_expired_fragments(void)
{
struct pf_fragment *frag;
#if defined(__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) {
#if defined(__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 +274,26 @@ pf_purge_expired_fragments(void)
}
while ((frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue)) != NULL) {
#if defined(__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);
#if defined(__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 +352,17 @@ pf_free_fragment(struct pf_fragment *frag)
frcache = LIST_FIRST(&frag->fr_cache)) {
LIST_REMOVE(frcache, fr_next);
#if defined(__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 +392,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? */
#if defined(__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 +439,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;
#if defined(__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 +466,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;
#if defined(__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,7 +491,12 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
frep = frea;
}
#if defined(__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 *
@ -455,7 +581,11 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
/* We have all the data */
frent = LIST_FIRST(&(*frag)->fr_queue);
#if defined(__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 +654,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;
#if defined(__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 +686,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;
#if defined(__FreeBSD__)
(*frag)->fr_timeout = time_second;
#else
(*frag)->fr_timeout = time.tv_sec;
#endif
cur->fr_off = off;
cur->fr_end = max;
@ -577,7 +716,12 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
frp = fra;
}
#if defined(__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 +763,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.
*/
#if defined(__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;
#if defined(__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,8 +794,13 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
h = mtod(m, struct ip *);
#if defined(__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 {
@ -693,7 +855,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 *);
#if defined(__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++;
@ -731,7 +899,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' */
#if defined(__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,
@ -1283,7 +1456,7 @@ pf_normalize_tcp(int dir, struct ifnet *ifp, 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);
@ -1301,7 +1474,12 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
u_int8_t hdr[60];
u_int8_t *opt;
#if defined(__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)
@ -1385,7 +1563,12 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
u_int8_t *opt;
int copyback = 0;
#if defined(__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

View File

@ -1,3 +1,4 @@
/* $FreeBSD$ */
/* $OpenBSD: pf_osfp.c,v 1.3 2003/08/27 18:23:36 frantzen Exp $ */
/*
@ -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)
#if defined(__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. */
@ -55,6 +59,10 @@ typedef struct pool pool_t;
# define pool_put(pool, item) free(item)
# define pool_init(pool, size, a, ao, f, m, p) (*(pool)) = (size)
# if defined(__FreeBSD__)
# define NTOHS(x) (x) = ntohs((u_int16_t)(x))
# endif
# ifdef PFDEBUG
# include <stdarg.h>
# define DPFPRINTF(format, x...) fprintf(stderr, format , ##x)
@ -106,7 +114,7 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct tcphdr *tcp)
{
struct pf_os_fingerprint fp, *fpresult;
int cnt, optlen = 0;
u_int8_t *optp;
const u_int8_t *optp;
if ((tcp->th_flags & (TH_SYN|TH_ACK)) != TH_SYN || (ip->ip_off &
htons(IP_OFFMASK)))
@ -122,7 +130,7 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct tcphdr *tcp)
cnt = (tcp->th_off << 2) - sizeof(*tcp);
optp = (caddr_t)tcp + sizeof(*tcp);
optp = (const u_int8_t *)((const char *)tcp + sizeof(*tcp));
for (; cnt > 0; cnt -= optlen, optp += optlen) {
if (*optp == TCPOPT_EOL)
break;
@ -228,16 +236,47 @@ pf_osfp_match(struct pf_osfp_enlist *list, pf_osfp_t os)
}
/* Initialize the OS fingerprint system */
#if defined(__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);
#if defined(__FreeBSD__)
#if defined(_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
pf_osfp_flush(void)

View File

@ -1,3 +1,4 @@
/* $FreeBSD$ */
/* $OpenBSD: pf_table.c,v 1.41 2003/08/22 15:19:23 henning Exp $ */
/*
@ -30,18 +31,33 @@
*
*/
#if defined(__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>
#if defined(__FreeBSD__)
#include <sys/malloc.h>
#endif
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#if !defined(__FreeBSD__)
#include <netinet/ip_ipsp.h>
#endif
#include <net/pfvar.h>
#if defined(FreeBSD__)
MALLOC_DECLARE(M_RTABLE);
#endif
#define ACCEPT_FLAGS(oklist) \
do { \
if ((flags & ~(oklist)) & \
@ -109,8 +125,13 @@ struct pfr_walktree {
#define senderr(e) do { rv = (e); goto _bad; } while (0)
#if defined(__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;
@ -172,10 +193,12 @@ int pfr_ktable_cnt;
void
pfr_initialize(void)
{
#if !defined(__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;
@ -226,7 +249,15 @@ 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;
#if defined(__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))
@ -241,8 +272,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 defined(__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);
@ -269,9 +306,17 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
xadd++;
}
}
#if defined(__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)))
senderr(EFAULT);
#endif
}
pfr_clean_node_mask(tmpkt, &workq);
if (!(flags & PFR_FLAG_DUMMY)) {
@ -304,6 +349,9 @@ 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;
#if defined(__FreeBSD__)
int ec;
#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
if (pfr_validate_table(tbl, 0))
@ -316,8 +364,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 defined(__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);
@ -337,9 +391,17 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
xdel++;
}
#if defined(__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)))
senderr(EFAULT);
#endif
}
if (!(flags & PFR_FLAG_DUMMY)) {
if (flags & PFR_FLAG_ATOMIC)
@ -366,7 +428,15 @@ 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;
#if defined(__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))
@ -384,8 +454,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 defined(__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;
@ -420,9 +496,17 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
}
}
_skip:
#if defined(__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)))
senderr(EFAULT);
#endif
}
pfr_enqueue_addrs(kt, &delq, &xdel, ENQUEUE_UNMARKED_ONLY);
if ((flags & PFR_FLAG_FEEDBACK) && *size2) {
@ -434,8 +518,14 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
SLIST_FOREACH(p, &delq, pfrke_workq) {
pfr_copyout_addr(&ad, p);
ad.pfra_fback = PFR_FB_DELETED;
#if defined(__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++;
}
}
@ -477,6 +567,9 @@ 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;
#if defined(__FreeBSD__)
int ec;
#endif
ACCEPT_FLAGS(PFR_FLAG_REPLACE);
if (pfr_validate_table(tbl, 0))
@ -486,8 +579,14 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (ESRCH);
for (i = 0; i < size; i++) {
#if defined(__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))
@ -499,8 +598,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 defined(__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,9 +635,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;
#if defined(__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)
#if defined(__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);
@ -553,7 +667,14 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
struct pfr_walktree w;
struct pfr_kentryworkq workq;
int rv, s;
#if defined(__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))
@ -572,9 +693,18 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
w.pfrw_free = kt->pfrkt_cnt;
if (flags & PFR_FLAG_ATOMIC)
s = splsoftnet();
#if defined(__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)
#if defined(__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);
@ -602,6 +732,9 @@ 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;
#if defined(__FreeBSD__)
int ec;
#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
if (pfr_validate_table(tbl, 0))
@ -611,16 +744,28 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (ESRCH);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
#if defined(__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 defined(__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);
@ -685,10 +830,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)
#if defined(__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)
#if defined(__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;
@ -701,9 +856,17 @@ pfr_mark_addrs(struct pfr_ktable *kt)
bzero(&w, sizeof(w));
w.pfrw_op = PFRW_MARK;
#if defined(__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");
#if defined(__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");
}
@ -727,7 +890,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;
@ -845,13 +1014,28 @@ pfr_reset_feedback(struct pfr_addr *addr, int size)
{
struct pfr_addr ad;
int i;
#if defined(__FreeBSD__)
int ec;
#endif
for (i = 0; i < size; i++) {
#if defined(__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 defined(__FreeBSD__)
PF_COPYOUT(&ad, addr+i, sizeof(ad), ec);
if (ec)
break;
#else
if (copyout(&ad, addr+i, sizeof(ad)))
break;
#endif
}
}
@ -895,11 +1079,17 @@ pfr_route_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
head = kt->pfrkt_ip6;
s = splsoftnet();
#if defined(__FreeBSD__) && (__FreeBSD_version >= 500100)
RADIX_NODE_HEAD_LOCK(head);
#endif
if (KENTRY_NETWORK(ke)) {
pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net);
rn = rn_addroute(&ke->pfrke_sa, &mask, head, ke->pfrke_node);
} else
rn = rn_addroute(&ke->pfrke_sa, NULL, head, ke->pfrke_node);
#if defined(__FreeBSD__) && (__FreeBSD_version >= 500100)
RADIX_NODE_HEAD_UNLOCK(head);
#endif
splx(s);
return (rn == NULL ? -1 : 0);
@ -919,11 +1109,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) {
@ -954,6 +1150,9 @@ pfr_walktree(struct radix_node *rn, void *arg)
struct pfr_kentry *ke = (struct pfr_kentry *)rn;
struct pfr_walktree *w = arg;
int s;
#if defined(__FreeBSD__)
int ec;
#endif
switch (w->pfrw_op) {
case PFRW_MARK:
@ -972,8 +1171,14 @@ pfr_walktree(struct radix_node *rn, void *arg)
struct pfr_addr ad;
pfr_copyout_addr(&ad, ke);
#if defined(__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;
@ -991,8 +1196,14 @@ pfr_walktree(struct radix_node *rn, void *arg)
splx(s);
as.pfras_tzero = ke->pfrke_tzero;
#if defined(__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;
@ -1047,14 +1258,28 @@ 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;
#if defined(__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 defined(__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);
#endif
if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK))
senderr(EINVAL);
key.pfrkt_flags |= PFR_TFLAG_ACTIVE;
@ -1127,12 +1352,21 @@ 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;
#if defined(__FreeBSD__)
int ec;
#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
#if defined(__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);
#endif
if (pfr_validate_table(&key.pfrkt_t, 0))
return (EINVAL);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
@ -1166,6 +1400,9 @@ pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
{
struct pfr_ktable *p;
int n, nn;
#if defined(__FreeBSD__)
int ec;
#endif
ACCEPT_FLAGS(PFR_FLAG_ALLRSETS);
n = nn = pfr_table_count(filter, flags);
@ -1180,8 +1417,14 @@ pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
continue;
if (n-- <= 0)
continue;
#if defined(__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);
@ -1198,7 +1441,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;
#if defined(__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 */
@ -1219,10 +1470,18 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
continue;
if (!(flags & PFR_FLAG_ATOMIC))
s = splsoftnet();
#if defined(__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);
@ -1246,13 +1505,27 @@ 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;
#if defined(__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 defined(__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);
#endif
if (pfr_validate_table(&key.pfrkt_t, 0))
return (EINVAL);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
@ -1280,6 +1553,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;
#if defined(__FreeBSD__)
int ec;
#endif
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
if ((setflag & ~PFR_TFLAG_USRMASK) ||
@ -1288,8 +1564,14 @@ 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 defined(__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);
#endif
if (pfr_validate_table(&key.pfrkt_t, 0))
return (EINVAL);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
@ -1370,6 +1652,9 @@ 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;
#if defined(__FreeBSD__)
int ec;
#endif
ACCEPT_FLAGS(PFR_FLAG_DUMMY|PFR_FLAG_ADDRSTOO);
if (size && !(flags & PFR_FLAG_ADDRSTOO))
@ -1416,8 +1701,14 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
}
SLIST_INIT(&addrq);
for (i = 0; i < size; i++) {
#if defined(__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)
@ -1466,7 +1757,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;
#if defined(__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);
@ -1761,10 +2059,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) {
@ -1883,7 +2192,14 @@ pfr_attach_table(struct pf_ruleset *rs, char *name)
}
kt = pfr_lookup_table(&tbl);
if (kt == NULL) {
#if defined(__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) {
@ -1917,6 +2233,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)
@ -2006,13 +2323,20 @@ pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
switch(af) {
case AF_INET:
#if defined(__FreeBSD__)
kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
#else
rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
#endif
return w.pfrw_kentry;
case AF_INET6:
#if defined(__FreeBSD__)
kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
#else
rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
#endif
return w.pfrw_kentry;
default:
return NULL;
}
}

View File

@ -1,3 +1,4 @@
/* $FreeBSD$ */
/* $OpenBSD: pfvar.h,v 1.170 2003/08/22 21:50:34 david Exp $ */
/*
@ -38,7 +39,26 @@
#include <sys/tree.h>
#include <net/radix.h>
#if defined(__FreeBSD__)
#include <vm/uma.h>
#else
#include <netinet/ip_ipsp.h>
#endif
#if defined(__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;
@ -119,7 +139,11 @@ struct pf_addr_dyn {
struct ifnet *ifp;
struct pf_addr *addr;
sa_family_t af;
#if defined(__FreeBSD__) && defined(HOOK_HACK)
eventhandler_tag hook_cookie;
#else
void *hook_cookie;
#endif
u_int8_t undefined;
};
@ -129,6 +153,66 @@ struct pf_addr_dyn {
#ifdef _KERNEL
#if defined(__FreeBSD__)
#define splsoftnet() splnet()
#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;
#if defined(ALTQ)
extern struct mtx pf_altq_mtx;
extern int pfaltq_ref;
#endif
#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
@ -1101,6 +1185,13 @@ struct pfioc_table {
#define DIOCOSFPFLUSH _IO('D', 78)
#define DIOCOSFPADD _IOWR('D', 79, struct pf_osfp_ioctl)
#define DIOCOSFPGET _IOWR('D', 80, struct pf_osfp_ioctl)
#if defined(__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_state_tree, pf_tree_node);
@ -1135,9 +1226,17 @@ 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);
#if defined(__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_states(void);
extern int pf_insert_state(struct pf_state *);
@ -1234,7 +1333,12 @@ void pf_tag_unref(u_int16_t);
int pf_tag_packet(struct mbuf *, struct pf_tag *, int);
extern struct pf_status pf_status;
#if defined(__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;
@ -1242,6 +1346,38 @@ struct pf_pool_limit {
};
extern struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX];
#if defined(__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) */
@ -1255,7 +1391,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 *);
#if defined(__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);

View File

@ -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");