Import pf from OpenBSD 3.5 (OPENBSD_3_5_BASE)

This commit is contained in:
Max Laier 2004-06-16 23:03:14 +00:00
parent ac529e0479
commit 32b3098356
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor-sys/pf/dist/; revision=130610
svn path=/vendor-sys/pf/3.5/; revision=130612; tag=vendor/pf-sys/3.5
11 changed files with 4688 additions and 1410 deletions

View file

@ -1,4 +1,4 @@
/* $OpenBSD: if_pflog.c,v 1.9 2003/05/14 08:42:00 canacar Exp $ */
/* $OpenBSD: if_pflog.c,v 1.11 2003/12/31 11:18:25 cedric Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@ -172,7 +172,7 @@ pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
int
pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir,
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)
{
@ -181,25 +181,23 @@ pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir,
struct pfloghdr hdr;
struct mbuf m1;
if (ifp == NULL || m == NULL || rm == NULL)
if (kif == NULL || m == NULL || rm == NULL)
return (-1);
bzero(&hdr, sizeof(hdr));
hdr.length = PFLOG_REAL_HDRLEN;
hdr.af = af;
hdr.action = rm->action;
hdr.reason = reason;
memcpy(hdr.ifname, ifp->if_xname, sizeof(hdr.ifname));
memcpy(hdr.ifname, kif->pfik_name, sizeof(hdr.ifname));
if (am == NULL) {
hdr.rulenr = htonl(rm->nr);
hdr.subrulenr = -1;
bzero(hdr.ruleset, sizeof(hdr.ruleset));
} else {
hdr.rulenr = htonl(am->nr);
hdr.subrulenr = htonl(rm->nr);
if (ruleset == NULL)
bzero(hdr.ruleset, sizeof(hdr.ruleset));
else
if (ruleset != NULL)
memcpy(hdr.ruleset, ruleset->name,
sizeof(hdr.ruleset));

View file

@ -1,4 +1,4 @@
/* $OpenBSD: if_pflog.h,v 1.9 2003/07/15 20:27:27 dhartmei Exp $ */
/* $OpenBSD: if_pflog.h,v 1.10 2004/03/19 04:52:04 frantzen Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@ -51,7 +51,7 @@ struct pfloghdr {
#define PFLOG_HDRLEN sizeof(struct pfloghdr)
/* minus pad, also used as a signature */
#define PFLOG_REAL_HDRLEN offsetof(struct pfloghdr, pad);
#define PFLOG_REAL_HDRLEN offsetof(struct pfloghdr, pad)
/* XXX remove later when old format logs are no longer needed */
struct old_pfloghdr {

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
/* $OpenBSD: if_pfsync.h,v 1.2 2002/12/11 18:31:26 mickey Exp $ */
/* $OpenBSD: if_pfsync.h,v 1.13 2004/03/22 04:54:17 mcbride Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@ -29,40 +29,208 @@
#ifndef _NET_IF_PFSYNC_H_
#define _NET_IF_PFSYNC_H_
#ifdef _KERNEL
struct pfsync_softc {
struct ifnet sc_if;
struct timeout sc_tmo;
struct mbuf *sc_mbuf; /* current cummulative mbuf */
struct pf_state *sc_ptr; /* current ongoing state */
int sc_count; /* number of states in one mtu */
#define PFSYNC_ID_LEN sizeof(u_int64_t)
struct pfsync_state_scrub {
u_int16_t pfss_flags;
u_int8_t pfss_ttl; /* stashed TTL */
u_int8_t scrub_flag;
u_int32_t pfss_ts_mod; /* timestamp modulation */
} __packed;
struct pfsync_state_host {
struct pf_addr addr;
u_int16_t port;
u_int16_t pad[3];
} __packed;
struct pfsync_state_peer {
struct pfsync_state_scrub scrub; /* state is scrubbed */
u_int32_t seqlo; /* Max sequence number sent */
u_int32_t seqhi; /* Max the other end ACKd + win */
u_int32_t seqdiff; /* Sequence number modulator */
u_int16_t max_win; /* largest window (pre scaling) */
u_int16_t mss; /* Maximum segment size option */
u_int8_t state; /* active state level */
u_int8_t wscale; /* window scaling factor */
u_int8_t scrub_flag;
u_int8_t pad[5];
} __packed;
struct pfsync_state {
u_int32_t id[2];
char ifname[IFNAMSIZ];
struct pfsync_state_host lan;
struct pfsync_state_host gwy;
struct pfsync_state_host ext;
struct pfsync_state_peer src;
struct pfsync_state_peer dst;
struct pf_addr rt_addr;
u_int32_t rule;
u_int32_t anchor;
u_int32_t nat_rule;
u_int32_t creation;
u_int32_t expire;
u_int32_t packets[2];
u_int32_t bytes[2];
u_int32_t creatorid;
sa_family_t af;
u_int8_t proto;
u_int8_t direction;
u_int8_t log;
u_int8_t allow_opts;
u_int8_t timeout;
u_int8_t sync_flags;
u_int8_t updates;
} __packed;
struct pfsync_state_upd {
u_int32_t id[2];
struct pfsync_state_peer src;
struct pfsync_state_peer dst;
u_int32_t creatorid;
u_int32_t expire;
u_int8_t timeout;
u_int8_t updates;
u_int8_t pad[6];
} __packed;
struct pfsync_state_del {
u_int32_t id[2];
u_int32_t creatorid;
struct {
u_int8_t state;
} src;
struct {
u_int8_t state;
} dst;
u_int8_t pad[2];
} __packed;
struct pfsync_state_upd_req {
u_int32_t id[2];
u_int32_t creatorid;
u_int32_t pad;
} __packed;
struct pfsync_state_clr {
char ifname[IFNAMSIZ];
u_int32_t creatorid;
u_int32_t pad;
} __packed;
struct pfsync_state_bus {
u_int32_t creatorid;
u_int32_t endtime;
u_int8_t status;
#define PFSYNC_BUS_START 1
#define PFSYNC_BUS_END 2
u_int8_t pad[7];
} __packed;
#ifdef _KERNEL
union sc_statep {
struct pfsync_state *s;
struct pfsync_state_upd *u;
struct pfsync_state_del *d;
struct pfsync_state_clr *c;
struct pfsync_state_bus *b;
struct pfsync_state_upd_req *r;
};
extern int pfsync_sync_ok;
struct pfsync_softc {
struct ifnet sc_if;
struct ifnet *sc_sync_ifp;
struct ip_moptions sc_imo;
struct timeout sc_tmo;
struct timeout sc_bulk_tmo;
struct timeout sc_bulkfail_tmo;
struct in_addr sc_sendaddr;
struct mbuf *sc_mbuf; /* current cummulative mbuf */
struct mbuf *sc_mbuf_net; /* current cummulative mbuf */
union sc_statep sc_statep;
union sc_statep sc_statep_net;
u_int32_t sc_ureq_received;
u_int32_t sc_ureq_sent;
int sc_bulk_tries;
int sc_maxcount; /* number of states in mtu */
int sc_maxupdates; /* number of updates/state */
};
#endif
struct pfsync_header {
u_int8_t version;
#define PFSYNC_VERSION 1
#define PFSYNC_VERSION 2
u_int8_t af;
u_int8_t action;
#define PFSYNC_ACT_CLR 0
#define PFSYNC_ACT_INS 1
#define PFSYNC_ACT_UPD 2
#define PFSYNC_ACT_DEL 3
#define PFSYNC_ACT_MAX 4
#define PFSYNC_ACT_CLR 0 /* clear all states */
#define PFSYNC_ACT_INS 1 /* insert state */
#define PFSYNC_ACT_UPD 2 /* update state */
#define PFSYNC_ACT_DEL 3 /* delete state */
#define PFSYNC_ACT_UPD_C 4 /* "compressed" state update */
#define PFSYNC_ACT_DEL_C 5 /* "compressed" state delete */
#define PFSYNC_ACT_INS_F 6 /* insert fragment */
#define PFSYNC_ACT_DEL_F 7 /* delete fragments */
#define PFSYNC_ACT_UREQ 8 /* request "uncompressed" state */
#define PFSYNC_ACT_BUS 9 /* Bulk Update Status */
#define PFSYNC_ACT_MAX 10
u_int8_t count;
};
} __packed;
#define PFSYNC_BULKPACKETS 1 /* # of packets per timeout */
#define PFSYNC_MAX_BULKTRIES 12
#define PFSYNC_HDRLEN sizeof(struct pfsync_header)
#define PFSYNC_ACTIONS \
"CLR ST", "INS ST", "UPD ST", "DEL ST"
"CLR ST", "INS ST", "UPD ST", "DEL ST", \
"UPD ST COMP", "DEL ST COMP", "INS FR", "DEL FR", \
"UPD REQ", "BLK UPD STAT"
#define PFSYNC_DFLTTL 255
struct pfsyncstats {
u_long pfsyncs_ipackets; /* total input packets, IPv4 */
u_long pfsyncs_ipackets6; /* total input packets, IPv6 */
u_long pfsyncs_badif; /* not the right interface */
u_long pfsyncs_badttl; /* TTL is not PFSYNC_DFLTTL */
u_long pfsyncs_hdrops; /* packets shorter than header */
u_long pfsyncs_badver; /* bad (incl unsupp) version */
u_long pfsyncs_badact; /* bad action */
u_long pfsyncs_badlen; /* data length does not match */
u_long pfsyncs_badauth; /* bad authentication */
u_long pfsyncs_badstate; /* insert/lookup failed */
u_long pfsyncs_opackets; /* total output packets, IPv4 */
u_long pfsyncs_opackets6; /* total output packets, IPv6 */
u_long pfsyncs_onomem; /* no memory for an mbuf for a send */
u_long pfsyncs_oerrors; /* ip output error */
};
/*
* Configuration structure for SIOCSETPFSYNC SIOCGETPFSYNC
*/
struct pfsyncreq {
char pfsyncr_syncif[IFNAMSIZ];
int pfsyncr_maxupdates;
int pfsyncr_authlevel;
};
#define SIOCSETPFSYNC _IOW('i', 247, struct ifreq)
#define SIOCGETPFSYNC _IOWR('i', 248, struct ifreq)
#define pf_state_peer_hton(s,d) do { \
(d)->seqlo = htonl((s)->seqlo); \
(d)->seqhi = htonl((s)->seqhi); \
(d)->seqdiff = htonl((s)->seqdiff); \
(d)->max_win = htons((s)->max_win); \
(d)->mss = htons((s)->mss); \
(d)->state = (s)->state; \
(d)->wscale = (s)->wscale; \
} while (0)
#define pf_state_peer_ntoh(s,d) do { \
@ -70,15 +238,43 @@ struct pfsync_header {
(d)->seqhi = ntohl((s)->seqhi); \
(d)->seqdiff = ntohl((s)->seqdiff); \
(d)->max_win = ntohs((s)->max_win); \
(d)->mss = ntohs((s)->mss); \
(d)->state = (s)->state; \
(d)->wscale = (s)->wscale; \
} while (0)
#define pf_state_host_hton(s,d) do { \
bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \
(d)->port = (s)->port; \
} while (0)
#define pf_state_host_ntoh(s,d) do { \
bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \
(d)->port = (s)->port; \
} while (0)
#ifdef _KERNEL
int pfsync_clear_state(struct pf_state *);
int pfsync_pack_state(u_int8_t, struct pf_state *);
#define pfsync_insert_state(st) pfsync_pack_state(PFSYNC_ACT_INS, (st))
#define pfsync_update_state(st) pfsync_pack_state(PFSYNC_ACT_UPD, (st))
#define pfsync_delete_state(st) pfsync_pack_state(PFSYNC_ACT_DEL, (st))
void pfsync_input(struct mbuf *, ...);
int pfsync_clear_states(u_int32_t, char *);
int pfsync_pack_state(u_int8_t, struct pf_state *, int);
#define pfsync_insert_state(st) do { \
if ((st->rule.ptr->rule_flag & PFRULE_NOSYNC) || \
(st->proto == IPPROTO_PFSYNC)) \
st->sync_flags |= PFSTATE_NOSYNC; \
else if (!st->sync_flags) \
pfsync_pack_state(PFSYNC_ACT_INS, (st), 1); \
st->sync_flags &= ~PFSTATE_FROMSYNC; \
} while (0)
#define pfsync_update_state(st) do { \
if (!st->sync_flags) \
pfsync_pack_state(PFSYNC_ACT_UPD, (st), 1); \
st->sync_flags &= ~PFSTATE_FROMSYNC; \
} while (0)
#define pfsync_delete_state(st) do { \
if (!st->sync_flags) \
pfsync_pack_state(PFSYNC_ACT_DEL, (st), 1); \
st->sync_flags &= ~PFSTATE_FROMSYNC; \
} while (0)
#endif
#endif /* _NET_IF_PFSYNC_H_ */

