Commit resolved import of OpenBSD 4.1 pf from perforce.

Approved by:	re (kensmith)
This commit is contained in:
Max Laier 2007-07-03 12:16:07 +00:00
parent b2630c2934
commit c9a03d91ad
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=171168
13 changed files with 3738 additions and 2816 deletions

View File

@ -1,6 +1,4 @@
/* $FreeBSD$ */
/* $OpenBSD: if_pflog.c,v 1.12 2004/05/19 17:50:51 dhartmei Exp $ */
/* $OpenBSD: if_pflog.c,v 1.22 2006/12/15 09:31:20 otto Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@ -38,15 +36,12 @@
#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"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#ifdef DEV_BPF
#define NBPFILTER DEV_BPF
#else
@ -59,14 +54,19 @@
#define NPFLOG 0
#endif
#endif
#else /* ! __FreeBSD__ */
#include "bpfilter.h"
#include "pflog.h"
#endif /* __FreeBSD__ */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/proc.h>
#include <sys/socket.h>
#ifdef __FreeBSD__
#include <sys/kernel.h>
#include <sys/limits.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/sockio.h>
@ -75,7 +75,7 @@
#endif
#include <net/if.h>
#if defined(__FreeBSD__)
#ifdef __FreeBSD__
#include <net/if_clone.h>
#endif
#include <net/if_types.h>
@ -89,10 +89,6 @@
#include <netinet/ip.h>
#endif
#ifdef __FreeBSD__
#include <machine/in_cksum.h>
#endif
#ifdef INET6
#ifndef INET
#include <netinet/in.h>
@ -104,7 +100,7 @@
#include <net/if_pflog.h>
#ifdef __FreeBSD__
#define PFLOGNAME "pflog"
#include <machine/in_cksum.h>
#endif
#define PFLOGMTU (32768 + MHLEN + MLEN)
@ -115,115 +111,148 @@
#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, caddr_t);
#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 *);
#ifdef __FreeBSD__
static int pflog_clone_create(struct if_clone *, int, caddr_t);
static void pflog_clone_destroy(struct ifnet *);
#else
int pflog_clone_create(struct if_clone *, int);
int pflog_clone_destroy(struct ifnet *);
#endif
LIST_HEAD(, pflog_softc) pflogif_list;
#ifdef __FreeBSD__
IFC_SIMPLE_DECLARE(pflog, 1);
#else
struct if_clone pflog_cloner =
IF_CLONE_INITIALIZER("pflog", pflog_clone_create, pflog_clone_destroy);
#endif
struct ifnet *pflogifs[PFLOGIFS_MAX]; /* for fast access */
#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;
#define SCP2IFP(sc) ((sc)->sc_ifp)
IFC_SIMPLE_DECLARE(pflog, 1);
static void
pflog_clone_destroy(struct ifnet *ifp)
void
pflogattach(int npflog)
{
struct pflog_softc *sc;
sc = ifp->if_softc;
/*
* Does we really need this?
*/
IF_DRAIN(&ifp->if_snd);
bpfdetach(ifp);
if_detach(ifp);
if_free(ifp);
LIST_REMOVE(sc, sc_next);
free(sc, M_PFLOG);
int i;
LIST_INIT(&pflogif_list);
for (i = 0; i < PFLOGIFS_MAX; i++)
pflogifs[i] = NULL;
#ifndef __FreeBSD__
(void) pflog_clone_create(&pflog_cloner, 0);
#endif
if_clone_attach(&pflog_cloner);
}
static int
#ifdef __FreeBSD__
pflog_clone_create(struct if_clone *ifc, int unit, caddr_t params)
static int
pflog_clone_create(struct if_clone *ifc, int unit, caddr_t param)
#else
int
pflog_clone_create(struct if_clone *ifc, int unit)
#endif
{
struct pflog_softc *sc;
struct ifnet *ifp;
struct pflog_softc *pflogif;
int s;
MALLOC(sc, struct pflog_softc *, sizeof(*sc), M_PFLOG, M_WAITOK|M_ZERO);
ifp = sc->sc_ifp = if_alloc(IFT_PFLOG);
if (unit >= PFLOGIFS_MAX)
return (EINVAL);
if ((pflogif = malloc(sizeof(*pflogif), M_DEVBUF, M_NOWAIT)) == NULL)
return (ENOMEM);
bzero(pflogif, sizeof(*pflogif));
pflogif->sc_unit = unit;
#ifdef __FreeBSD__
ifp = pflogif->sc_ifp = if_alloc(IFT_PFLOG);
if (ifp == NULL) {
free(sc, M_PFLOG);
free(pflogif, M_DEVBUF);
return (ENOSPC);
}
if_initname(ifp, ifc->ifc_name, unit);
#else
ifp = &pflogif->sc_if;
snprintf(ifp->if_xname, sizeof ifp->if_xname, "pflog%d", unit);
#endif
ifp->if_softc = pflogif;
ifp->if_mtu = PFLOGMTU;
ifp->if_ioctl = pflogioctl;
ifp->if_output = pflogoutput;
ifp->if_start = pflogstart;
#ifndef __FreeBSD__
ifp->if_type = IFT_PFLOG;
#endif
ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_hdrlen = PFLOG_HDRLEN;
ifp->if_softc = sc;
if_attach(ifp);
LIST_INSERT_HEAD(&pflog_list, sc, sc_next);
#if NBPFILTER > 0
bpfattach(ifp, DLT_PFLOG, PFLOG_HDRLEN);
#ifndef __FreeBSD__
if_alloc_sadl(ifp);
#endif
#if NBPFILTER > 0
#ifdef __FreeBSD__
bpfattach(ifp, DLT_PFLOG, PFLOG_HDRLEN);
#else
bpfattach(&pflogif->sc_if.if_bpf, ifp, DLT_PFLOG, PFLOG_HDRLEN);
#endif
#endif
s = splnet();
#ifdef __FreeBSD__
PF_LOCK();
#endif
LIST_INSERT_HEAD(&pflogif_list, pflogif, sc_list);
pflogifs[unit] = ifp;
#ifdef __FreeBSD__
PF_UNLOCK();
#endif
splx(s);
return (0);
}
#else /* !__FreeBSD__ */
void
pflogattach(int npflog)
#ifdef __FreeBSD__
static void
pflog_clone_destroy(struct ifnet *ifp)
#else
int
pflog_clone_destroy(struct ifnet *ifp)
#endif
{
struct ifnet *ifp;
int i;
struct pflog_softc *pflogif = ifp->if_softc;
int s;
bzero(pflogif, sizeof(pflogif));
for (i = 0; i < NPFLOG; i++) {
ifp = &pflogif[i].sc_if;
snprintf(ifp->if_xname, sizeof ifp->if_xname, "pflog%d", i);
ifp->if_softc = &pflogif[i];
ifp->if_mtu = PFLOGMTU;
ifp->if_ioctl = pflogioctl;
ifp->if_output = pflogoutput;
ifp->if_start = pflogstart;
ifp->if_type = IFT_PFLOG;
ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_hdrlen = PFLOG_HDRLEN;
if_attach(ifp);
if_alloc_sadl(ifp);
s = splnet();
#ifdef __FreeBSD__
PF_LOCK();
#endif
pflogifs[pflogif->sc_unit] = NULL;
LIST_REMOVE(pflogif, sc_list);
#ifdef __FreeBSD__
PF_UNLOCK();
#endif
splx(s);
#if NBPFILTER > 0
bpfattach(&pflogif[i].sc_if.if_bpf, ifp, DLT_PFLOG,
PFLOG_HDRLEN);
bpfdetach(ifp);
#endif
if_detach(ifp);
#ifdef __FreeBSD__
if_free(ifp);
#endif
free(pflogif, M_DEVBUF);
#ifndef __FreeBSD__
return (0);
#endif
}
}
#endif /* __FreeBSD__ */
/*
* Start output on the pflog interface.
@ -241,23 +270,18 @@ pflogstart(struct ifnet *ifp)
IF_LOCK(&ifp->if_snd);
_IF_DROP(&ifp->if_snd);
_IF_DEQUEUE(&ifp->if_snd, m);
if (m == NULL) {
IF_UNLOCK(&ifp->if_snd);
return;
}
else
m_freem(m);
IF_UNLOCK(&ifp->if_snd);
IF_UNLOCK(&ifp->if_snd);
#else
s = splimp();
s = splnet();
IF_DROP(&ifp->if_snd);
IF_DEQUEUE(&ifp->if_snd, m);
splx(s);
#endif
if (m == NULL)
return;
else
m_freem(m);
#endif
}
}
@ -269,14 +293,6 @@ pflogoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
return (0);
}
/* ARGSUSED */
void
pflogrtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa)
{
if (rt)
rt->rt_rmx.rmx_mtu = PFLOGMTU;
}
/* ARGSUSED */
int
pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
@ -308,18 +324,18 @@ 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,
u_int8_t reason, struct pf_rule *rm, struct pf_rule *am,
struct pf_ruleset *ruleset)
struct pf_ruleset *ruleset, struct pf_pdesc *pd)
{
#if NBPFILTER > 0
struct ifnet *ifn;
struct pfloghdr hdr;
#ifndef __FreeBSD__
struct mbuf m1;
#endif
if (kif == NULL || m == NULL || rm == NULL)
if (kif == NULL || m == NULL || rm == NULL || pd == NULL)
return (-1);
if ((ifn = pflogifs[rm->logif]) == NULL || !ifn->if_bpf)
return (0);
bzero(&hdr, sizeof(hdr));
hdr.length = PFLOG_REAL_HDRLEN;
hdr.af = af;
@ -337,6 +353,25 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
strlcpy(hdr.ruleset, ruleset->anchor->name,
sizeof(hdr.ruleset));
}
if (rm->log & PF_LOG_SOCKET_LOOKUP && !pd->lookup.done)
#ifdef __FreeBSD__
/*
* XXX: This should not happen as we force an early lookup
* via debug.pfugidhack
*/
; /* empty */
#else
pd->lookup.done = pf_socket_lookup(dir, pd);
#endif
if (pd->lookup.done > 0) {
hdr.uid = pd->lookup.uid;
hdr.pid = pd->lookup.pid;
} else {
hdr.uid = UID_MAX;
hdr.pid = NO_PID;
}
hdr.rule_uid = rm->cuid;
hdr.rule_pid = rm->cpid;
hdr.dir = dir;
#ifdef INET
@ -349,21 +384,13 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
}
#endif /* INET */
#ifndef __FreeBSD__
m1.m_next = m;
m1.m_len = PFLOG_HDRLEN;
m1.m_data = (char *) &hdr;
#endif
ifn->if_opackets++;
ifn->if_obytes += m->m_pkthdr.len;
#ifdef __FreeBSD__
KASSERT((!LIST_EMPTY(&pflog_list)), ("pflog: no interface"));
ifn = SCP2IFP(LIST_FIRST(&pflog_list));
BPF_MTAP2(ifn, &hdr, sizeof(hdr), m);
BPF_MTAP2(ifn, &hdr, PFLOG_HDRLEN, m);
#else
ifn = &(pflogif[0].sc_if);
if (ifn->if_bpf)
bpf_mtap(ifn->if_bpf, &m1);
bpf_mtap_hdr(ifn->if_bpf, (char *)&hdr, PFLOG_HDRLEN, m,
BPF_DIRECTION_OUT);
#endif
#endif
@ -378,20 +405,17 @@ pflog_modevent(module_t mod, int type, void *data)
switch (type) {
case MOD_LOAD:
LIST_INIT(&pflog_list);
if_clone_attach(&pflog_cloner);
pflogattach(1);
PF_LOCK();
pflog_packet_ptr = pflog_packet;
PF_UNLOCK();
break;
case MOD_UNLOAD:
PF_LOCK();
pflog_packet_ptr = NULL;
PF_UNLOCK();
if_clone_detach(&pflog_cloner);
break;
default:
error = EINVAL;
break;
@ -400,11 +424,7 @@ pflog_modevent(module_t mod, int type, void *data)
return error;
}
static moduledata_t pflog_mod = {
"pflog",
pflog_modevent,
0
};
static moduledata_t pflog_mod = { "pflog", pflog_modevent, 0 };
#define PFLOG_MODVER 1