File diff suppressed because it is too large Load diff

840
sys/contrib/pf/net/pf_if.c Normal file
View file

@ -0,0 +1,840 @@
/* $OpenBSD: pf_if.c,v 1.11 2004/03/15 11:38:23 cedric Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
* Copyright (c) 2003 Cedric Berger
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/filio.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/time.h>
#include <net/if.h>
#include <net/if_types.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 <net/pfvar.h>
#ifdef INET6
#include <netinet/ip6.h>
#endif /* INET6 */
#define ACCEPT_FLAGS(oklist) \
do { \
if ((flags & ~(oklist)) & \
PFI_FLAG_ALLMASK) \
return (EINVAL); \
} while (0)
#define senderr(e) do { rv = (e); goto _bad; } while (0)
struct pfi_kif **pfi_index2kif;
struct pfi_kif *pfi_self;
int pfi_indexlim;
struct pfi_ifhead pfi_ifs;
struct pfi_statehead pfi_statehead;
int pfi_ifcnt;
struct pool pfi_addr_pl;
long pfi_update = 1;
struct pfr_addr *pfi_buffer;
int pfi_buffer_cnt;
int pfi_buffer_max;
char pfi_reserved_anchor[PF_ANCHOR_NAME_SIZE] =
PF_RESERVED_ANCHOR;
char pfi_interface_ruleset[PF_RULESET_NAME_SIZE] =
PF_INTERFACE_RULESET;
void pfi_dynaddr_update(void *);
void pfi_kifaddr_update(void *);
void pfi_table_update(struct pfr_ktable *, struct pfi_kif *,
int, int);
void pfi_instance_add(struct ifnet *, int, int);
void pfi_address_add(struct sockaddr *, int, int);
int pfi_if_compare(struct pfi_kif *, struct pfi_kif *);
struct pfi_kif *pfi_if_create(const char *, struct pfi_kif *, int);
void pfi_copy_group(char *, const char *, int);
void pfi_dynamic_drivers(void);
void pfi_newgroup(const char *, int);
int pfi_skip_if(const char *, struct pfi_kif *, int);
int pfi_unmask(void *);
void pfi_dohooks(struct pfi_kif *);
RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
#define PFI_DYNAMIC_BUSES { "pcmcia", "cardbus", "uhub" }
#define PFI_BUFFER_MAX 0x10000
#define PFI_MTYPE M_IFADDR
void
pfi_initialize(void)
{
if (pfi_self != NULL) /* already initialized */
return;
TAILQ_INIT(&pfi_statehead);
pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0,
"pfiaddrpl", &pool_allocator_nointr);
pfi_buffer_max = 64;
pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer),
PFI_MTYPE, M_WAITOK);
pfi_self = pfi_if_create("self", NULL, PFI_IFLAG_GROUP);
pfi_dynamic_drivers();
}
void
pfi_attach_clone(struct if_clone *ifc)
{
pfi_initialize();
pfi_newgroup(ifc->ifc_name, PFI_IFLAG_CLONABLE);
}
void
pfi_attach_ifnet(struct ifnet *ifp)
{
struct pfi_kif *p, *q, key;
int s;
pfi_initialize();
s = splsoftnet();
pfi_update++;
if (ifp->if_index >= pfi_indexlim) {
/*
* grow pfi_index2kif, similar to ifindex2ifnet code in if.c
*/
size_t m, n, oldlim;
struct pfi_kif **mp, **np;
oldlim = pfi_indexlim;
if (pfi_indexlim == 0)
pfi_indexlim = 64;
while (ifp->if_index >= pfi_indexlim)
pfi_indexlim <<= 1;
m = oldlim * sizeof(struct pfi_kif *);
mp = pfi_index2kif;
n = pfi_indexlim * sizeof(struct pfi_kif *);
np = malloc(n, PFI_MTYPE, M_DONTWAIT);
if (np == NULL)
panic("pfi_attach_ifnet: "
"cannot allocate translation table");
bzero(np, n);
if (mp != NULL)
bcopy(mp, np, m);
pfi_index2kif = np;
if (mp != NULL)
free(mp, PFI_MTYPE);
}
strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name));
p = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
if (p == NULL) {
/* add group */
pfi_copy_group(key.pfik_name, ifp->if_xname,
sizeof(key.pfik_name));
q = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
if (q == NULL)
q = pfi_if_create(key.pfik_name, pfi_self, PFI_IFLAG_GROUP);
if (q == NULL)
panic("pfi_attach_ifnet: "
"cannot allocate '%s' group", key.pfik_name);
/* add interface */
p = pfi_if_create(ifp->if_xname, q, PFI_IFLAG_INSTANCE);
if (p == NULL)
panic("pfi_attach_ifnet: "
"cannot allocate '%s' interface", ifp->if_xname);
} else
q = p->pfik_parent;
p->pfik_ifp = ifp;
p->pfik_flags |= PFI_IFLAG_ATTACHED;
p->pfik_ah_cookie =
hook_establish(ifp->if_addrhooks, 1, pfi_kifaddr_update, p);
pfi_index2kif[ifp->if_index] = p;
pfi_dohooks(p);
splx(s);
}
void
pfi_detach_ifnet(struct ifnet *ifp)
{
struct pfi_kif *p, *q, key;
int s;
strlcpy(key.pfik_name, ifp->if_xname, sizeof(key.pfik_name));
s = splsoftnet();
pfi_update++;
p = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
if (p == NULL) {
printf("pfi_detach_ifnet: cannot find %s", ifp->if_xname);
splx(s);
return;
}
hook_disestablish(p->pfik_ifp->if_addrhooks, p->pfik_ah_cookie);
q = p->pfik_parent;
p->pfik_ifp = NULL;
p->pfik_flags &= ~PFI_IFLAG_ATTACHED;
pfi_index2kif[ifp->if_index] = NULL;
pfi_dohooks(p);
pfi_maybe_destroy(p);
splx(s);
}
struct pfi_kif *
pfi_lookup_create(const char *name)
{
struct pfi_kif *p, *q, key;
int s;
s = splsoftnet();
p = pfi_lookup_if(name);
if (p == NULL) {
pfi_copy_group(key.pfik_name, name, sizeof(key.pfik_name));
q = pfi_lookup_if(key.pfik_name);
if (q != NULL)
p = pfi_if_create(name, q, PFI_IFLAG_INSTANCE);
}
splx(s);
return (p);
}
struct pfi_kif *
pfi_attach_rule(const char *name)
{
struct pfi_kif *p;
p = pfi_lookup_create(name);
if (p != NULL)
p->pfik_rules++;
return (p);
}
void
pfi_detach_rule(struct pfi_kif *p)
{
if (p == NULL)
return;
if (p->pfik_rules > 0)
p->pfik_rules--;
else
printf("pfi_detach_rule: reference count at 0\n");
pfi_maybe_destroy(p);
}
void
pfi_attach_state(struct pfi_kif *p)
{
if (!p->pfik_states++)
TAILQ_INSERT_TAIL(&pfi_statehead, p, pfik_w_states);
}
void
pfi_detach_state(struct pfi_kif *p)
{
if (p == NULL)
return;
if (p->pfik_states <= 0) {
printf("pfi_detach_state: reference count <= 0\n");
return;
}
if (!--p->pfik_states)
TAILQ_REMOVE(&pfi_statehead, p, pfik_w_states);
pfi_maybe_destroy(p);
}
int
pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
{
struct pfi_dynaddr *dyn;
char tblname[PF_TABLE_NAME_SIZE];
struct pf_ruleset *ruleset = NULL;
int s, rv = 0;
if (aw->type != PF_ADDR_DYNIFTL)
return (0);
dyn = pool_get(&pfi_addr_pl, PR_NOWAIT);
if (dyn == NULL)
return (1);
bzero(dyn, sizeof(*dyn));
s = splsoftnet();
dyn->pfid_kif = pfi_attach_rule(aw->v.ifname);
if (dyn->pfid_kif == NULL)
senderr(1);
dyn->pfid_net = pfi_unmask(&aw->v.a.mask);
if (af == AF_INET && dyn->pfid_net == 32)
dyn->pfid_net = 128;
strlcpy(tblname, aw->v.ifname, sizeof(tblname));
if (aw->iflags & PFI_AFLAG_NETWORK)
strlcat(tblname, ":network", sizeof(tblname));
if (aw->iflags & PFI_AFLAG_BROADCAST)
strlcat(tblname, ":broadcast", sizeof(tblname));
if (aw->iflags & PFI_AFLAG_PEER)
strlcat(tblname, ":peer", sizeof(tblname));
if (aw->iflags & PFI_AFLAG_NOALIAS)
strlcat(tblname, ":0", sizeof(tblname));
if (dyn->pfid_net != 128)
snprintf(tblname + strlen(tblname),
sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net);
ruleset = pf_find_or_create_ruleset(pfi_reserved_anchor,
pfi_interface_ruleset);
if (ruleset == NULL)
senderr(1);
dyn->pfid_kt = pfr_attach_table(ruleset, tblname);
if (dyn->pfid_kt == NULL)
senderr(1);
dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE;
dyn->pfid_iflags = aw->iflags;
dyn->pfid_af = af;
dyn->pfid_hook_cookie = hook_establish(dyn->pfid_kif->pfik_ah_head, 1,
pfi_dynaddr_update, dyn);
if (dyn->pfid_hook_cookie == NULL)
senderr(1);
aw->p.dyn = dyn;
pfi_dynaddr_update(aw->p.dyn);
splx(s);
return (0);
_bad:
if (dyn->pfid_kt != NULL)
pfr_detach_table(dyn->pfid_kt);
if (ruleset != NULL)
pf_remove_if_empty_ruleset(ruleset);
if (dyn->pfid_kif != NULL)
pfi_detach_rule(dyn->pfid_kif);
pool_put(&pfi_addr_pl, dyn);
splx(s);
return (rv);
}
void
pfi_dynaddr_update(void *p)
{
struct pfi_dynaddr *dyn = (struct pfi_dynaddr *)p;
struct pfi_kif *kif = dyn->pfid_kif;
struct pfr_ktable *kt = dyn->pfid_kt;
if (dyn == NULL || kif == NULL || kt == NULL)
panic("pfi_dynaddr_update");
if (kt->pfrkt_larg != pfi_update) {
/* this table needs to be brought up-to-date */
pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags);
kt->pfrkt_larg = pfi_update;
}
pfr_dynaddr_update(kt, dyn);
}
void
pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags)
{
int e, size2 = 0;
struct pfi_kif *p;
struct pfr_table t;
if ((kif->pfik_flags & PFI_IFLAG_INSTANCE) && kif->pfik_ifp == NULL) {
pfr_clr_addrs(&kt->pfrkt_t, NULL, 0);
return;
}
pfi_buffer_cnt = 0;
if ((kif->pfik_flags & PFI_IFLAG_INSTANCE))
pfi_instance_add(kif->pfik_ifp, net, flags);
else if (strcmp(kif->pfik_name, "self")) {
TAILQ_FOREACH(p, &kif->pfik_grouphead, pfik_instances)
pfi_instance_add(p->pfik_ifp, net, flags);
} else {
RB_FOREACH(p, pfi_ifhead, &pfi_ifs)
if (p->pfik_flags & PFI_IFLAG_INSTANCE)
pfi_instance_add(p->pfik_ifp, net, flags);
}
t = kt->pfrkt_t;
t.pfrt_flags = 0;
if ((e = pfr_set_addrs(&t, pfi_buffer, pfi_buffer_cnt, &size2,
NULL, NULL, NULL, 0)))
printf("pfi_table_update: cannot set %d new addresses "
"into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e);
}
void
pfi_instance_add(struct ifnet *ifp, int net, int flags)
{
struct ifaddr *ia;
int got4 = 0, got6 = 0;
int net2, af;
if (ifp == NULL)
return;
TAILQ_FOREACH(ia, &ifp->if_addrlist, ifa_list) {
if (ia->ifa_addr == NULL)
continue;
af = ia->ifa_addr->sa_family;
if (af != AF_INET && af != AF_INET6)
continue;
if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6)
continue;
if ((flags & PFI_AFLAG_BROADCAST) &&
!(ifp->if_flags & IFF_BROADCAST))
continue;
if ((flags & PFI_AFLAG_PEER) &&
!(ifp->if_flags & IFF_POINTOPOINT))
continue;
if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 &&
IN6_IS_ADDR_LINKLOCAL(
&((struct sockaddr_in6 *)ia->ifa_addr)->sin6_addr))
continue;
if (flags & PFI_AFLAG_NOALIAS) {
if (af == AF_INET && got4)
continue;
if (af == AF_INET6 && got6)
continue;
}
if (af == AF_INET)
got4 = 1;
else
got6 = 1;
net2 = net;
if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) {
if (af == AF_INET) {
net2 = pfi_unmask(&((struct sockaddr_in *)
ia->ifa_netmask)->sin_addr);
} else {
net2 = pfi_unmask(&((struct sockaddr_in6 *)
ia->ifa_netmask)->sin6_addr);
}
}
if (af == AF_INET && net2 > 32)
net2 = 32;
if (flags & PFI_AFLAG_BROADCAST)
pfi_address_add(ia->ifa_broadaddr, af, net2);
else if (flags & PFI_AFLAG_PEER)
pfi_address_add(ia->ifa_dstaddr, af, net2);
else
pfi_address_add(ia->ifa_addr, af, net2);
}
}
void
pfi_address_add(struct sockaddr *sa, int af, int net)
{
struct pfr_addr *p;
int i;
if (pfi_buffer_cnt >= pfi_buffer_max) {
int new_max = pfi_buffer_max * 2;
if (new_max > PFI_BUFFER_MAX) {
printf("pfi_address_add: address buffer full (%d/%d)\n",
pfi_buffer_cnt, PFI_BUFFER_MAX);
return;
}
p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE,
M_DONTWAIT);
if (p == NULL) {
printf("pfi_address_add: no memory to grow buffer "
"(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX);
return;
}
memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer));
/* no need to zero buffer */
free(pfi_buffer, PFI_MTYPE);
pfi_buffer = p;
pfi_buffer_max = new_max;
}
if (af == AF_INET && net > 32)
net = 128;
p = pfi_buffer + pfi_buffer_cnt++;
bzero(p, sizeof(*p));
p->pfra_af = af;
p->pfra_net = net;
if (af == AF_INET)
p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr;
if (af == AF_INET6) {
p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr;
if (IN6_IS_ADDR_LINKLOCAL(&p->pfra_ip6addr))
p->pfra_ip6addr.s6_addr16[1] = 0;
}
/* mask network address bits */
if (net < 128)
((caddr_t)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8));
for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++)
((caddr_t)p)[i] = 0;
}
void
pfi_dynaddr_remove(struct pf_addr_wrap *aw)
{
int s;
if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL ||
aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL)
return;
s = splsoftnet();
hook_disestablish(aw->p.dyn->pfid_kif->pfik_ah_head,
aw->p.dyn->pfid_hook_cookie);
pfi_detach_rule(aw->p.dyn->pfid_kif);
aw->p.dyn->pfid_kif = NULL;
pfr_detach_table(aw->p.dyn->pfid_kt);
aw->p.dyn->pfid_kt = NULL;
pool_put(&pfi_addr_pl, aw->p.dyn);
aw->p.dyn = NULL;
splx(s);
}
void
pfi_dynaddr_copyout(struct pf_addr_wrap *aw)
{
if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL ||
aw->p.dyn->pfid_kif == NULL)
return;
aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6;
}
void
pfi_kifaddr_update(void *v)
{
int s;
s = splsoftnet();
pfi_update++;
pfi_dohooks(v);
splx(s);
}
int
pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q)
{
return (strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ));
}
struct pfi_kif *
pfi_if_create(const char *name, struct pfi_kif *q, int flags)
{
struct pfi_kif *p;
p = malloc(sizeof(*p), PFI_MTYPE, M_DONTWAIT);
if (p == NULL)
return (NULL);
bzero(p, sizeof(*p));
p->pfik_ah_head = malloc(sizeof(*p->pfik_ah_head), PFI_MTYPE,
M_DONTWAIT);
if (p->pfik_ah_head == NULL) {
free(p, PFI_MTYPE);
return (NULL);
}
bzero(p->pfik_ah_head, sizeof(*p->pfik_ah_head));
TAILQ_INIT(p->pfik_ah_head);
TAILQ_INIT(&p->pfik_grouphead);
strlcpy(p->pfik_name, name, sizeof(p->pfik_name));
RB_INIT(&p->pfik_lan_ext);
RB_INIT(&p->pfik_ext_gwy);
p->pfik_flags = flags;
p->pfik_parent = q;
p->pfik_tzero = time.tv_sec;
RB_INSERT(pfi_ifhead, &pfi_ifs, p);
if (q != NULL) {
q->pfik_addcnt++;
TAILQ_INSERT_TAIL(&q->pfik_grouphead, p, pfik_instances);
}
pfi_ifcnt++;
return (p);
}
int
pfi_maybe_destroy(struct pfi_kif *p)
{
int i, j, k, s;
struct pfi_kif *q = p->pfik_parent;
if ((p->pfik_flags & (PFI_IFLAG_ATTACHED | PFI_IFLAG_GROUP)) ||
p->pfik_rules > 0 || p->pfik_states > 0)
return (0);
s = splsoftnet();
if (q != NULL) {
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
for (k = 0; k < 2; k++) {
q->pfik_bytes[i][j][k] +=
p->pfik_bytes[i][j][k];
q->pfik_packets[i][j][k] +=
p->pfik_packets[i][j][k];
}
q->pfik_delcnt++;
TAILQ_REMOVE(&q->pfik_grouphead, p, pfik_instances);
}
pfi_ifcnt--;
RB_REMOVE(pfi_ifhead, &pfi_ifs, p);
splx(s);
free(p->pfik_ah_head, PFI_MTYPE);
free(p, PFI_MTYPE);
return (1);
}
void
pfi_copy_group(char *p, const char *q, int m)
{
while (m > 1 && *q && !(*q >= '0' && *q <= '9')) {
*p++ = *q++;
m--;
}
if (m > 0)
*p++ = '\0';
}
void
pfi_dynamic_drivers(void)
{
char *buses[] = PFI_DYNAMIC_BUSES;
int nbuses = sizeof(buses)/sizeof(buses[0]);
int enabled[sizeof(buses)/sizeof(buses[0])];
struct device *dev;
struct cfdata *cf;
struct cfdriver *drv;
short *p;
int i;
bzero(enabled, sizeof(enabled));
TAILQ_FOREACH(dev, &alldevs, dv_list) {
if (!(dev->dv_flags & DVF_ACTIVE))
continue;
for (i = 0; i < nbuses; i++)
if (!enabled[i] && !strcmp(buses[i],
dev->dv_cfdata->cf_driver->cd_name))
enabled[i] = 1;
}
for (cf = cfdata; cf->cf_driver; cf++) {
if (cf->cf_driver->cd_class != DV_IFNET)
continue;
for (p = cf->cf_parents; p && *p >= 0; p++) {
if ((drv = cfdata[*p].cf_driver) == NULL)
continue;
for (i = 0; i < nbuses; i++)
if (enabled[i] &&
!strcmp(drv->cd_name, buses[i]))
break;
if (i < nbuses) {
pfi_newgroup(cf->cf_driver->cd_name,
PFI_IFLAG_DYNAMIC);
break;
}
}
}
}
void
pfi_newgroup(const char *name, int flags)
{
struct pfi_kif *p;
p = pfi_lookup_if(name);
if (p == NULL)
p = pfi_if_create(name, pfi_self, PFI_IFLAG_GROUP);
if (p == NULL) {
printf("pfi_newgroup: cannot allocate '%s' group", name);
return;
}
p->pfik_flags |= flags;
}
void
pfi_fill_oldstatus(struct pf_status *pfs)
{
struct pfi_kif *p, key;
int i, j, k, s;
strlcpy(key.pfik_name, pfs->ifname, sizeof(key.pfik_name));
s = splsoftnet();
p = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
if (p == NULL) {
splx(s);
return;
}
bzero(pfs->pcounters, sizeof(pfs->pcounters));
bzero(pfs->bcounters, sizeof(pfs->bcounters));
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
for (k = 0; k < 2; k++) {
pfs->pcounters[i][j][k] =
p->pfik_packets[i][j][k];
pfs->bcounters[i][j] +=
p->pfik_bytes[i][j][k];
}
splx(s);
}
int
pfi_clr_istats(const char *name, int *nzero, int flags)
{
struct pfi_kif *p;
int n = 0, s;
long tzero = time.tv_sec;
s = splsoftnet();
ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE);
RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
if (pfi_skip_if(name, p, flags))
continue;
bzero(p->pfik_packets, sizeof(p->pfik_packets));
bzero(p->pfik_bytes, sizeof(p->pfik_bytes));
p->pfik_tzero = tzero;
n++;
}
splx(s);
if (nzero != NULL)
*nzero = n;
return (0);
}
int
pfi_get_ifaces(const char *name, struct pfi_if *buf, int *size, int flags)
{
struct pfi_kif *p;
int s, n = 0;
ACCEPT_FLAGS(PFI_FLAG_GROUP|PFI_FLAG_INSTANCE);
s = splsoftnet();
RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
if (pfi_skip_if(name, p, flags))
continue;
if (*size > n++) {
if (!p->pfik_tzero)
p->pfik_tzero = boottime.tv_sec;
if (copyout(p, buf++, sizeof(*buf))) {
splx(s);
return (EFAULT);
}
}
}
splx(s);
*size = n;
return (0);
}
struct pfi_kif *
pfi_lookup_if(const char *name)
{
struct pfi_kif *p, key;
strlcpy(key.pfik_name, name, sizeof(key.pfik_name));
p = RB_FIND(pfi_ifhead, &pfi_ifs, &key);
return (p);
}
int
pfi_skip_if(const char *filter, struct pfi_kif *p, int f)
{
int n;
if ((p->pfik_flags & PFI_IFLAG_GROUP) && !(f & PFI_FLAG_GROUP))
return (1);
if ((p->pfik_flags & PFI_IFLAG_INSTANCE) && !(f & PFI_FLAG_INSTANCE))
return (1);
if (filter == NULL || !*filter)
return (0);
if (!strcmp(p->pfik_name, filter))
return (0); /* exact match */
n = strlen(filter);
if (n < 1 || n >= IFNAMSIZ)
return (1); /* sanity check */
if (filter[n-1] >= '0' && filter[n-1] <= '9')
return (1); /* only do exact match in that case */
if (strncmp(p->pfik_name, filter, n))
return (1); /* prefix doesn't match */
return (p->pfik_name[n] < '0' || p->pfik_name[n] > '9');
}
/* from pf_print_state.c */
int
pfi_unmask(void *addr)
{
struct pf_addr *m = addr;
int i = 31, j = 0, b = 0;
u_int32_t tmp;
while (j < 4 && m->addr32[j] == 0xffffffff) {
b += 32;
j++;
}
if (j < 4) {
tmp = ntohl(m->addr32[j]);
for (i = 31; tmp & (1 << i); --i)
b++;
}
return (b);
}
void
pfi_dohooks(struct pfi_kif *p)
{
for (; p != NULL; p = p->pfik_parent)
dohooks(p->pfik_ah_head, 0);
}
int
pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af)
{
if (af == AF_INET) {
switch (dyn->pfid_acnt4) {
case 0:
return (0);
case 1:
return (PF_MATCHA(0, &dyn->pfid_addr4,
&dyn->pfid_mask4, a, AF_INET));
default:
return (pfr_match_addr(dyn->pfid_kt, a, AF_INET));
}
} else {
switch (dyn->pfid_acnt6) {
case 0:
return (0);
case 1:
return (PF_MATCHA(0, &dyn->pfid_addr6,
&dyn->pfid_mask6, a, AF_INET6));
default:
return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6));
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
/* $OpenBSD: pf_norm.c,v 1.75.2.1 2004/04/30 23:28:36 brad Exp $ */
/* $OpenBSD: pf_norm.c,v 1.80 2004/03/09 21:44:41 mcbride Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@ -374,7 +374,7 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
if (frep != NULL &&
FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) - frep->fr_ip->ip_hl *
4 > off)
4 > off)
{
u_int16_t precut;
@ -638,8 +638,10 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
h = mtod(m, struct ip *);
KASSERT((int)m->m_len == ntohs(h->ip_len) - precut);
h->ip_off = htons(ntohs(h->ip_off) + (precut >> 3));
KASSERT((int)m->m_len ==
ntohs(h->ip_len) - precut);
h->ip_off = htons(ntohs(h->ip_off) +
(precut >> 3));
h->ip_len = htons(ntohs(h->ip_len) - precut);
} else {
hosed++;
@ -693,7 +695,8 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
m->m_pkthdr.len = plen;
}
h = mtod(m, struct ip *);
KASSERT((int)m->m_len == ntohs(h->ip_len) - aftercut);
KASSERT((int)m->m_len ==
ntohs(h->ip_len) - aftercut);
h->ip_len = htons(ntohs(h->ip_len) - aftercut);
} else {
hosed++;
@ -807,7 +810,7 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
}
int
pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
{
struct mbuf *m = *m0;
struct pf_rule *r;
@ -824,7 +827,8 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
while (r != NULL) {
r->evaluations++;
if (r->ifp != NULL && r->ifp != ifp)
if (r->kif != NULL &&
(r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@ -987,13 +991,13 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
no_mem:
REASON_SET(reason, PFRES_MEMORY);
if (r != NULL && r->log)
PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL);
PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL);
return (PF_DROP);
drop:
REASON_SET(reason, PFRES_NORM);
if (r != NULL && r->log)
PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL);
PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL);
return (PF_DROP);
bad:
@ -1005,14 +1009,15 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
REASON_SET(reason, PFRES_FRAG);
if (r != NULL && r->log)
PFLOG_PACKET(ifp, h, m, AF_INET, dir, *reason, r, NULL, NULL);
PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL);
return (PF_DROP);
}
#ifdef INET6
int
pf_normalize_ip6(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
u_short *reason)
{
struct mbuf *m = *m0;
struct pf_rule *r;
@ -1032,7 +1037,8 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
while (r != NULL) {
r->evaluations++;
if (r->ifp != NULL && r->ifp != ifp)
if (r->kif != NULL &&
(r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@ -1166,25 +1172,25 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct ifnet *ifp, u_short *reason)
shortpkt:
REASON_SET(reason, PFRES_SHORT);
if (r != NULL && r->log)
PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
return (PF_DROP);
drop:
REASON_SET(reason, PFRES_NORM);
if (r != NULL && r->log)
PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
return (PF_DROP);
badfrag:
REASON_SET(reason, PFRES_FRAG);
if (r != NULL && r->log)
PFLOG_PACKET(ifp, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
return (PF_DROP);
}
#endif
int
pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff,
pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
int off, void *h, struct pf_pdesc *pd)
{
struct pf_rule *r, *rm = NULL;
@ -1197,7 +1203,8 @@ pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff,
r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
while (r != NULL) {
r->evaluations++;
if (r->ifp != NULL && r->ifp != ifp)
if (r->kif != NULL &&
(r->kif != kif && r->kif != kif->pfik_parent) == !r->ifnot)
r = r->skip[PF_SKIP_IFP].ptr;
else if (r->direction && r->direction != dir)
r = r->skip[PF_SKIP_DIR].ptr;
@ -1290,7 +1297,7 @@ pf_normalize_tcp(int dir, struct ifnet *ifp, struct mbuf *m, int ipoff,
tcp_drop:
REASON_SET(&reason, PFRES_NORM);
if (rm != NULL && r->log)
PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, NULL, NULL);
PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, NULL, NULL);
return (PF_DROP);
}
@ -1331,7 +1338,7 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
* the connections. They must all set an enabled bit in pfss_flags
*/
if ((th->th_flags & TH_SYN) == 0)
return 0;
return (0);
if (th->th_off > (sizeof(struct tcphdr) >> 2) && src->scrub &&
@ -1355,8 +1362,8 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
}
/* FALLTHROUGH */
default:
hlen -= MAX(opt[1], 2);
opt += MAX(opt[1], 2);
hlen -= opt[1];
opt += opt[1];
break;
}
}
@ -1406,7 +1413,7 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
#endif /* INET */
#ifdef INET6
case AF_INET6: {
if (dst->scrub) {
if (src->scrub) {
struct ip6_hdr *h = mtod(m, struct ip6_hdr *);
if (h->ip6_hlim > src->scrub->pfss_ttl)
src->scrub->pfss_ttl = h->ip6_hlim;
@ -1450,11 +1457,13 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
&th->th_sum, ts_value, 0);
copyback = 1;
}
if (dst->scrub &&
/* Modulate TS reply iff valid (!0) */
memcpy(&ts_value, &opt[6],
sizeof(u_int32_t));
if (ts_value && dst->scrub &&
(dst->scrub->pfss_flags &
PFSS_TIMESTAMP)) {
memcpy(&ts_value, &opt[6],
sizeof(u_int32_t));
ts_value = htonl(ntohl(ts_value)
- dst->scrub->pfss_ts_mod);
pf_change_a(&opt[6],
@ -1464,8 +1473,8 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
}
/* FALLTHROUGH */
default:
hlen -= MAX(opt[1], 2);
opt += MAX(opt[1], 2);
hlen -= opt[1];
opt += opt[1];
break;
}
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: pf_osfp.c,v 1.3 2003/08/27 18:23:36 frantzen Exp $ */
/* $OpenBSD: pf_osfp.c,v 1.9 2004/01/04 20:08:42 pvalchev Exp $ */
/*
* Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
@ -50,13 +50,14 @@ typedef struct pool pool_t;
# include <errno.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# define pool_t int
# define pool_get(pool, flags) malloc(*(pool))
# define pool_put(pool, item) free(item)
# define pool_init(pool, size, a, ao, f, m, p) (*(pool)) = (size)
# ifdef PFDEBUG
# include <stdarg.h>
# include <sys/stdarg.h>
# define DPFPRINTF(format, x...) fprintf(stderr, format , ##x)
# else
# define DPFPRINTF(format, x...) ((void)0)
@ -106,7 +107,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 +123,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;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: pf_table.c,v 1.41 2003/08/22 15:19:23 henning Exp $ */
/* $OpenBSD: pf_table.c,v 1.47 2004/03/09 21:44:41 mcbride Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@ -49,6 +49,16 @@
return (EINVAL); \
} while (0)
#define COPYIN(from, to, size) \
((flags & PFR_FLAG_USERIOCTL) ? \
copyin((from), (to), (size)) : \
(bcopy((from), (to), (size)), 0))
#define COPYOUT(from, to, size) \
((flags & PFR_FLAG_USERIOCTL) ? \
copyout((from), (to), (size)) : \
(bcopy((from), (to), (size)), 0))
#define FILLIN_SIN(sin, addr) \
do { \
(sin).sin_len = sizeof(sin); \
@ -71,8 +81,8 @@
} while (0)
#define SUNION2PF(su, af) (((af)==AF_INET) ? \
(struct pf_addr *)&(su)->sin.sin_addr : \
(struct pf_addr *)&(su)->sin6.sin6_addr)
(struct pf_addr *)&(su)->sin.sin_addr : \
(struct pf_addr *)&(su)->sin6.sin6_addr)
#define AF_BITS(af) (((af)==AF_INET)?32:128)
#define ADDR_NETWORK(ad) ((ad)->pfra_net < AF_BITS((ad)->pfra_af))
@ -91,20 +101,24 @@ struct pfr_walktree {
PFRW_ENQUEUE,
PFRW_GET_ADDRS,
PFRW_GET_ASTATS,
PFRW_POOL_GET
PFRW_POOL_GET,
PFRW_DYNADDR_UPDATE
} pfrw_op;
union {
struct pfr_addr *pfrw1_addr;
struct pfr_astats *pfrw1_astats;
struct pfr_kentryworkq *pfrw1_workq;
struct pfr_kentry *pfrw1_kentry;
struct pfi_dynaddr *pfrw1_dyn;
} pfrw_1;
int pfrw_free;
int pfrw_flags;
};
#define pfrw_addr pfrw_1.pfrw1_addr
#define pfrw_astats pfrw_1.pfrw1_astats
#define pfrw_workq pfrw_1.pfrw1_workq
#define pfrw_kentry pfrw_1.pfrw1_kentry
#define pfrw_dyn pfrw_1.pfrw1_dyn
#define pfrw_cnt pfrw_free
#define senderr(e) do { rv = (e); goto _bad; } while (0)
@ -113,7 +127,7 @@ struct pool pfr_ktable_pl;
struct pool pfr_kentry_pl;
struct sockaddr_in pfr_sin;
struct sockaddr_in6 pfr_sin6;
union sockaddr_union pfr_mask;
union sockaddr_union pfr_mask;
struct pf_addr pfr_ffaddr;
void pfr_copyout_addr(struct pfr_addr *,
@ -133,14 +147,14 @@ void pfr_remove_kentries(struct pfr_ktable *,
struct pfr_kentryworkq *);
void pfr_clstats_kentries(struct pfr_kentryworkq *, long,
int);
void pfr_reset_feedback(struct pfr_addr *, int);
void pfr_reset_feedback(struct pfr_addr *, int, int);
void pfr_prepare_network(union sockaddr_union *, int, int);
int pfr_route_kentry(struct pfr_ktable *,
struct pfr_kentry *);
int pfr_unroute_kentry(struct pfr_ktable *,
struct pfr_kentry *);
int pfr_walktree(struct radix_node *, void *);
int pfr_validate_table(struct pfr_table *, int);
int pfr_validate_table(struct pfr_table *, int, int);
void pfr_commit_ktable(struct pfr_ktable *, long);
void pfr_insert_ktables(struct pfr_ktableworkq *);
void pfr_insert_ktable(struct pfr_ktable *);
@ -160,7 +174,7 @@ void pfr_clean_node_mask(struct pfr_ktable *,
int pfr_table_count(struct pfr_table *, int);
int pfr_skip_table(struct pfr_table *,
struct pfr_ktable *, int);
struct pfr_kentry *pfr_kentry_byidx(struct pfr_ktable *, int, int);
struct pfr_kentry *pfr_kentry_byidx(struct pfr_ktable *, int, int);
RB_PROTOTYPE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
RB_GENERATE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
@ -193,7 +207,7 @@ pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
int s;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
if (pfr_validate_table(tbl, 0))
if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@ -229,7 +243,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
long tzero = time.tv_sec;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
if (pfr_validate_table(tbl, 0))
if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@ -241,7 +255,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (ENOMEM);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
if (copyin(addr+i, &ad, sizeof(ad)))
if (COPYIN(addr+i, &ad, sizeof(ad)))
senderr(EFAULT);
if (pfr_validate_addr(&ad))
senderr(EINVAL);
@ -270,7 +284,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
}
}
if (flags & PFR_FLAG_FEEDBACK)
if (copyout(&ad, addr+i, sizeof(ad)))
if (COPYOUT(&ad, addr+i, sizeof(ad)))
senderr(EFAULT);
}
pfr_clean_node_mask(tmpkt, &workq);
@ -290,7 +304,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
pfr_clean_node_mask(tmpkt, &workq);
pfr_destroy_kentries(&workq);
if (flags & PFR_FLAG_FEEDBACK)
pfr_reset_feedback(addr, size);
pfr_reset_feedback(addr, size, flags);
pfr_destroy_ktable(tmpkt, 0);
return (rv);
}
@ -306,7 +320,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
int i, rv, s, xdel = 0;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
if (pfr_validate_table(tbl, 0))
if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@ -316,7 +330,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
pfr_mark_addrs(kt);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
if (copyin(addr+i, &ad, sizeof(ad)))
if (COPYIN(addr+i, &ad, sizeof(ad)))
senderr(EFAULT);
if (pfr_validate_addr(&ad))
senderr(EINVAL);
@ -338,7 +352,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
xdel++;
}
if (flags & PFR_FLAG_FEEDBACK)
if (copyout(&ad, addr+i, sizeof(ad)))
if (COPYOUT(&ad, addr+i, sizeof(ad)))
senderr(EFAULT);
}
if (!(flags & PFR_FLAG_DUMMY)) {
@ -353,7 +367,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (0);
_bad:
if (flags & PFR_FLAG_FEEDBACK)
pfr_reset_feedback(addr, size);
pfr_reset_feedback(addr, size, flags);
return (rv);
}
@ -369,7 +383,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
long tzero = time.tv_sec;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
if (pfr_validate_table(tbl, 0))
if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@ -384,7 +398,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
SLIST_INIT(&delq);
SLIST_INIT(&changeq);
for (i = 0; i < size; i++) {
if (copyin(addr+i, &ad, sizeof(ad)))
if (COPYIN(addr+i, &ad, sizeof(ad)))
senderr(EFAULT);
if (pfr_validate_addr(&ad))
senderr(EINVAL);
@ -421,7 +435,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
}
_skip:
if (flags & PFR_FLAG_FEEDBACK)
if (copyout(&ad, addr+i, sizeof(ad)))
if (COPYOUT(&ad, addr+i, sizeof(ad)))
senderr(EFAULT);
}
pfr_enqueue_addrs(kt, &delq, &xdel, ENQUEUE_UNMARKED_ONLY);
@ -434,7 +448,7 @@ 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 (copyout(&ad, addr+size+i, sizeof(ad)))
if (COPYOUT(&ad, addr+size+i, sizeof(ad)))
senderr(EFAULT);
i++;
}
@ -456,7 +470,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
*ndel = xdel;
if (nchange != NULL)
*nchange = xchange;
if ((flags & PFR_FLAG_FEEDBACK) && *size2)
if ((flags & PFR_FLAG_FEEDBACK) && size2)
*size2 = size+xdel;
pfr_destroy_ktable(tmpkt, 0);
return (0);
@ -464,7 +478,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
pfr_clean_node_mask(tmpkt, &addq);
pfr_destroy_kentries(&addq);
if (flags & PFR_FLAG_FEEDBACK)
pfr_reset_feedback(addr, size);
pfr_reset_feedback(addr, size, flags);
pfr_destroy_ktable(tmpkt, 0);
return (rv);
}
@ -479,14 +493,14 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
int i, xmatch = 0;
ACCEPT_FLAGS(PFR_FLAG_REPLACE);
if (pfr_validate_table(tbl, 0))
if (pfr_validate_table(tbl, 0, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
return (ESRCH);
for (i = 0; i < size; i++) {
if (copyin(addr+i, &ad, sizeof(ad)))
if (COPYIN(addr+i, &ad, sizeof(ad)))
return (EFAULT);
if (pfr_validate_addr(&ad))
return (EINVAL);
@ -499,7 +513,7 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
(p->pfrke_not ? PFR_FB_NOTMATCH : PFR_FB_MATCH);
if (p != NULL && !p->pfrke_not)
xmatch++;
if (copyout(&ad, addr+i, sizeof(ad)))
if (COPYOUT(&ad, addr+i, sizeof(ad)))
return (EFAULT);
}
if (nmatch != NULL)
@ -516,7 +530,7 @@ pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
int rv;
ACCEPT_FLAGS(0);
if (pfr_validate_table(tbl, 0))
if (pfr_validate_table(tbl, 0, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@ -530,6 +544,7 @@ pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
w.pfrw_op = PFRW_GET_ADDRS;
w.pfrw_addr = addr;
w.pfrw_free = kt->pfrkt_cnt;
w.pfrw_flags = flags;
rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
if (!rv)
rv = rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
@ -556,7 +571,7 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
long tzero = time.tv_sec;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC); /* XXX PFR_FLAG_CLSTATS disabled */
if (pfr_validate_table(tbl, 0))
if (pfr_validate_table(tbl, 0, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@ -570,6 +585,7 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
w.pfrw_op = PFRW_GET_ASTATS;
w.pfrw_astats = addr;
w.pfrw_free = kt->pfrkt_cnt;
w.pfrw_flags = flags;
if (flags & PFR_FLAG_ATOMIC)
s = splsoftnet();
rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
@ -604,14 +620,14 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
int i, rv, s, xzero = 0;
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
if (pfr_validate_table(tbl, 0))
if (pfr_validate_table(tbl, 0, 0))
return (EINVAL);
kt = pfr_lookup_table(tbl);
if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
return (ESRCH);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
if (copyin(addr+i, &ad, sizeof(ad)))
if (COPYIN(addr+i, &ad, sizeof(ad)))
senderr(EFAULT);
if (pfr_validate_addr(&ad))
senderr(EINVAL);
@ -619,7 +635,7 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
if (flags & PFR_FLAG_FEEDBACK) {
ad.pfra_fback = (p != NULL) ?
PFR_FB_CLEARED : PFR_FB_NONE;
if (copyout(&ad, addr+i, sizeof(ad)))
if (COPYOUT(&ad, addr+i, sizeof(ad)))
senderr(EFAULT);
}
if (p != NULL) {
@ -640,7 +656,7 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (0);
_bad:
if (flags & PFR_FLAG_FEEDBACK)
pfr_reset_feedback(addr, size);
pfr_reset_feedback(addr, size, flags);
return (rv);
}
@ -817,10 +833,10 @@ void
pfr_clean_node_mask(struct pfr_ktable *kt,
struct pfr_kentryworkq *workq)
{
struct pfr_kentry *p;
struct pfr_kentry *p;
SLIST_FOREACH(p, workq, pfrke_workq)
pfr_unroute_kentry(kt, p);
SLIST_FOREACH(p, workq, pfrke_workq)
pfr_unroute_kentry(kt, p);
}
void
@ -841,16 +857,16 @@ pfr_clstats_kentries(struct pfr_kentryworkq *workq, long tzero, int negchange)
}
void
pfr_reset_feedback(struct pfr_addr *addr, int size)
pfr_reset_feedback(struct pfr_addr *addr, int size, int flags)
{
struct pfr_addr ad;
int i;
for (i = 0; i < size; i++) {
if (copyin(addr+i, &ad, sizeof(ad)))
if (COPYIN(addr+i, &ad, sizeof(ad)))
break;
ad.pfra_fback = PFR_FB_NONE;
if (copyout(&ad, addr+i, sizeof(ad)))
if (COPYOUT(&ad, addr+i, sizeof(ad)))
break;
}
}
@ -953,7 +969,7 @@ pfr_walktree(struct radix_node *rn, void *arg)
{
struct pfr_kentry *ke = (struct pfr_kentry *)rn;
struct pfr_walktree *w = arg;
int s;
int s, flags = w->pfrw_flags;
switch (w->pfrw_op) {
case PFRW_MARK:
@ -962,7 +978,7 @@ pfr_walktree(struct radix_node *rn, void *arg)
case PFRW_SWEEP:
if (ke->pfrke_mark)
break;
/* fall trough */
/* FALLTHROUGH */
case PFRW_ENQUEUE:
SLIST_INSERT_HEAD(w->pfrw_workq, ke, pfrke_workq);
w->pfrw_cnt++;
@ -991,7 +1007,7 @@ pfr_walktree(struct radix_node *rn, void *arg)
splx(s);
as.pfras_tzero = ke->pfrke_tzero;
if (copyout(&as, w->pfrw_astats, sizeof(as)))
if (COPYOUT(&as, w->pfrw_astats, sizeof(as)))
return (EFAULT);
w->pfrw_astats++;
}
@ -1004,6 +1020,25 @@ pfr_walktree(struct radix_node *rn, void *arg)
return (1); /* finish search */
}
break;
case PFRW_DYNADDR_UPDATE:
if (ke->pfrke_af == AF_INET) {
if (w->pfrw_dyn->pfid_acnt4++ > 0)
break;
pfr_prepare_network(&pfr_mask, AF_INET, ke->pfrke_net);
w->pfrw_dyn->pfid_addr4 = *SUNION2PF(
&ke->pfrke_sa, AF_INET);
w->pfrw_dyn->pfid_mask4 = *SUNION2PF(
&pfr_mask, AF_INET);
} else {
if (w->pfrw_dyn->pfid_acnt6++ > 0)
break;
pfr_prepare_network(&pfr_mask, AF_INET6, ke->pfrke_net);
w->pfrw_dyn->pfid_addr6 = *SUNION2PF(
&ke->pfrke_sa, AF_INET6);
w->pfrw_dyn->pfid_mask6 = *SUNION2PF(
&pfr_mask, AF_INET6);
}
break;
}
return (0);
}
@ -1023,6 +1058,8 @@ pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
if (pfr_skip_table(filter, p, flags))
continue;
if (!strcmp(p->pfrkt_anchor, PF_RESERVED_ANCHOR))
continue;
if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE))
continue;
p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE;
@ -1053,9 +1090,10 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
SLIST_INIT(&addq);
SLIST_INIT(&changeq);
for (i = 0; i < size; i++) {
if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
senderr(EFAULT);
if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK))
if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK,
flags & PFR_FLAG_USERIOCTL))
senderr(EINVAL);
key.pfrkt_flags |= PFR_TFLAG_ACTIVE;
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
@ -1131,9 +1169,10 @@ pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
return (EFAULT);
if (pfr_validate_table(&key.pfrkt_t, 0))
if (pfr_validate_table(&key.pfrkt_t, 0,
flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
@ -1180,7 +1219,7 @@ pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
continue;
if (n-- <= 0)
continue;
if (copyout(&p->pfrkt_t, tbl++, sizeof(*tbl)))
if (COPYOUT(&p->pfrkt_t, tbl++, sizeof(*tbl)))
return (EFAULT);
}
if (n) {
@ -1219,7 +1258,7 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
continue;
if (!(flags & PFR_FLAG_ATOMIC))
s = splsoftnet();
if (copyout(&p->pfrkt_ts, tbl++, sizeof(*tbl))) {
if (COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl))) {
splx(s);
return (EFAULT);
}
@ -1251,9 +1290,9 @@ pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ADDRSTOO);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
return (EFAULT);
if (pfr_validate_table(&key.pfrkt_t, 0))
if (pfr_validate_table(&key.pfrkt_t, 0, 0))
return (EINVAL);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (p != NULL) {
@ -1288,9 +1327,10 @@ pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
return (EINVAL);
SLIST_INIT(&workq);
for (i = 0; i < size; i++) {
if (copyin(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
return (EFAULT);
if (pfr_validate_table(&key.pfrkt_t, 0))
if (pfr_validate_table(&key.pfrkt_t, 0,
flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
@ -1374,7 +1414,8 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
ACCEPT_FLAGS(PFR_FLAG_DUMMY|PFR_FLAG_ADDRSTOO);
if (size && !(flags & PFR_FLAG_ADDRSTOO))
return (EINVAL);
if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK))
if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK,
flags & PFR_FLAG_USERIOCTL))
return (EINVAL);
rs = pf_find_ruleset(tbl->pfrt_anchor, tbl->pfrt_ruleset);
if (rs == NULL || !rs->topen || ticket != rs->tticket)
@ -1416,7 +1457,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
}
SLIST_INIT(&addrq);
for (i = 0; i < size; i++) {
if (copyin(addr+i, &ad, sizeof(ad)))
if (COPYIN(addr+i, &ad, sizeof(ad)))
senderr(EFAULT);
if (pfr_validate_addr(&ad))
senderr(EINVAL);
@ -1458,6 +1499,37 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
return (rv);
}
int
pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
{
struct pfr_ktableworkq workq;
struct pfr_ktable *p;
struct pf_ruleset *rs;
int xdel = 0;
ACCEPT_FLAGS(PFR_FLAG_DUMMY);
rs = pf_find_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
if (rs == NULL || !rs->topen || ticket != rs->tticket)
return (0);
SLIST_INIT(&workq);
RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
pfr_skip_table(trs, p, 0))
continue;
p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE;
SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
xdel++;
}
if (!(flags & PFR_FLAG_DUMMY)) {
pfr_setflags_ktables(&workq);
rs->topen = 0;
pf_remove_if_empty_ruleset(rs);
}
if (ndel != NULL)
*ndel = xdel;
return (0);
}
int
pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
int *nchange, int flags)
@ -1563,12 +1635,14 @@ pfr_commit_ktable(struct pfr_ktable *kt, long tzero)
}
int
pfr_validate_table(struct pfr_table *tbl, int allowedflags)
pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved)
{
int i;
if (!tbl->pfrt_name[0])
return (-1);
if (no_reserved && !strcmp(tbl->pfrt_anchor, PF_RESERVED_ANCHOR))
return (-1);
if (tbl->pfrt_name[PF_TABLE_NAME_SIZE-1])
return (-1);
for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++)
@ -1786,15 +1860,16 @@ pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q)
if ((d = strncmp(p->pfrkt_anchor, q->pfrkt_anchor,
PF_ANCHOR_NAME_SIZE)))
return (d);
return strncmp(p->pfrkt_ruleset, q->pfrkt_ruleset,
PF_RULESET_NAME_SIZE);
return (strncmp(p->pfrkt_ruleset, q->pfrkt_ruleset,
PF_RULESET_NAME_SIZE));
}
struct pfr_ktable *
pfr_lookup_table(struct pfr_table *tbl)
{
/* struct pfr_ktable start like a struct pfr_table */
return RB_FIND(pfr_ktablehead, &pfr_ktables, (struct pfr_ktable *)tbl);
return (RB_FIND(pfr_ktablehead, &pfr_ktables,
(struct pfr_ktable *)tbl));
}
int
@ -1806,7 +1881,7 @@ pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
kt = kt->pfrkt_root;
if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
return 0;
return (0);
switch (af) {
case AF_INET:
@ -1904,7 +1979,7 @@ pfr_attach_table(struct pf_ruleset *rs, char *name)
}
if (!kt->pfrkt_refcnt[PFR_REFCNT_RULE]++)
pfr_setflags_ktable(kt, kt->pfrkt_flags|PFR_TFLAG_REFERENCED);
return kt;
return (kt);
}
void
@ -1970,7 +2045,7 @@ pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter,
}
for (;;) {
/* we don't want to use a nested block */
ke2 = (struct pfr_kentry *)(af == AF_INET ?
ke2 = (struct pfr_kentry *)(af == AF_INET ?
rn_match(&pfr_sin, kt->pfrkt_ip4) :
rn_match(&pfr_sin6, kt->pfrkt_ip6));
/* no need to check KENTRY_RNF_ROOT() here */
@ -2000,19 +2075,38 @@ pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
{
struct pfr_walktree w;
bzero(&w, sizeof(w));
w.pfrw_op = PFRW_POOL_GET;
w.pfrw_cnt = idx;
bzero(&w, sizeof(w));
w.pfrw_op = PFRW_POOL_GET;
w.pfrw_cnt = idx;
switch(af) {
switch (af) {
case AF_INET:
rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
return w.pfrw_kentry;
return (w.pfrw_kentry);
case AF_INET6:
rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
return w.pfrw_kentry;
return (w.pfrw_kentry);
default:
return NULL;
return (NULL);
}
}
void
pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn)
{
struct pfr_walktree w;
int s;
bzero(&w, sizeof(w));
w.pfrw_op = PFRW_DYNADDR_UPDATE;
w.pfrw_dyn = dyn;
s = splsoftnet();
dyn->pfid_acnt4 = 0;
dyn->pfid_acnt6 = 0;
if (!dyn->pfid_af || dyn->pfid_af == AF_INET)
rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
if (!dyn->pfid_af || dyn->pfid_af == AF_INET6)
rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
splx(s);
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: pfvar.h,v 1.170 2003/08/22 21:50:34 david Exp $ */
/* $OpenBSD: pfvar.h,v 1.187 2004/03/22 04:54:18 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@ -47,6 +47,7 @@ struct ip;
#define PF_TCPS_PROXY_DST ((TCP_NSTATES)+1)
enum { PF_INOUT, PF_IN, PF_OUT };
enum { PF_LAN_EXT, PF_EXT_GWY, PF_ID };
enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NAT, PF_NONAT,
PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP };
enum { PF_RULESET_SCRUB, PF_RULESET_FILTER, PF_RULESET_NAT,
@ -67,16 +68,17 @@ enum { PFTM_TCP_FIRST_PACKET, PFTM_TCP_OPENING, PFTM_TCP_ESTABLISHED,
PFTM_ICMP_FIRST_PACKET, PFTM_ICMP_ERROR_REPLY,
PFTM_OTHER_FIRST_PACKET, PFTM_OTHER_SINGLE,
PFTM_OTHER_MULTIPLE, PFTM_FRAG, PFTM_INTERVAL,
PFTM_ADAPTIVE_START, PFTM_ADAPTIVE_END, PFTM_MAX,
PFTM_PURGE, PFTM_UNTIL_PACKET };
PFTM_ADAPTIVE_START, PFTM_ADAPTIVE_END, PFTM_SRC_NODE,
PFTM_MAX, PFTM_PURGE, PFTM_UNTIL_PACKET };
enum { PF_NOPFROUTE, PF_FASTROUTE, PF_ROUTETO, PF_DUPTO, PF_REPLYTO };
enum { PF_LIMIT_STATES, PF_LIMIT_FRAGS, PF_LIMIT_MAX };
enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS, PF_LIMIT_MAX };
#define PF_POOL_IDMASK 0x0f
enum { PF_POOL_NONE, PF_POOL_BITMASK, PF_POOL_RANDOM,
PF_POOL_SRCHASH, PF_POOL_ROUNDROBIN };
enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL,
PF_ADDR_TABLE };
#define PF_POOL_TYPEMASK 0x0f
#define PF_POOL_STICKYADDR 0x20
#define PF_WSCALE_FLAG 0x80
#define PF_WSCALE_MASK 0x0f
@ -97,6 +99,12 @@ struct pf_addr {
#define PF_TABLE_NAME_SIZE 32
#define PFI_AFLAG_NETWORK 0x01
#define PFI_AFLAG_BROADCAST 0x02
#define PFI_AFLAG_PEER 0x04
#define PFI_AFLAG_MODEMASK 0x07
#define PFI_AFLAG_NOALIAS 0x08
struct pf_addr_wrap {
union {
struct {
@ -107,28 +115,36 @@ struct pf_addr_wrap {
char tblname[PF_TABLE_NAME_SIZE];
} v;
union {
struct pf_addr_dyn *dyn;
struct pfi_dynaddr *dyn;
struct pfr_ktable *tbl;
int dyncnt;
int tblcnt;
} p;
u_int8_t type; /* PF_ADDR_* */
u_int8_t iflags; /* PFI_AFLAG_* */
};
struct pf_addr_dyn {
char ifname[IFNAMSIZ];
struct ifnet *ifp;
struct pf_addr *addr;
sa_family_t af;
void *hook_cookie;
u_int8_t undefined;
#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_* */
};
/*
* Address manipulation macros
*/
#ifdef _KERNEL
#ifdef INET
#ifndef INET6
#define PF_INET_ONLY
@ -265,10 +281,7 @@ struct pf_addr_dyn {
((aw)->type == PF_ADDR_TABLE && \
!pfr_match_addr((aw)->p.tbl, (x), (af))) || \
((aw)->type == PF_ADDR_DYNIFTL && \
((aw)->p.dyn->undefined || \
(!PF_AZERO(&(aw)->v.a.mask, (af)) && \
!PF_MATCHA(0, &(aw)->v.a.addr, \
&(aw)->v.a.mask, (x), (af))))) || \
!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, \
@ -297,7 +310,7 @@ struct pf_pooladdr {
struct pf_addr_wrap addr;
TAILQ_ENTRY(pf_pooladdr) entries;
char ifname[IFNAMSIZ];
struct ifnet *ifp;
struct pfi_kif *kif;
};
TAILQ_HEAD(pf_palist, pf_pooladdr);
@ -446,7 +459,6 @@ struct pf_rule {
union pf_rule_ptr skip[PF_SKIP_COUNT];
#define PF_RULE_LABEL_SIZE 64
char label[PF_RULE_LABEL_SIZE];
u_int32_t timeout[PFTM_MAX];
#define PF_QNAME_SIZE 16
char ifname[IFNAMSIZ];
char qname[PF_QNAME_SIZE];
@ -464,12 +476,17 @@ struct pf_rule {
u_int64_t packets;
u_int64_t bytes;
struct ifnet *ifp;
struct pfi_kif *kif;
struct pf_anchor *anchor;
pf_osfp_t os_fingerprint;
u_int32_t timeout[PFTM_MAX];
u_int32_t states;
u_int32_t max_states;
u_int32_t src_nodes;
u_int32_t max_src_nodes;
u_int32_t max_src_states;
u_int32_t qid;
u_int32_t pqid;
u_int32_t rt_listid;
@ -516,6 +533,9 @@ struct pf_rule {
#define PFRULE_FRAGMENT 0x0002
#define PFRULE_RETURNICMP 0x0004
#define PFRULE_RETURN 0x0008
#define PFRULE_NOSYNC 0x0010
#define PFRULE_SRCTRACK 0x0020 /* track source states */
#define PFRULE_RULESRCTRACK 0x0040 /* per rule */
/* scrub flags */
#define PFRULE_NODF 0x0100
@ -524,8 +544,28 @@ struct pf_rule {
#define PFRULE_RANDOMID 0x0800
#define PFRULE_REASSEMBLE_TCP 0x1000
/* rule flags again */
#define PFRULE_IFBOUND 0x00010000 /* if-bound */
#define PFRULE_GRBOUND 0x00020000 /* group-bound */
#define PFSTATE_HIWAT 10000 /* default state table size */
struct pf_src_node {
RB_ENTRY(pf_src_node) entry;
struct pf_addr addr;
struct pf_addr raddr;
union pf_rule_ptr rule;
struct pfi_kif *kif;
u_int32_t bytes;
u_int32_t packets;
u_int32_t states;
u_int32_t creation;
u_int32_t expire;
sa_family_t af;
u_int8_t ruletype;
};
#define PFSNODE_HIWAT 10000 /* default source node table size */
struct pf_state_scrub {
u_int16_t pfss_flags;
@ -552,7 +592,20 @@ struct pf_state_peer {
struct pf_state_scrub *scrub; /* state is scrubbed */
};
TAILQ_HEAD(pf_state_queue, pf_state);
struct pf_state {
u_int64_t id;
union {
struct {
RB_ENTRY(pf_state) entry_lan_ext;
RB_ENTRY(pf_state) entry_ext_gwy;
RB_ENTRY(pf_state) entry_id;
TAILQ_ENTRY(pf_state) entry_updates;
struct pfi_kif *kif;
} s;
char ifname[IFNAMSIZ];
} u;
struct pf_state_host lan;
struct pf_state_host gwy;
struct pf_state_host ext;
@ -562,27 +615,25 @@ struct pf_state {
union pf_rule_ptr anchor;
union pf_rule_ptr nat_rule;
struct pf_addr rt_addr;
struct ifnet *rt_ifp;
struct pfi_kif *rt_kif;
struct pf_src_node *src_node;
struct pf_src_node *nat_src_node;
u_int32_t creation;
u_int32_t expire;
u_int32_t pfsync_time;
u_int32_t packets[2];
u_int32_t bytes[2];
u_int32_t creatorid;
sa_family_t af;
u_int8_t proto;
u_int8_t direction;
u_int8_t log;
u_int8_t allow_opts;
u_int8_t timeout;
u_int8_t pad[2];
};
struct pf_tree_node {
RB_ENTRY(pf_tree_node) entry;
struct pf_state *state;
struct pf_addr addr[2];
u_int16_t port[2];
sa_family_t af;
u_int8_t proto;
u_int8_t sync_flags;
#define PFSTATE_NOSYNC 0x01
#define PFSTATE_FROMSYNC 0x02
u_int8_t pad;
};
TAILQ_HEAD(pf_rulequeue, pf_rule);
@ -598,6 +649,7 @@ struct pf_ruleset {
struct {
struct pf_rulequeue *ptr;
u_int32_t ticket;
int open;
} active, inactive;
} rules[PF_RULESET_MAX];
struct pf_anchor *anchor;
@ -617,6 +669,9 @@ struct pf_anchor {
TAILQ_HEAD(pf_anchorqueue, pf_anchor);
#define PF_RESERVED_ANCHOR "_pf"
#define PF_INTERFACE_RULESET "_if"
#define PFR_TFLAG_PERSIST 0x00000001
#define PFR_TFLAG_CONST 0x00000002
#define PFR_TFLAG_ACTIVE 0x00000004
@ -703,12 +758,13 @@ struct pfr_ktable {
struct pfr_ktable *pfrkt_shadow;
struct pfr_ktable *pfrkt_root;
struct pf_ruleset *pfrkt_rs;
long pfrkt_larg;
int pfrkt_nflags;
};
#define pfrkt_t pfrkt_ts.pfrts_t
#define pfrkt_name pfrkt_t.pfrt_name
#define pfrkt_anchor pfrkt_t.pfrt_anchor
#define pfrkt_ruleset pfrkt_t.pfrt_ruleset
#define pfrkt_anchor pfrkt_t.pfrt_anchor
#define pfrkt_ruleset pfrkt_t.pfrt_ruleset
#define pfrkt_flags pfrkt_t.pfrt_flags
#define pfrkt_cnt pfrkt_ts.pfrts_cnt
#define pfrkt_refcnt pfrkt_ts.pfrts_refcnt
@ -718,6 +774,60 @@ struct pfr_ktable {
#define pfrkt_nomatch pfrkt_ts.pfrts_nomatch
#define pfrkt_tzero pfrkt_ts.pfrts_tzero
RB_HEAD(pf_state_tree_lan_ext, pf_state);
RB_PROTOTYPE(pf_state_tree_lan_ext, pf_state,
u.s.entry_lan_ext, pf_state_compare_lan_ext);
RB_HEAD(pf_state_tree_ext_gwy, pf_state);
RB_PROTOTYPE(pf_state_tree_ext_gwy, pf_state,
u.s.entry_ext_gwy, pf_state_compare_ext_gwy);
struct pfi_if {
char pfif_name[IFNAMSIZ];
u_int64_t pfif_packets[2][2][2];
u_int64_t pfif_bytes[2][2][2];
u_int64_t pfif_addcnt;
u_int64_t pfif_delcnt;
long pfif_tzero;
int pfif_states;
int pfif_rules;
int pfif_flags;
};
TAILQ_HEAD(pfi_grouphead, pfi_kif);
TAILQ_HEAD(pfi_statehead, pfi_kif);
RB_HEAD(pfi_ifhead, pfi_kif);
struct pfi_kif {
struct pfi_if pfik_if;
RB_ENTRY(pfi_kif) pfik_tree;
struct pf_state_tree_lan_ext pfik_lan_ext;
struct pf_state_tree_ext_gwy pfik_ext_gwy;
struct pfi_grouphead pfik_grouphead;
TAILQ_ENTRY(pfi_kif) pfik_instances;
TAILQ_ENTRY(pfi_kif) pfik_w_states;
struct hook_desc_head *pfik_ah_head;
void *pfik_ah_cookie;
struct pfi_kif *pfik_parent;
struct ifnet *pfik_ifp;
int pfik_states;
int pfik_rules;
};
#define pfik_name pfik_if.pfif_name
#define pfik_packets pfik_if.pfif_packets
#define pfik_bytes pfik_if.pfif_bytes
#define pfik_tzero pfik_if.pfif_tzero
#define pfik_flags pfik_if.pfif_flags
#define pfik_addcnt pfik_if.pfif_addcnt
#define pfik_delcnt pfik_if.pfif_delcnt
#define pfik_states pfik_if.pfif_states
#define pfik_rules pfik_if.pfif_rules
#define PFI_IFLAG_GROUP 0x0001 /* group of interfaces */
#define PFI_IFLAG_INSTANCE 0x0002 /* single instance */
#define PFI_IFLAG_CLONABLE 0x0010 /* clonable group */
#define PFI_IFLAG_DYNAMIC 0x0020 /* dynamic group */
#define PFI_IFLAG_ATTACHED 0x0040 /* interface attached */
struct pf_pdesc {
u_int64_t tot_len; /* Make Mickey money */
union {
@ -729,6 +839,9 @@ struct pf_pdesc {
#endif /* INET6 */
void *any;
} hdr;
struct pf_addr baddr; /* address before translation */
struct pf_addr naddr; /* address after translation */
struct pf_rule *nat_rule; /* nat/rdr rule applied to packet */
struct pf_addr *src;
struct pf_addr *dst;
u_int16_t *ip_sum;
@ -797,6 +910,10 @@ struct pf_pdesc {
#define FCNT_STATE_REMOVALS 2
#define FCNT_MAX 3
#define SCNT_SRC_NODE_SEARCH 0
#define SCNT_SRC_NODE_INSERT 1
#define SCNT_SRC_NODE_REMOVALS 2
#define SCNT_MAX 3
#define ACTION_SET(a, x) \
do { \
@ -815,12 +932,16 @@ struct pf_pdesc {
struct pf_status {
u_int64_t counters[PFRES_MAX];
u_int64_t fcounters[FCNT_MAX];
u_int64_t scounters[SCNT_MAX];
u_int64_t pcounters[2][2][3];
u_int64_t bcounters[2][2];
u_int64_t stateid;
u_int32_t running;
u_int32_t states;
u_int32_t src_nodes;
u_int32_t since;
u_int32_t debug;
u_int32_t hostid;
char ifname[IFNAMSIZ];
};
@ -952,6 +1073,7 @@ struct pfioc_state_kill {
int psk_proto;
struct pf_rule_addr psk_src;
struct pf_rule_addr psk_dst;
char psk_ifname[IFNAMSIZ];
};
struct pfioc_states {
@ -964,6 +1086,16 @@ struct pfioc_states {
#define ps_states ps_u.psu_states
};
struct pfioc_src_nodes {
int psn_len;
union {
caddr_t psu_buf;
struct pf_src_node *psu_src_nodes;
} psn_u;
#define psn_buf psn_u.psu_buf
#define psn_src_nodes psn_u.psu_src_nodes
};
struct pfioc_if {
char ifname[IFNAMSIZ];
};
@ -1004,6 +1136,19 @@ struct pfioc_ruleset {
char name[PF_RULESET_NAME_SIZE];
};
#define PF_RULESET_ALTQ (PF_RULESET_MAX)
#define PF_RULESET_TABLE (PF_RULESET_MAX+1)
struct pfioc_trans {
int size; /* number of elements */
int esize; /* size of each element in bytes */
struct pfioc_trans_e {
int rs_num;
char anchor[PF_ANCHOR_NAME_SIZE];
char ruleset[PF_RULESET_NAME_SIZE];
u_int32_t ticket;
} *array;
};
#define PFR_FLAG_ATOMIC 0x00000001
#define PFR_FLAG_DUMMY 0x00000002
#define PFR_FLAG_FEEDBACK 0x00000004
@ -1012,6 +1157,9 @@ struct pfioc_ruleset {
#define PFR_FLAG_REPLACE 0x00000020
#define PFR_FLAG_ALLRSETS 0x00000040
#define PFR_FLAG_ALLMASK 0x0000007F
#ifdef _KERNEL
#define PFR_FLAG_USERIOCTL 0x10000000
#endif
struct pfioc_table {
struct pfr_table pfrio_table;
@ -1033,6 +1181,20 @@ struct pfioc_table {
#define pfrio_clrflag pfrio_nadd
#define PFI_FLAG_GROUP 0x0001 /* gets groups of interfaces */
#define PFI_FLAG_INSTANCE 0x0002 /* gets single interfaces */
#define PFI_FLAG_ALLMASK 0x0003
struct pfioc_iface {
char pfiio_name[IFNAMSIZ];
void *pfiio_buffer;
int pfiio_esize;
int pfiio_size;
int pfiio_nzero;
int pfiio_flags;
};
/*
* ioctl operations
*/
@ -1045,7 +1207,7 @@ struct pfioc_table {
#define DIOCGETRULES _IOWR('D', 6, struct pfioc_rule)
#define DIOCGETRULE _IOWR('D', 7, struct pfioc_rule)
/* XXX cut 8 - 17 */
#define DIOCCLRSTATES _IO ('D', 18)
#define DIOCCLRSTATES _IOWR('D', 18, struct pfioc_state_kill)
#define DIOCGETSTATE _IOWR('D', 19, struct pfioc_state)
#define DIOCSETSTATUSIF _IOWR('D', 20, struct pfioc_if)
#define DIOCGETSTATUS _IOWR('D', 21, struct pf_status)
@ -1101,23 +1263,38 @@ 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)
#define DIOCXBEGIN _IOWR('D', 81, struct pfioc_trans)
#define DIOCXCOMMIT _IOWR('D', 82, struct pfioc_trans)
#define DIOCXROLLBACK _IOWR('D', 83, struct pfioc_trans)
#define DIOCGETSRCNODES _IOWR('D', 84, struct pfioc_src_nodes)
#define DIOCCLRSRCNODES _IO('D', 85)
#define DIOCSETHOSTID _IOWR('D', 86, u_int32_t)
#define DIOCIGETIFACES _IOWR('D', 87, struct pfioc_iface)
#define DIOCICLRISTATS _IOWR('D', 88, struct pfioc_iface)
#ifdef _KERNEL
RB_HEAD(pf_state_tree, pf_tree_node);
RB_PROTOTYPE(pf_state_tree, pf_tree_node, entry, pf_state_compare);
extern struct pf_state_tree tree_lan_ext, tree_ext_gwy;
RB_HEAD(pf_src_tree, pf_src_node);
RB_PROTOTYPE(pf_src_tree, pf_src_node, entry, pf_src_compare);
extern struct pf_src_tree tree_src_tracking;
extern struct pf_anchorqueue pf_anchors;
extern struct pf_ruleset pf_main_ruleset;
RB_HEAD(pf_state_tree_id, pf_state);
RB_PROTOTYPE(pf_state_tree_id, pf_state,
entry_id, pf_state_compare_id);
extern struct pf_state_tree_id tree_id;
extern struct pf_state_queue state_updates;
extern struct pf_anchorqueue pf_anchors;
extern struct pf_ruleset pf_main_ruleset;
TAILQ_HEAD(pf_poolqueue, pf_pool);
extern struct pf_poolqueue pf_pools[2];
extern struct pf_poolqueue pf_pools[2];
TAILQ_HEAD(pf_altqqueue, pf_altq);
extern struct pf_altqqueue pf_altqs[2];
extern struct pf_palist pf_pabuf;
extern struct 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;
extern int altqs_inactive_open;
extern u_int32_t ticket_pabuf;
extern struct pf_altqqueue *pf_altqs_active;
extern struct pf_altqqueue *pf_altqs_inactive;
@ -1127,29 +1304,32 @@ extern int pf_tbladdr_setup(struct pf_ruleset *,
struct pf_addr_wrap *);
extern void pf_tbladdr_remove(struct pf_addr_wrap *);
extern void pf_tbladdr_copyout(struct pf_addr_wrap *);
extern int pf_dynaddr_setup(struct pf_addr_wrap *,
sa_family_t);
extern void pf_dynaddr_copyout(struct pf_addr_wrap *);
extern void pf_dynaddr_remove(struct pf_addr_wrap *);
extern void pf_calc_skip_steps(struct pf_rulequeue *);
extern void pf_rule_set_qid(struct pf_rulequeue *);
extern u_int32_t pf_qname_to_qid(char *);
extern void pf_update_anchor_rules(void);
extern struct pool pf_tree_pl, pf_rule_pl, pf_addr_pl;
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;
extern void pf_purge_timeout(void *);
extern void pf_purge_expired_src_nodes(void);
extern void pf_purge_expired_states(void);
extern int pf_insert_state(struct pf_state *);
extern struct pf_state *pf_find_state(struct pf_state_tree *,
struct pf_tree_node *);
extern int pf_insert_state(struct pfi_kif *,
struct pf_state *);
extern int pf_insert_src_node(struct pf_src_node **,
struct pf_rule *, struct pf_addr *,
sa_family_t);
void pf_src_tree_remove_state(struct pf_state *);
extern struct pf_state *pf_find_state_byid(struct pf_state *);
extern struct pf_state *pf_find_state_all(struct pf_state *key,
u_int8_t tree, int *more);
extern struct pf_anchor *pf_find_anchor(const char *);
extern struct pf_ruleset *pf_find_ruleset(char *, char *);
extern struct pf_ruleset *pf_find_or_create_ruleset(char *, char *);
extern struct pf_ruleset *pf_find_or_create_ruleset(
char[PF_ANCHOR_NAME_SIZE],
char[PF_RULESET_NAME_SIZE]);
extern void pf_remove_if_empty_ruleset(
struct pf_ruleset *);
extern struct ifnet *status_ifp;
extern struct ifnet *sync_ifp;
extern struct pf_rule pf_default_rule;
extern void pf_addrcpy(struct pf_addr *, struct pf_addr *,
u_int8_t);
@ -1170,7 +1350,7 @@ void pf_addr_inc(struct pf_addr *, sa_family_t);
void *pf_pull_hdr(struct mbuf *, int, void *, int, u_short *, u_short *,
sa_family_t);
void pf_change_a(void *, u_int16_t *, u_int32_t, u_int8_t);
int pflog_packet(struct ifnet *, struct mbuf *, sa_family_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 *);
int pf_match_addr(u_int8_t, struct pf_addr *, struct pf_addr *,
struct pf_addr *, sa_family_t);
@ -1180,9 +1360,9 @@ int pf_match_uid(u_int8_t, uid_t, uid_t, uid_t);
int pf_match_gid(u_int8_t, gid_t, gid_t, gid_t);
void pf_normalize_init(void);
int pf_normalize_ip(struct mbuf **, int, struct ifnet *, u_short *);
int pf_normalize_ip6(struct mbuf **, int, struct ifnet *, u_short *);
int pf_normalize_tcp(int, struct ifnet *, struct mbuf *, int, int, void *,
int pf_normalize_ip(struct mbuf **, int, struct pfi_kif *, u_short *);
int pf_normalize_ip6(struct mbuf **, int, struct pfi_kif *, u_short *);
int pf_normalize_tcp(int, struct pfi_kif *, struct mbuf *, int, int, void *,
struct pf_pdesc *);
void pf_normalize_tcp_cleanup(struct pf_state *);
int pf_normalize_tcp_init(struct mbuf *, int, struct pf_pdesc *,
@ -1200,6 +1380,7 @@ void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t,
u_int64_t, int, int, int);
int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *,
struct pf_addr **, struct pf_addr **, sa_family_t);
void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *);
struct pfr_ktable *
pfr_attach_table(struct pf_ruleset *, char *);
void pfr_detach_table(struct pfr_ktable *);
@ -1224,14 +1405,40 @@ int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *,
int pfr_tst_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
int);
int pfr_ina_begin(struct pfr_table *, u_int32_t *, int *, int);
int pfr_ina_rollback(struct pfr_table *, u_int32_t, int *, int);
int pfr_ina_commit(struct pfr_table *, u_int32_t, int *, int *, int);
int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
int *, u_int32_t, int);
void pfi_initialize(void);
void pfi_attach_clone(struct if_clone *);
void pfi_attach_ifnet(struct ifnet *);
void pfi_detach_ifnet(struct ifnet *);
struct pfi_kif *pfi_lookup_create(const char *);
struct pfi_kif *pfi_lookup_if(const char *);
int pfi_maybe_destroy(struct pfi_kif *);
struct pfi_kif *pfi_attach_rule(const char *);
void pfi_detach_rule(struct pfi_kif *);
void pfi_attach_state(struct pfi_kif *);
void pfi_detach_state(struct pfi_kif *);
int pfi_dynaddr_setup(struct pf_addr_wrap *, sa_family_t);
void pfi_dynaddr_copyout(struct pf_addr_wrap *);
void pfi_dynaddr_remove(struct pf_addr_wrap *);
void pfi_fill_oldstatus(struct pf_status *);
int pfi_clr_istats(const char *, int *, int);
int pfi_get_ifaces(const char *, struct pfi_if *, int *, int);
int pfi_match_addr(struct pfi_dynaddr *, struct pf_addr *,
sa_family_t);
extern struct pfi_statehead pfi_statehead;
u_int16_t pf_tagname2tag(char *);
void pf_tag2tagname(u_int16_t, char *);
void pf_tag_unref(u_int16_t);
int pf_tag_packet(struct mbuf *, struct pf_tag *, int);
u_int32_t pf_qname2qid(char *);
void pf_qid2qname(u_int32_t, char *);
void pf_qid_unref(u_int32_t);
extern struct pf_status pf_status;
extern struct pool pf_frent_pl, pf_frag_pl;