View File

@ -1,6 +1,5 @@
/* $FreeBSD$ */
/* $OpenBSD: if_pflog.h,v 1.11 2004/05/19 17:50:51 dhartmei Exp $ */
/* $FreeBSD$ */
/* $OpenBSD: if_pflog.h,v 1.14 2006/10/25 11:27:01 henning Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@ -29,14 +28,19 @@
#ifndef _NET_IF_PFLOG_H_
#define _NET_IF_PFLOG_H_
#define PFLOGIFS_MAX 16
#ifdef _KERNEL
struct pflog_softc {
#ifdef __FreeBSD__
struct ifnet *sc_ifp; /* the interface */
LIST_ENTRY(pflog_softc) sc_next;
struct ifnet *sc_ifp; /* the interface pointer */
#else
struct ifnet sc_if; /* the interface */
struct ifnet sc_if; /* the interface */
#endif
int sc_unit;
LIST_ENTRY(pflog_softc) sc_list;
};
#endif /* _KERNEL */
#define PFLOG_RULESET_NAME_SIZE 16
@ -49,6 +53,10 @@ struct pfloghdr {
char ruleset[PFLOG_RULESET_NAME_SIZE];
u_int32_t rulenr;
u_int32_t subrulenr;
uid_t uid;
pid_t pid;
uid_t rule_uid;
pid_t rule_pid;
u_int8_t dir;
u_int8_t pad[3];
};
@ -74,20 +82,21 @@ struct old_pfloghdr {
struct pf_rule;
struct pf_ruleset;
struct pfi_kif;
struct pf_pdesc;
typedef int pflog_packet_t(struct pfi_kif *, struct mbuf *, sa_family_t,
u_int8_t, u_int8_t, struct pf_rule *, struct pf_rule *,
struct pf_ruleset *);
struct pf_ruleset *, struct pf_pdesc *);
extern pflog_packet_t *pflog_packet_ptr;
#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g) do { \
if (pflog_packet_ptr != NULL) \
pflog_packet_ptr(i,a,b,c,d,e,f,g); \
#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g,h) do { \
if (pflog_packet_ptr != NULL) \
pflog_packet_ptr(i,a,b,c,d,e,f,g,h); \
} while (0)
#else
#else /* ! __FreeBSD__ */
#if NPFLOG > 0
#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g) pflog_packet(i,a,b,c,d,e,f,g)
#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g,h) pflog_packet(i,a,b,c,d,e,f,g,h)
#else
#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g) ((void)0)
#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g,h) ((void)0)
#endif /* NPFLOG > 0 */
#endif /* __FreeBSD__ */
#endif /* _KERNEL */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* $FreeBSD$ */
/* $OpenBSD: if_pfsync.h,v 1.19 2005/01/20 17:47:38 mcbride Exp $ */
/* $OpenBSD: if_pfsync.h,v 1.30 2006/10/31 14:49:01 henning Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@ -36,6 +36,7 @@
struct pfsync_state_scrub {
u_int16_t pfss_flags;
u_int8_t pfss_ttl; /* stashed TTL */
#define PFSYNC_SCRUB_FLAG_VALID 0x01
u_int8_t scrub_flag;
u_int32_t pfss_ts_mod; /* timestamp modulation */
} __packed;
@ -55,8 +56,7 @@ struct pfsync_state_peer {
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];
u_int8_t pad[6];
} __packed;
struct pfsync_state {
@ -73,8 +73,8 @@ struct pfsync_state {
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 packets[2][2];
u_int32_t bytes[2][2];
u_int32_t creatorid;
sa_family_t af;
u_int8_t proto;
@ -89,6 +89,18 @@ struct pfsync_state {
#define PFSYNC_FLAG_COMPRESS 0x01
#define PFSYNC_FLAG_STALE 0x02
#ifdef PFSYNC_TDB
struct pfsync_tdb {
u_int32_t spi;
union sockaddr_union dst;
u_int32_t rpl;
u_int64_t cur_bytes;
u_int8_t sproto;
u_int8_t updates;
u_int8_t pad[2];
} __packed;
#endif
struct pfsync_state_upd {
u_int32_t id[2];
struct pfsync_state_peer src;
@ -144,6 +156,12 @@ union sc_statep {
struct pfsync_state_upd_req *r;
};
#ifdef PFSYNC_TDB
union sc_tdb_statep {
struct pfsync_tdb *t;
};
#endif
extern int pfsync_sync_ok;
struct pfsync_softc {
@ -157,10 +175,14 @@ struct pfsync_softc {
struct ip_moptions sc_imo;
#ifdef __FreeBSD__
struct callout sc_tmo;
#ifdef PFSYNC_TDB
struct callout sc_tdb_tmo;
#endif
struct callout sc_bulk_tmo;
struct callout sc_bulkfail_tmo;
#else
struct timeout sc_tmo;
struct timeout sc_tdb_tmo;
struct timeout sc_bulk_tmo;
struct timeout sc_bulkfail_tmo;
#endif
@ -168,28 +190,37 @@ struct pfsync_softc {
struct in_addr sc_sendaddr;
struct mbuf *sc_mbuf; /* current cumulative mbuf */
struct mbuf *sc_mbuf_net; /* current cumulative mbuf */
#ifdef PFSYNC_TDB
struct mbuf *sc_mbuf_tdb; /* dito for TDB updates */
#endif
#ifdef __FreeBSD__
struct ifqueue sc_ifq;
struct callout sc_send_tmo;
struct task sc_send_task;
#endif
union sc_statep sc_statep;
union sc_statep sc_statep_net;
#ifdef PFSYNC_TDB
union sc_tdb_statep sc_statep_tdb;
#endif
u_int32_t sc_ureq_received;
u_int32_t sc_ureq_sent;
struct pf_state *sc_bulk_send_next;
struct pf_state *sc_bulk_terminator;
int sc_bulk_tries;
int sc_maxcount; /* number of states in mtu */
int sc_maxupdates; /* number of updates/state */
#ifdef __FreeBSD__
LIST_ENTRY(pfsync_softc) sc_next;
eventhandler_tag sc_detachtag;
#endif
};
extern struct pfsync_softc *pfsyncif;
#endif
struct pfsync_header {
u_int8_t version;
#define PFSYNC_VERSION 2
#define PFSYNC_VERSION 3
u_int8_t af;
u_int8_t action;
#define PFSYNC_ACT_CLR 0 /* clear all states */
@ -202,8 +233,10 @@ struct pfsync_header {
#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_TDB_UPD 10 /* TDB replay counter update */
#define PFSYNC_ACT_MAX 11
u_int8_t count;
u_int8_t pf_chksum[PF_MD5_DIGEST_LENGTH];
} __packed;
#define PFSYNC_BULKPACKETS 1 /* # of packets per timeout */
@ -212,7 +245,7 @@ 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"
"UPD REQ", "BLK UPD STAT", "TDB UPD"
#define PFSYNC_DFLTTL 255
@ -259,6 +292,13 @@ struct pfsyncreq {
(d)->mss = htons((s)->mss); \
(d)->state = (s)->state; \
(d)->wscale = (s)->wscale; \
if ((s)->scrub) { \
(d)->scrub.pfss_flags = \
htons((s)->scrub->pfss_flags & PFSS_TIMESTAMP); \
(d)->scrub.pfss_ttl = (s)->scrub->pfss_ttl; \
(d)->scrub.pfss_ts_mod = htonl((s)->scrub->pfss_ts_mod);\
(d)->scrub.scrub_flag = PFSYNC_SCRUB_FLAG_VALID; \
} \
} while (0)
#define pf_state_peer_ntoh(s,d) do { \
@ -269,6 +309,13 @@ struct pfsyncreq {
(d)->mss = ntohs((s)->mss); \
(d)->state = (s)->state; \
(d)->wscale = (s)->wscale; \
if ((s)->scrub.scrub_flag == PFSYNC_SCRUB_FLAG_VALID && \
(d)->scrub != NULL) { \
(d)->scrub->pfss_flags = \
ntohs((s)->scrub.pfss_flags) & PFSS_TIMESTAMP; \
(d)->scrub->pfss_ttl = (s)->scrub.pfss_ttl; \
(d)->scrub->pfss_ts_mod = ntohl((s)->scrub.pfss_ts_mod);\
} \
} while (0)
#define pf_state_host_hton(s,d) do { \
@ -281,6 +328,17 @@ struct pfsyncreq {
(d)->port = (s)->port; \
} while (0)
#define pf_state_counter_hton(s,d) do { \
d[0] = htonl((s>>32)&0xffffffff); \
d[1] = htonl(s&0xffffffff); \
} while (0)
#define pf_state_counter_ntoh(s,d) do { \
d = ntohl(s[0]); \
d = d<<32; \
d += ntohl(s[1]); \
} while (0)
#ifdef _KERNEL
#ifdef __FreeBSD__
void pfsync_input(struct mbuf *, __unused int);
@ -294,7 +352,8 @@ int pfsync_pack_state(u_int8_t, struct pf_state *, int);
(st->proto == IPPROTO_PFSYNC)) \
st->sync_flags |= PFSTATE_NOSYNC; \
else if (!st->sync_flags) \
pfsync_pack_state(PFSYNC_ACT_INS, (st), 1); \
pfsync_pack_state(PFSYNC_ACT_INS, (st), \
PFSYNC_FLAG_COMPRESS); \
st->sync_flags &= ~PFSTATE_FROMSYNC; \
} while (0)
#define pfsync_update_state(st) do { \
@ -307,8 +366,10 @@ int pfsync_pack_state(u_int8_t, struct pf_state *, int);
if (!st->sync_flags) \
pfsync_pack_state(PFSYNC_ACT_DEL, (st), \
PFSYNC_FLAG_COMPRESS); \
st->sync_flags &= ~PFSTATE_FROMSYNC; \
} while (0)
#ifdef PFSYNC_TDB
int pfsync_update_tdb(struct tdb *, int);
#endif
#endif
#endif /* _NET_IF_PFSYNC_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,4 @@
/* $FreeBSD$ */
/* $OpenBSD: pf_norm.c,v 1.97 2004/09/21 16:59:12 aaron Exp $ */
/* add: $OpenBSD: pf_norm.c,v 1.106 2006/03/25 20:55:24 dhartmei Exp $ */
/* $OpenBSD: pf_norm.c,v 1.107 2006/04/16 00:59:52 pascoe Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@ -31,6 +29,10 @@
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_pf.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#ifdef DEV_PFLOG
#define NPFLOG DEV_PFLOG
#else
@ -493,7 +495,7 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
break;
}
/* This fragment is completely overlapped, loose it */
/* This fragment is completely overlapped, lose it */
next = LIST_NEXT(frea, fr_next);
m_freem(frea->fr_m);
LIST_REMOVE(frea, fr_next);
@ -966,8 +968,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 (pfi_kif_match(r->kif, kif) == r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@ -976,19 +977,23 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
else if (r->proto && r->proto != h->ip_p)
r = r->skip[PF_SKIP_PROTO].ptr;
else if (PF_MISMATCHAW(&r->src.addr,
(struct pf_addr *)&h->ip_src.s_addr, AF_INET, r->src.neg))
(struct pf_addr *)&h->ip_src.s_addr, AF_INET,
r->src.neg, kif))
r = r->skip[PF_SKIP_SRC_ADDR].ptr;
else if (PF_MISMATCHAW(&r->dst.addr,
(struct pf_addr *)&h->ip_dst.s_addr, AF_INET, r->dst.neg))
(struct pf_addr *)&h->ip_dst.s_addr, AF_INET,
r->dst.neg, NULL))
r = r->skip[PF_SKIP_DST_ADDR].ptr;
else
break;
}
if (r == NULL)
if (r == NULL || r->action == PF_NOSCRUB)
return (PF_PASS);
else
r->packets++;
else {
r->packets[dir == PF_OUT]++;
r->bytes[dir == PF_OUT] += pd->tot_len;
}
/* Check for illegal packets */
if (hlen < (int)sizeof(struct ip))
@ -1061,6 +1066,18 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
if (m == NULL)
return (PF_DROP);
/* use mtag from concatenated mbuf chain */
pd->pf_mtag = pf_find_mtag(m);
#ifdef DIAGNOSTIC
if (pd->pf_mtag == NULL) {
printf("%s: pf_find_mtag returned NULL(1)\n", __func__);
if ((pd->pf_mtag = pf_get_mtag(m)) == NULL) {
m_freem(m);
*m0 = NULL;
goto no_mem;
}
}
#endif
if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
goto drop;
@ -1069,15 +1086,13 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
/* non-buffering fragment cache (drops or masks overlaps) */
int nomem = 0;
if (dir == PF_OUT) {
if (m_tag_find(m, PACKET_TAG_PF_FRAGCACHE, NULL) !=
NULL) {
/* Already passed the fragment cache in the
* input direction. If we continued, it would
* appear to be a dup and would be dropped.
*/
goto fragment_pass;
}
if (dir == PF_OUT && pd->pf_mtag->flags & PF_TAG_FRAGCACHE) {
/*
* Already passed the fragment cache in the
* input direction. If we continued, it would
* appear to be a dup and would be dropped.
*/
goto fragment_pass;
}
frag = pf_find_fragment(h, &pf_cache_tree);
@ -1098,14 +1113,21 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
goto drop;
}
if (dir == PF_IN) {
struct m_tag *mtag;
mtag = m_tag_get(PACKET_TAG_PF_FRAGCACHE, 0, M_NOWAIT);
if (mtag == NULL)
/* use mtag from copied and trimmed mbuf chain */
pd->pf_mtag = pf_find_mtag(m);
#ifdef DIAGNOSTIC
if (pd->pf_mtag == NULL) {
printf("%s: pf_find_mtag returned NULL(2)\n", __func__);
if ((pd->pf_mtag = pf_get_mtag(m)) == NULL) {
m_freem(m);
*m0 = NULL;
goto no_mem;
m_tag_prepend(m, mtag);
}
}
#endif
if (dir == PF_IN)
pd->pf_mtag->flags |= PF_TAG_FRAGCACHE;
if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
goto drop;
goto fragment_pass;
@ -1154,13 +1176,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(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
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(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
bad:
@ -1172,7 +1194,7 @@ 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(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
}
@ -1200,8 +1222,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 (pfi_kif_match(r->kif, kif) == r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@ -1212,19 +1233,23 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
r = r->skip[PF_SKIP_PROTO].ptr;
#endif
else if (PF_MISMATCHAW(&r->src.addr,
(struct pf_addr *)&h->ip6_src, AF_INET6, r->src.neg))
(struct pf_addr *)&h->ip6_src, AF_INET6,
r->src.neg, kif))
r = r->skip[PF_SKIP_SRC_ADDR].ptr;
else if (PF_MISMATCHAW(&r->dst.addr,
(struct pf_addr *)&h->ip6_dst, AF_INET6, r->dst.neg))
(struct pf_addr *)&h->ip6_dst, AF_INET6,
r->dst.neg, NULL))
r = r->skip[PF_SKIP_DST_ADDR].ptr;
else
break;
}
if (r == NULL)
if (r == NULL || r->action == PF_NOSCRUB)
return (PF_PASS);
else
r->packets++;
else {
r->packets[dir == PF_OUT]++;
r->bytes[dir == PF_OUT] += pd->tot_len;
}
/* Check for illegal packets */
if (sizeof(struct ip6_hdr) + IPV6_MAXPACKET < m->m_pkthdr.len)
@ -1336,19 +1361,19 @@ 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(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
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(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
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(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
return (PF_DROP);
}
#endif /* INET6 */
@ -1367,8 +1392,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 (pfi_kif_match(r->kif, kif) == r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@ -1376,12 +1400,14 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
r = r->skip[PF_SKIP_AF].ptr;
else if (r->proto && r->proto != pd->proto)
r = r->skip[PF_SKIP_PROTO].ptr;
else if (PF_MISMATCHAW(&r->src.addr, pd->src, af, r->src.neg))
else if (PF_MISMATCHAW(&r->src.addr, pd->src, af,
r->src.neg, kif))
r = r->skip[PF_SKIP_SRC_ADDR].ptr;
else if (r->src.port_op && !pf_match_port(r->src.port_op,
r->src.port[0], r->src.port[1], th->th_sport))
r = r->skip[PF_SKIP_SRC_PORT].ptr;
else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af, r->dst.neg))
else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af,
r->dst.neg, NULL))
r = r->skip[PF_SKIP_DST_ADDR].ptr;
else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
r->dst.port[0], r->dst.port[1], th->th_dport))
@ -1398,8 +1424,10 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
if (rm == NULL || rm->action == PF_NOSCRUB)
return (PF_PASS);
else
r->packets++;
else {
r->packets[dir == PF_OUT]++;
r->bytes[dir == PF_OUT] += pd->tot_len;
}
if (rm->rule_flag & PFRULE_REASSEMBLE_TCP)
pd->flags |= PFDESC_TCP_NORM;
@ -1461,7 +1489,7 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
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(kif, h, m, AF_INET, dir, reason, r, NULL, NULL, pd);
return (PF_DROP);
}
@ -1931,7 +1959,7 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
* timestamps. And require all data packets to contain a timestamp
* if the first does. PAWS implicitly requires that all data packets be
* timestamped. But I think there are middle-man devices that hijack
* TCP streams immedietly after the 3whs and don't timestamp their
* TCP streams immediately after the 3whs and don't timestamp their
* packets (seen in a WWW accelerator or cache).
*/
if (pd->p_len > 0 && src->scrub && (src->scrub->pfss_flags &

View File

@ -1,5 +1,4 @@
/* $FreeBSD$ */
/* $OpenBSD: pf_osfp.c,v 1.10 2004/04/09 19:30:41 frantzen Exp $ */
/* $OpenBSD: pf_osfp.c,v 1.12 2006/12/13 18:14:10 itojun Exp $ */
/*
* Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
@ -18,6 +17,11 @@
*
*/
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#endif
#include <sys/param.h>
#include <sys/socket.h>
#ifdef _KERNEL
@ -33,9 +37,10 @@
#include <net/if.h>
#include <net/pfvar.h>
#ifdef INET6
#include <netinet/ip6.h>
#endif /* INET6 */
#ifdef _KERNEL
#include <netinet6/in6_var.h>
#endif
#ifdef _KERNEL
# define DPFPRINTF(format, x...) \
@ -55,6 +60,7 @@ typedef struct pool pool_t;
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <netdb.h>
# define pool_t int
# define pool_get(pool, flags) malloc(*(pool))
# define pool_put(pool, item) free(item)
@ -95,38 +101,96 @@ pf_osfp_fingerprint(struct pf_pdesc *pd, struct mbuf *m, int off,
const struct tcphdr *tcp)
{
struct ip *ip;
struct ip6_hdr *ip6;
char hdr[60];
/* XXX don't have a fingerprint database for IPv6 :-( */
if (pd->af != PF_INET || pd->proto != IPPROTO_TCP || (tcp->th_off << 2)
< sizeof(*tcp))
if ((pd->af != PF_INET && pd->af != PF_INET6) ||
pd->proto != IPPROTO_TCP || (tcp->th_off << 2) < sizeof(*tcp))
return (NULL);
ip = mtod(m, struct ip *);
if (!pf_pull_hdr(m, off, hdr, tcp->th_off << 2, NULL, NULL, pd->af))
return (NULL);
if (pd->af == PF_INET) {
ip = mtod(m, struct ip *);
ip6 = (struct ip6_hdr *)NULL;
} else {
ip = (struct ip *)NULL;
ip6 = mtod(m, struct ip6_hdr *);
}
if (!pf_pull_hdr(m, off, hdr, tcp->th_off << 2, NULL, NULL,
pd->af)) return (NULL);
return (pf_osfp_fingerprint_hdr(ip, (struct tcphdr *)hdr));
return (pf_osfp_fingerprint_hdr(ip, ip6, (struct tcphdr *)hdr));
}
#endif /* _KERNEL */
struct pf_osfp_enlist *
pf_osfp_fingerprint_hdr(const struct ip *ip, const struct tcphdr *tcp)
pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcp)
{
struct pf_os_fingerprint fp, *fpresult;
int cnt, optlen = 0;
const u_int8_t *optp;
#ifdef _KERNEL
char srcname[128];
#else
char srcname[NI_MAXHOST];
#endif
if ((tcp->th_flags & (TH_SYN|TH_ACK)) != TH_SYN || (ip->ip_off &
htons(IP_OFFMASK)))
if ((tcp->th_flags & (TH_SYN|TH_ACK)) != TH_SYN)
return (NULL);
if (ip) {
if ((ip->ip_off & htons(IP_OFFMASK)) != 0)
return (NULL);
}
memset(&fp, 0, sizeof(fp));
fp.fp_psize = ntohs(ip->ip_len);
fp.fp_ttl = ip->ip_ttl;
if (ip->ip_off & htons(IP_DF))
if (ip) {
#ifndef _KERNEL
struct sockaddr_in sin;
#endif
fp.fp_psize = ntohs(ip->ip_len);
fp.fp_ttl = ip->ip_ttl;
if (ip->ip_off & htons(IP_DF))
fp.fp_flags |= PF_OSFP_DF;
#ifdef _KERNEL
strlcpy(srcname, inet_ntoa(ip->ip_src), sizeof(srcname));
#else
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_addr = ip->ip_src;
(void)getnameinfo((struct sockaddr *)&sin,
sizeof(struct sockaddr_in), srcname, sizeof(srcname),
NULL, 0, NI_NUMERICHOST);
#endif
}
#ifdef INET6
else if (ip6) {
#ifndef _KERNEL
struct sockaddr_in6 sin6;
#endif
/* jumbo payload? */
fp.fp_psize = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
fp.fp_ttl = ip6->ip6_hlim;
fp.fp_flags |= PF_OSFP_DF;
fp.fp_flags |= PF_OSFP_INET6;
#ifdef _KERNEL
strlcpy(srcname, ip6_sprintf((struct in6_addr *)&ip6->ip6_src),
sizeof(srcname));
#else
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_addr = ip6->ip6_src;
(void)getnameinfo((struct sockaddr *)&sin6,
sizeof(struct sockaddr_in6), srcname, sizeof(srcname),
NULL, 0, NI_NUMERICHOST);
#endif
}
#endif
else
return (NULL);
fp.fp_wsize = ntohs(tcp->th_win);
@ -189,7 +253,7 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct tcphdr *tcp)
DPFPRINTF("fingerprinted %s:%d %d:%d:%d:%d:%llx (%d) "
"(TS=%s,M=%s%d,W=%s%d)\n",
inet_ntoa(ip->ip_src), ntohs(tcp->th_sport),
srcname, ntohs(tcp->th_sport),
fp.fp_wsize, fp.fp_ttl, (fp.fp_flags & PF_OSFP_DF) != 0,
fp.fp_psize, (long long int)fp.fp_tcpopts, fp.fp_optcnt,
(fp.fp_flags & PF_OSFP_TS0) ? "0" : "",

View File

@ -35,6 +35,11 @@
*
*/
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#endif
#include <sys/param.h>
#include <sys/socket.h>
#ifdef _KERNEL
@ -59,7 +64,11 @@
# define DPFPRINTF(format, x...) \
if (pf_status.debug >= PF_DEBUG_NOISY) \
printf(format , ##x)
#ifdef __FreeBSD__
#define rs_malloc(x) malloc(x, M_TEMP, M_NOWAIT)
#else
#define rs_malloc(x) malloc(x, M_TEMP, M_WAITOK)
#endif
#define rs_free(x) free(x, M_TEMP)
#else
@ -85,6 +94,8 @@
struct pf_anchor_global pf_anchors;
struct pf_anchor pf_main_anchor;
#ifndef __FreeBSD__
/* XXX: hum? */
int pf_get_ruleset_number(u_int8_t);
void pf_init_ruleset(struct pf_ruleset *);
int pf_anchor_setup(struct pf_rule *,
@ -92,6 +103,7 @@ int pf_anchor_setup(struct pf_rule *,
int pf_anchor_copyout(const struct pf_ruleset *,
const struct pf_rule *, struct pfioc_rule *);
void pf_anchor_remove(struct pf_rule *);
#endif
static __inline int pf_anchor_compare(struct pf_anchor *, struct pf_anchor *);
@ -184,7 +196,11 @@ pf_find_or_create_ruleset(const char *path)
{
char *p, *q, *r;
struct pf_ruleset *ruleset;
#ifdef __FreeBSD__
struct pf_anchor *anchor = NULL, *dup, *parent = NULL;
#else
struct pf_anchor *anchor, *dup, *parent = NULL;
#endif
if (path[0] == 0)
return (&pf_main_ruleset);

View File

@ -1,15 +1,6 @@
/* $FreeBSD$ */
/* from $OpenBSD: kern_subr.c,v 1.26 2003/10/31 11:10:41 markus Exp $ */
/* $NetBSD: kern_subr.c,v 1.15 1996/04/09 17:21:56 ragge Exp $ */
/*
* Copyright (c) 1982, 1986, 1991, 1993
/*-
* Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -19,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@ -35,93 +26,143 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
*/
#include "opt_inet.h"
#include "opt_inet6.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/libkern.h>
#include <sys/mbuf.h>
#include <sys/md5.h>
#include <sys/time.h>
#include <sys/random.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/proc.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/kernel.h>
#include <sys/resourcevar.h>
#include <sys/systm.h>
#include <sys/time.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/bpf.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcp_seq.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <netinet/in_pcb.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/if_ether.h>
#include <net/pfvar.h>
/*
* This implements additional functions used by pf which can not be ported
* easyly. At this point it boils down to mostly the Net/OpenBSD hook
* implementation.
* Following is where TCP initial sequence number generation occurs.
*
* BEWARE: this is not locked! Required locking is done by the caller.
* There are two places where we must use initial sequence numbers:
* 1. In SYN-ACK packets.
* 2. In SYN packets.
*
* All ISNs for SYN-ACK packets are generated by the syncache. See
* tcp_syncache.c for details.
*
* The ISNs in SYN packets must be monotonic; TIME_WAIT recycling
* depends on this property. In addition, these ISNs should be
* unguessable so as to prevent connection hijacking. To satisfy
* the requirements of this situation, the algorithm outlined in
* RFC 1948 is used, with only small modifications.
*
* Implementation details:
*
* Time is based off the system timer, and is corrected so that it
* increases by one megabyte per second. This allows for proper
* recycling on high speed LANs while still leaving over an hour
* before rollover.
*
* As reading the *exact* system time is too expensive to be done
* whenever setting up a TCP connection, we increment the time
* offset in two ways. First, a small random positive increment
* is added to isn_offset for each connection that is set up.
* Second, the function tcp_isn_tick fires once per clock tick
* and increments isn_offset as necessary so that sequence numbers
* are incremented at approximately ISN_BYTES_PER_SECOND. The
* random positive increments serve only to ensure that the same
* exact sequence number is never sent out twice (as could otherwise
* happen when a port is recycled in less than the system tick
* interval.)
*
* net.inet.tcp.isn_reseed_interval controls the number of seconds
* between seeding of isn_secret. This is normally set to zero,
* as reseeding should not be necessary.
*
* Locking of the global variables isn_secret, isn_last_reseed, isn_offset,
* isn_offset_old, and isn_ctx is performed using the TCP pcbinfo lock. In
* general, this means holding an exclusive (write) lock.
*/
void *
hook_establish(struct hook_desc_head *head, int tail, void (*fn)(void *),
void *arg)
#define ISN_BYTES_PER_SECOND 1048576
#define ISN_STATIC_INCREMENT 4096
#define ISN_RANDOM_INCREMENT (4096 - 1)
static u_char isn_secret[32];
static int isn_last_reseed;
static u_int32_t isn_offset, isn_offset_old;
static MD5_CTX isn_ctx;
u_int32_t
pf_new_isn(struct pf_state *s)
{
struct hook_desc *hdp;
u_int32_t md5_buffer[4];
u_int32_t new_isn;
struct pf_state_host *src, *dst;
hdp = (struct hook_desc *)malloc(sizeof (*hdp), M_DEVBUF, M_NOWAIT);
if (hdp == NULL)
return (NULL);
hdp->hd_fn = fn;
hdp->hd_arg = arg;
if (tail)
TAILQ_INSERT_TAIL(head, hdp, hd_list);
else
TAILQ_INSERT_HEAD(head, hdp, hd_list);
return (hdp);
}
void
hook_disestablish(struct hook_desc_head *head, void *vhook)
{
struct hook_desc *hdp;
#ifdef DIAGNOSTIC
for (hdp = TAILQ_FIRST(head); hdp != NULL;
hdp = TAILQ_NEXT(hdp, hd_list))
if (hdp == vhook)
break;
if (hdp == NULL)
panic("hook_disestablish: hook not established");
#endif
hdp = vhook;
TAILQ_REMOVE(head, hdp, hd_list);
free(hdp, M_DEVBUF);
}
/*
* Run hooks. Startup hooks are invoked right after scheduler_start but
* before root is mounted. Shutdown hooks are invoked immediately before the
* system is halted or rebooted, i.e. after file systems unmounted,
* after crash dump done, etc.
*/
void
dohooks(struct hook_desc_head *head, int flags)
{
struct hook_desc *hdp;
if ((flags & HOOK_REMOVE) == 0) {
TAILQ_FOREACH(hdp, head, hd_list) {
(*hdp->hd_fn)(hdp->hd_arg);
}
} else {
while ((hdp = TAILQ_FIRST(head)) != NULL) {
TAILQ_REMOVE(head, hdp, hd_list);
(*hdp->hd_fn)(hdp->hd_arg);
if ((flags & HOOK_FREE) != 0)
free(hdp, M_DEVBUF);
}
/* Seed if this is the first use, reseed if requested. */
if (isn_last_reseed == 0) {
read_random(&isn_secret, sizeof(isn_secret));
isn_last_reseed = ticks;
}
if (s->direction == PF_IN) {
src = &s->ext;
dst = &s->gwy;
} else {
src = &s->lan;
dst = &s->ext;
}
/* Compute the md5 hash and return the ISN. */
MD5Init(&isn_ctx);
MD5Update(&isn_ctx, (u_char *) &dst->port, sizeof(u_short));
MD5Update(&isn_ctx, (u_char *) &src->port, sizeof(u_short));
#ifdef INET6
if (s->af == AF_INET6) {
MD5Update(&isn_ctx, (u_char *) &dst->addr,
sizeof(struct in6_addr));
MD5Update(&isn_ctx, (u_char *) &src->addr,
sizeof(struct in6_addr));
} else
#endif
{
MD5Update(&isn_ctx, (u_char *) &dst->addr,
sizeof(struct in_addr));
MD5Update(&isn_ctx, (u_char *) &src->addr,
sizeof(struct in_addr));
}
MD5Update(&isn_ctx, (u_char *) &isn_secret, sizeof(isn_secret));
MD5Final((u_char *) &md5_buffer, &isn_ctx);
new_isn = (tcp_seq) md5_buffer[0];
isn_offset += ISN_STATIC_INCREMENT +
(arc4random() & ISN_RANDOM_INCREMENT);
new_isn += isn_offset;
return (new_isn);
}

View File

@ -1,5 +1,4 @@
/* $FreeBSD$ */
/* $OpenBSD: pf_table.c,v 1.62 2004/12/07 18:02:04 mcbride Exp $ */
/* $OpenBSD: pf_table.c,v 1.68 2006/05/02 10:08:45 dhartmei Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@ -34,6 +33,9 @@
#ifdef __FreeBSD__
#include "opt_inet.h"
#include "opt_inet6.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#endif
#include <sys/param.h>
@ -465,7 +467,8 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
int
pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
int *size2, int *nadd, int *ndel, int *nchange, int flags)
int *size2, int *nadd, int *ndel, int *nchange, int flags,
u_int32_t ignore_pfrt_flags)
{
struct pfr_ktable *kt, *tmpkt;
struct pfr_kentryworkq addq, delq, changeq;
@ -475,7 +478,8 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
long tzero = time_second;
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, ignore_pfrt_flags, flags &
PFR_FLAG_USERIOCTL))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@ -875,13 +879,10 @@ 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);
#ifdef __FreeBSD__
PF_ASSERT(MA_OWNED);
#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;
@ -1079,17 +1080,14 @@ 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);
#ifdef __FreeBSD__
PF_ASSERT(MA_OWNED);
#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);
@ -1109,8 +1107,8 @@ 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);
#ifdef __FreeBSD__
PF_ASSERT(MA_OWNED);
#endif
if (KENTRY_NETWORK(ke)) {
pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net);
@ -1124,9 +1122,6 @@ pfr_unroute_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
rn = rn_delete(&ke->pfrke_sa, NULL, head);
#else
rn = rn_delete(&ke->pfrke_sa, NULL, head, NULL);
#endif
#if defined(__FreeBSD__) && (__FreeBSD_version >= 500100)
RADIX_NODE_HEAD_UNLOCK(head);
#endif
splx(s);
@ -2182,7 +2177,7 @@ pfr_attach_table(struct pf_ruleset *rs, char *name)
bzero(&tbl, sizeof(tbl));
strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name));
if (ac != NULL)
strlcpy(tbl.pfrt_anchor, ac->name, sizeof(tbl.pfrt_anchor));
strlcpy(tbl.pfrt_anchor, ac->path, sizeof(tbl.pfrt_anchor));
kt = pfr_lookup_table(&tbl);
if (kt == NULL) {
kt = pfr_create_ktable(&tbl, time_second, 1);

View File

@ -1,5 +1,5 @@
/* $FreeBSD$ */
/* $OpenBSD: pfvar.h,v 1.213 2005/03/03 07:13:39 dhartmei Exp $ */
/* $OpenBSD: pfvar.h,v 1.244 2007/02/23 21:31:51 deraadt Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@ -38,11 +38,18 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/tree.h>
#ifdef __FreeBSD__
#include <sys/lock.h>
#include <sys/sx.h>
#else
#include <sys/rwlock.h>
#endif
#include <net/radix.h>
#include <net/route.h>
#ifdef __FreeBSD__
#include <net/if_clone.h>
#include <net/pf_mtag.h>
#include <vm/uma.h>
#else
#include <netinet/ip_ipsp.h>
@ -55,6 +62,7 @@
#include <netinet/tcp_fsm.h>
struct ip;
struct ip6_hdr;
#ifdef __FreeBSD__
struct inpcb;
#endif
@ -62,6 +70,13 @@ struct inpcb;
#define PF_TCPS_PROXY_SRC ((TCP_NSTATES)+0)
#define PF_TCPS_PROXY_DST ((TCP_NSTATES)+1)
#define PF_MD5_DIGEST_LENGTH 16
#ifdef MD5_DIGEST_LENGTH
#if PF_MD5_DIGEST_LENGTH != MD5_DIGEST_LENGTH
#error
#endif
#endif
enum { PF_INOUT, PF_IN, PF_OUT };
enum { PF_LAN_EXT, PF_EXT_GWY, PF_ID };
enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, PF_NAT, PF_NONAT,
@ -74,6 +89,8 @@ enum { PF_DEBUG_NONE, PF_DEBUG_URGENT, PF_DEBUG_MISC, PF_DEBUG_NOISY };
enum { PF_CHANGE_NONE, PF_CHANGE_ADD_HEAD, PF_CHANGE_ADD_TAIL,
PF_CHANGE_ADD_BEFORE, PF_CHANGE_ADD_AFTER,
PF_CHANGE_REMOVE, PF_CHANGE_GET_TICKET };
enum { PF_GET_NONE, PF_GET_CLR_CNTR };
/*
* Note about PFTM_*: real indices into pf_rule.timeout[] come before
* PFTM_MAX, special cases afterwards. See pf_state_expires().
@ -85,7 +102,8 @@ enum { PFTM_TCP_FIRST_PACKET, PFTM_TCP_OPENING, PFTM_TCP_ESTABLISHED,
PFTM_OTHER_FIRST_PACKET, PFTM_OTHER_SINGLE,
PFTM_OTHER_MULTIPLE, PFTM_FRAG, PFTM_INTERVAL,
PFTM_ADAPTIVE_START, PFTM_ADAPTIVE_END, PFTM_SRC_NODE,
PFTM_TS_DIFF, PFTM_MAX, PFTM_PURGE, PFTM_UNTIL_PACKET };
PFTM_TS_DIFF, PFTM_MAX, PFTM_PURGE, PFTM_UNLINKED,
PFTM_UNTIL_PACKET };
/* PFTM default values */
#define PFTM_TCP_FIRST_PACKET_VAL 120 /* First TCP packet */
@ -108,17 +126,22 @@ enum { PFTM_TCP_FIRST_PACKET, PFTM_TCP_OPENING, PFTM_TCP_ESTABLISHED,
#define PFTM_TS_DIFF_VAL 30 /* Allowed TS diff */
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_SRC_NODES, PF_LIMIT_FRAGS,
PF_LIMIT_TABLES, PF_LIMIT_TABLE_ENTRIES, 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, PF_ADDR_RTLABEL };
PF_ADDR_TABLE, PF_ADDR_RTLABEL, PF_ADDR_URPFFAILED };
#define PF_POOL_TYPEMASK 0x0f
#define PF_POOL_STICKYADDR 0x20
#define PF_WSCALE_FLAG 0x80
#define PF_WSCALE_MASK 0x0f
#define PF_LOG 0x01
#define PF_LOG_ALL 0x02
#define PF_LOG_SOCKET_LOOKUP 0x04
struct pf_addr {
union {
struct in_addr v4;
@ -169,18 +192,19 @@ struct pf_addr_wrap {
#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_* */
TAILQ_ENTRY(pfi_dynaddr) entry;
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; /* mask or 128 */
int pfid_acnt4; /* address count IPv4 */
int pfid_acnt6; /* address count IPv6 */
sa_family_t pfid_af; /* rule af */
u_int8_t pfid_iflags; /* PFI_AFLAG_* */
};
/*
@ -246,21 +270,6 @@ extern void destroy_pf_mutex(void);
#define PFSYNC_MINVER 1
#define PFSYNC_PREFVER PFSYNC_MODVER
#define PFSYNC_MAXVER 1
/* prototyped for pf_subr.c */
struct hook_desc {
TAILQ_ENTRY(hook_desc) hd_list;
void (*hd_fn)(void *);
void *hd_arg;
};
TAILQ_HEAD(hook_desc_head, hook_desc);
void *hook_establish(struct hook_desc_head *, int, void (*)(void *), void *);
void hook_disestablish(struct hook_desc_head *, void *);
void dohooks(struct hook_desc_head *, int);
#define HOOK_REMOVE 0x01
#define HOOK_FREE 0x02
#endif /* __FreeBSD__ */
#ifdef INET
@ -392,23 +401,26 @@ void dohooks(struct hook_desc_head *, int);
#endif /* PF_INET6_ONLY */
#endif /* PF_INET_INET6 */
#define PF_MISMATCHAW(aw, x, af, neg) \
( \
(((aw)->type == PF_ADDR_NOROUTE && \
pf_routable((x), (af))) || \
((aw)->type == PF_ADDR_RTLABEL && \
!pf_rtlabel_match((x), (af), (aw))) || \
((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)->type == PF_ADDR_ADDRMASK && \
!PF_AZERO(&(aw)->v.a.mask, (af)) && \
!PF_MATCHA(0, &(aw)->v.a.addr, \
&(aw)->v.a.mask, (x), (af)))) != \
(neg) \
#define PF_MISMATCHAW(aw, x, af, neg, ifp) \
( \
(((aw)->type == PF_ADDR_NOROUTE && \
pf_routable((x), (af), NULL)) || \
(((aw)->type == PF_ADDR_URPFFAILED && (ifp) != NULL && \
pf_routable((x), (af), (ifp))) || \
((aw)->type == PF_ADDR_RTLABEL && \
!pf_rtlabel_match((x), (af), (aw))) || \
((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)->type == PF_ADDR_ADDRMASK && \
!PF_AZERO(&(aw)->v.a.mask, (af)) && \
!PF_MATCHA(0, &(aw)->v.a.addr, \
&(aw)->v.a.mask, (x), (af))))) != \
(neg) \
)
struct pf_rule_uid {
uid_t uid[2];
u_int8_t op;
@ -526,6 +538,7 @@ struct pf_os_fingerprint {
#define PF_OSFP_MSS_DC 0x0800 /* TCP MSS dont-care */
#define PF_OSFP_DF 0x1000 /* IPv4 don't fragment bit */
#define PF_OSFP_TS0 0x2000 /* Zero timestamp */
#define PF_OSFP_INET6 0x4000 /* IPv6 */
u_int8_t fp_optcnt; /* TCP option count */
u_int8_t fp_wscale; /* TCP window scaling */
u_int8_t fp_ttl; /* IPv4 TTL */
@ -581,11 +594,11 @@ struct pf_rule {
union pf_rule_ptr skip[PF_SKIP_COUNT];
#define PF_RULE_LABEL_SIZE 64
char label[PF_RULE_LABEL_SIZE];
#define PF_QNAME_SIZE 16
#define PF_QNAME_SIZE 64
char ifname[IFNAMSIZ];
char qname[PF_QNAME_SIZE];
char pqname[PF_QNAME_SIZE];
#define PF_TAG_NAME_SIZE 16
#define PF_TAG_NAME_SIZE 64
char tagname[PF_TAG_NAME_SIZE];
char match_tagname[PF_TAG_NAME_SIZE];
@ -595,8 +608,8 @@ struct pf_rule {
struct pf_pool rpool;
u_int64_t evaluations;
u_int64_t packets;
u_int64_t bytes;
u_int64_t packets[2];
u_int64_t bytes[2];
struct pfi_kif *kif;
struct pf_anchor *anchor;
@ -604,6 +617,7 @@ struct pf_rule {
pf_osfp_t os_fingerprint;
int rtableid;
u_int32_t timeout[PFTM_MAX];
u_int32_t states;
u_int32_t max_states;
@ -620,6 +634,8 @@ struct pf_rule {
u_int32_t rt_listid;
u_int32_t nr;
u_int32_t prob;
uid_t cuid;
pid_t cpid;
u_int16_t return_icmp;
u_int16_t return_icmp6;
@ -634,6 +650,7 @@ struct pf_rule {
u_int8_t action;
u_int8_t direction;
u_int8_t log;
u_int8_t logif;
u_int8_t quick;
u_int8_t ifnot;
u_int8_t match_tag_not;
@ -681,9 +698,10 @@ struct pf_rule {
/* rule flags again */
#define PFRULE_IFBOUND 0x00010000 /* if-bound */
#define PFRULE_GRBOUND 0x00020000 /* group-bound */
#define PFSTATE_HIWAT 10000 /* default state table size */
#define PFSTATE_ADAPT_START 6000 /* default adaptive timeout start */
#define PFSTATE_ADAPT_END 12000 /* default adaptive timeout end */
struct pf_threshold {
@ -701,8 +719,8 @@ struct pf_src_node {
struct pf_addr raddr;
union pf_rule_ptr rule;
struct pfi_kif *kif;
u_int32_t bytes;
u_int32_t packets;
u_int64_t bytes[2];
u_int64_t packets[2];
u_int32_t states;
u_int32_t conn;
struct pf_threshold conn_rate;
@ -744,26 +762,58 @@ struct pf_state_peer {
u_int8_t state; /* active state level */
u_int8_t wscale; /* window scaling factor */
u_int16_t mss; /* Maximum segment size option */
u_int8_t tcp_est; /* Did we reach TCPS_ESTABLISHED */
struct pf_state_scrub *scrub; /* state is scrubbed */
u_int8_t pad[3];
};
TAILQ_HEAD(pf_state_queue, pf_state);
/* keep synced with struct pf_state, used in RB_FIND */
struct pf_state_cmp {
u_int64_t id;
u_int32_t creatorid;
struct pf_state_host lan;
struct pf_state_host gwy;
struct pf_state_host ext;
sa_family_t af;
u_int8_t proto;
u_int8_t direction;
u_int8_t pad;
};
struct pf_state {
u_int64_t id;
u_int32_t creatorid;
struct pf_state_host lan;
struct pf_state_host gwy;
struct pf_state_host ext;
sa_family_t af;
u_int8_t proto;
u_int8_t direction;
#ifdef __FreeBSD__
u_int8_t local_flags;
#define PFSTATE_EXPIRING 0x01
#else
u_int8_t pad;
#endif
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
#define PFSTATE_STALE 0x04
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;
TAILQ_ENTRY(pf_state) entry_list;
struct pfi_kif *kif;
} s;
char ifname[IFNAMSIZ];
} u;
struct pf_state_host lan;
struct pf_state_host gwy;
struct pf_state_host ext;
struct pf_state_peer src;
struct pf_state_peer dst;
union pf_rule_ptr rule;
@ -773,30 +823,12 @@ struct pf_state {
struct pfi_kif *rt_kif;
struct pf_src_node *src_node;
struct pf_src_node *nat_src_node;
u_int64_t packets[2];
u_int64_t bytes[2];
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;
u_int16_t tag;
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
#define PFSTATE_STALE 0x04
#ifdef __FreeBSD__
u_int8_t local_flags;
#define PFSTATE_EXPIRING 0x01
#define PFSTATE_SRC_CONN 0x02
#else
u_int8_t pad;
#endif
};
TAILQ_HEAD(pf_rulequeue, pf_rule);
@ -808,6 +840,8 @@ struct pf_ruleset {
struct pf_rulequeue queues[2];
struct {
struct pf_rulequeue *ptr;
struct pf_rule **ptr_array;
u_int32_t rcount;
u_int32_t ticket;
int open;
} active, inactive;
@ -829,6 +863,7 @@ struct pf_anchor {
char path[MAXPATHLEN];
struct pf_ruleset ruleset;
int refcnt; /* anchor rules */
int match;
};
RB_PROTOTYPE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare);
RB_PROTOTYPE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare);
@ -954,56 +989,52 @@ 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);
/* keep synced with pfi_kif, used in RB_FIND */
struct pfi_kif_cmp {
char pfik_name[IFNAMSIZ];
};
struct pfi_kif {
struct pfi_if pfik_if;
char pfik_name[IFNAMSIZ];
RB_ENTRY(pfi_kif) pfik_tree;
u_int64_t pfik_packets[2][2][2];
u_int64_t pfik_bytes[2][2][2];
u_int32_t pfik_tzero;
int pfik_flags;
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;
#ifndef __FreeBSD__
void *pfik_ah_cookie;
struct pfi_kif *pfik_parent;
#endif
struct ifnet *pfik_ifp;
struct ifg_group *pfik_group;
int pfik_states;
int pfik_rules;
TAILQ_HEAD(, pfi_dynaddr) pfik_dynaddrs;
};
enum pfi_kif_refs {
PFI_KIF_REF_NONE,
PFI_KIF_REF_STATE,
PFI_KIF_REF_RULE
};
#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 */
#define PFI_IFLAG_SKIP 0x0100 /* skip filtering on interface */
/* XXX: revisist */
#define PFI_IFLAG_SETABLE_MASK 0x0100 /* setable via DIOC{SET,CLR}IFFLAG */
#define PFI_IFLAG_PLACEHOLDER 0x8000 /* placeholder group/interface */
struct pf_pdesc {
struct {
int done;
uid_t uid;
gid_t gid;
pid_t pid;
} lookup;
u_int64_t tot_len; /* Make Mickey money */
union {
struct tcphdr *tcp;
@ -1021,6 +1052,7 @@ struct pf_pdesc {
struct pf_addr *dst;
struct ether_header
*eh;
struct pf_mtag *pf_mtag;
u_int16_t *ip_sum;
u_int32_t p_len; /* total length of payload */
u_int16_t flags; /* Let SCRUB trigger behavior in
@ -1161,6 +1193,7 @@ struct pf_status {
u_int32_t debug;
u_int32_t hostid;
char ifname[IFNAMSIZ];
u_int8_t pf_chksum[PF_MD5_DIGEST_LENGTH];
};
struct cbq_opts {
@ -1223,6 +1256,23 @@ struct pf_altq {
u_int32_t qid; /* return value */
};
#ifndef __FreeBSD__
#define PF_TAG_GENERATED 0x01
#define PF_TAG_FRAGCACHE 0x02
#define PF_TAG_TRANSLATE_LOCALHOST 0x04
struct pf_mtag {
void *hdr; /* saved hdr pos in mbuf, for ECN */
u_int rtableid; /* alternate routing table id */
u_int32_t qid; /* queue id */
u_int16_t tag; /* tag id */
u_int8_t flags;
u_int8_t routed;
sa_family_t af; /* for ECN */
};
#endif
struct pf_tag {
u_int16_t tag; /* tag id */
};
@ -1239,6 +1289,10 @@ struct pf_tagname {
#define PFFRAG_FRCENT_HIWAT 50000 /* Number of fragment cache entries */
#define PFFRAG_FRCACHE_HIWAT 10000 /* Number of fragment descriptors */
#define PFR_KTABLE_HIWAT 1000 /* Number of tables */
#define PFR_KENTRY_HIWAT 200000 /* Number of table entries */
#define PFR_KENTRY_HIWAT_SMALL 100000 /* Number of table entries (tiny hosts) */
/*
* ioctl parameter structures
*/
@ -1284,6 +1338,13 @@ struct pfioc_state {
struct pf_state state;
};
struct pfioc_src_node_kill {
/* XXX returns the number of src nodes killed in psnk_af */
sa_family_t psnk_af;
struct pf_rule_addr psnk_src;
struct pf_rule_addr psnk_dst;
};
struct pfioc_state_kill {
/* XXX returns the number of states killed in psk_af */
sa_family_t psk_af;
@ -1391,11 +1452,6 @@ struct pfioc_table {
#define pfrio_setflag pfrio_size2
#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;
@ -1474,15 +1530,15 @@ struct pfioc_iface {
#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)
#define DIOCSETIFFLAG _IOWR('D', 89, struct pfioc_iface)
#define DIOCCLRIFFLAG _IOWR('D', 90, struct pfioc_iface)
#define DIOCKILLSRCNODES _IOWR('D', 91, struct pfioc_src_node_kill)
#ifdef __FreeBSD__
struct pf_ifspeed {
char ifname[IFNAMSIZ];
u_int32_t baudrate;
};
#define DIOCGIFSPEED _IOWR('D', 91, struct pf_ifspeed)
#define DIOCGIFSPEED _IOWR('D', 92, struct pf_ifspeed)
#endif
#ifdef _KERNEL
@ -1494,16 +1550,13 @@ 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_state_queue state_list;
extern struct pf_anchor_global pf_anchors;
extern struct pf_ruleset pf_main_ruleset;
TAILQ_HEAD(pf_poolqueue, pf_pool);
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 u_int32_t ticket_altqs_active;
extern u_int32_t ticket_altqs_inactive;
@ -1530,26 +1583,22 @@ extern struct pool pf_src_tree_pl, pf_rule_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 void pf_purge_expired_state(struct pf_state *);
extern void pf_purge_thread(void *);
extern void pf_purge_expired_src_nodes(int);
extern void pf_purge_expired_states(u_int32_t);
extern void pf_unlink_state(struct pf_state *);
extern void pf_free_state(struct pf_state *);
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,
extern struct pf_state *pf_find_state_byid(struct pf_state_cmp *);
extern struct pf_state *pf_find_state_all(struct pf_state_cmp *key,
u_int8_t tree, int *more);
extern void pf_print_state(struct pf_state *);
extern void pf_print_flags(u_int8_t);
extern struct pf_anchor *pf_find_anchor(const char *);
extern struct pf_ruleset *pf_find_ruleset(const char *);
extern struct pf_ruleset *pf_find_or_create_ruleset(const char *);
extern void pf_remove_if_empty_ruleset(
struct pf_ruleset *);
extern u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t,
u_int8_t);
@ -1581,11 +1630,15 @@ void pf_poolmask(struct pf_addr *, struct pf_addr*,
void pf_addr_inc(struct pf_addr *, sa_family_t);
#endif /* INET6 */
#ifdef __FreeBSD__
u_int32_t pf_new_isn(struct pf_state *);
#endif
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,
u_int8_t, struct pf_rule *, struct pf_rule *, struct pf_ruleset *);
u_int8_t, struct pf_rule *, struct pf_rule *, struct pf_ruleset *,
struct pf_pdesc *);
int pf_match_addr(u_int8_t, struct pf_addr *, struct pf_addr *,
struct pf_addr *, sa_family_t);
int pf_match(u_int8_t, u_int32_t, u_int32_t, u_int32_t);
@ -1609,8 +1662,13 @@ int pf_normalize_tcp_stateful(struct mbuf *, int, struct pf_pdesc *,
u_int32_t
pf_state_expires(const struct pf_state *);
void pf_purge_expired_fragments(void);
int pf_routable(struct pf_addr *addr, sa_family_t af);
int pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *);
int pf_rtlabel_match(struct pf_addr *, sa_family_t, struct pf_addr_wrap *);
#ifdef __FreeBSD__
int pf_socket_lookup(int, struct pf_pdesc *, struct inpcb *);
#else
int pf_socket_lookup(int, struct pf_pdesc *);
#endif
void pfr_initialize(void);
int pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t);
void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t,
@ -1635,7 +1693,7 @@ int pfr_add_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
int pfr_del_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
int);
int pfr_set_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
int *, int *, int *, int);
int *, int *, int *, int, u_int32_t);
int pfr_get_addrs(struct pfr_table *, struct pfr_addr *, int *, int);
int pfr_get_astats(struct pfr_table *, struct pfr_astats *, int *, int);
int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *,
@ -1648,48 +1706,54 @@ 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);
extern struct pfi_statehead pfi_statehead;
extern struct pfi_kif *pfi_all;
void pfi_initialize(void);
#ifdef __FreeBSD__
void pfi_cleanup(void);
#endif
void pfi_attach_clone(struct if_clone *);
struct pfi_kif *pfi_kif_get(const char *);
void pfi_kif_ref(struct pfi_kif *, enum pfi_kif_refs);
void pfi_kif_unref(struct pfi_kif *, enum pfi_kif_refs);
int pfi_kif_match(struct pfi_kif *, struct pfi_kif *);
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_set_flags(const char *, int);
int pfi_clear_flags(const char *, int);
void pfi_attach_ifgroup(struct ifg_group *);
void pfi_detach_ifgroup(struct ifg_group *);
void pfi_group_change(const char *);
int pfi_match_addr(struct pfi_dynaddr *, struct pf_addr *,
sa_family_t);
int pfi_dynaddr_setup(struct pf_addr_wrap *, sa_family_t);
void pfi_dynaddr_remove(struct pf_addr_wrap *);
void pfi_dynaddr_copyout(struct pf_addr_wrap *);
void pfi_fill_oldstatus(struct pf_status *);
int pfi_clr_istats(const char *);
int pfi_get_ifaces(const char *, struct pfi_kif *, int *);
int pfi_set_flags(const char *, int);
int pfi_clear_flags(const char *, int);
extern struct pfi_statehead pfi_statehead;
u_int16_t pf_tagname2tag(char *);
void pf_tag2tagname(u_int16_t, char *);
void pf_tag_ref(u_int16_t);
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);
u_int16_t pf_tagname2tag(char *);
void pf_tag2tagname(u_int16_t, char *);
void pf_tag_ref(u_int16_t);
void pf_tag_unref(u_int16_t);
int pf_tag_packet(struct mbuf *, struct pf_mtag *, int, int);
u_int32_t pf_qname2qid(char *);
void pf_qid2qname(u_int32_t, char *);
void pf_qid_unref(u_int32_t);
#ifndef __FreeBSD__
struct pf_mtag *pf_find_mtag(struct mbuf *);
struct pf_mtag *pf_get_mtag(struct mbuf *);
#endif
extern struct pf_status pf_status;
#ifdef __FreeBSD__
extern uma_zone_t pf_frent_pl, pf_frag_pl;
extern struct sx pf_consistency_lock;
#else
extern struct pool pf_frent_pl, pf_frag_pl;
extern struct rwlock pf_consistency_lock;
#endif
struct pf_pool_limit {
@ -1732,6 +1796,34 @@ struct pf_fragment {
#endif /* _KERNEL */
extern struct pf_anchor_global pf_anchors;
extern struct pf_anchor pf_main_anchor;
#define pf_main_ruleset pf_main_anchor.ruleset
/* these ruleset functions can be linked into userland programs (pfctl) */
int pf_get_ruleset_number(u_int8_t);
void pf_init_ruleset(struct pf_ruleset *);
int pf_anchor_setup(struct pf_rule *,
const struct pf_ruleset *, const char *);
int pf_anchor_copyout(const struct pf_ruleset *,
const struct pf_rule *, struct pfioc_rule *);
void pf_anchor_remove(struct pf_rule *);
void pf_remove_if_empty_ruleset(struct pf_ruleset *);
struct pf_anchor *pf_find_anchor(const char *);
struct pf_ruleset *pf_find_ruleset(const char *);
struct pf_ruleset *pf_find_or_create_ruleset(const char *);
void pf_rs_initialize(void);
#ifndef __FreeBSD__
/* ?!? */
#ifdef _KERNEL
int pf_anchor_copyout(const struct pf_ruleset *,
const struct pf_rule *, struct pfioc_rule *);
void pf_anchor_remove(struct pf_rule *);
#endif /* _KERNEL */
#endif
/* The fingerprint functions can be linked into userland programs (tcpdump) */
int pf_osfp_add(struct pf_osfp_ioctl *);
#ifdef _KERNEL
@ -1740,7 +1832,8 @@ struct pf_osfp_enlist *
const struct tcphdr *);
#endif /* _KERNEL */
struct pf_osfp_enlist *
pf_osfp_fingerprint_hdr(const struct ip *, const struct tcphdr *);
pf_osfp_fingerprint_hdr(const struct ip *, const struct ip6_hdr *,
const struct tcphdr *);
void pf_osfp_flush(void);
int pf_osfp_get(struct pf_osfp_ioctl *);
#ifdef __FreeBSD__