Import pf from OpenBSD 3.7 (OPENBSD_3_7 as of today)
This commit is contained in:
parent
61ba182027
commit
f0d663ded8
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: if_pflog.c,v 1.11 2003/12/31 11:18:25 cedric Exp $ */
|
||||
/* $OpenBSD: if_pflog.c,v 1.12 2004/05/19 17:50:51 dhartmei Exp $ */
|
||||
/*
|
||||
* The authors of this code are John Ioannidis (ji@tla.org),
|
||||
* Angelos D. Keromytis (kermit@csd.uch.gr) and
|
||||
@ -197,11 +197,9 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
|
||||
} else {
|
||||
hdr.rulenr = htonl(am->nr);
|
||||
hdr.subrulenr = htonl(rm->nr);
|
||||
if (ruleset != NULL)
|
||||
memcpy(hdr.ruleset, ruleset->name,
|
||||
if (ruleset != NULL && ruleset->anchor != NULL)
|
||||
strlcpy(hdr.ruleset, ruleset->anchor->name,
|
||||
sizeof(hdr.ruleset));
|
||||
|
||||
|
||||
}
|
||||
hdr.dir = dir;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: if_pflog.h,v 1.10 2004/03/19 04:52:04 frantzen Exp $ */
|
||||
/* $OpenBSD: if_pflog.h,v 1.11 2004/05/19 17:50:51 dhartmei Exp $ */
|
||||
/*
|
||||
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
@ -31,10 +31,7 @@ struct pflog_softc {
|
||||
struct ifnet sc_if; /* the interface */
|
||||
};
|
||||
|
||||
/* XXX keep in sync with pfvar.h */
|
||||
#ifndef PF_RULESET_NAME_SIZE
|
||||
#define PF_RULESET_NAME_SIZE 16
|
||||
#endif
|
||||
#define PFLOG_RULESET_NAME_SIZE 16
|
||||
|
||||
struct pfloghdr {
|
||||
u_int8_t length;
|
||||
@ -42,7 +39,7 @@ struct pfloghdr {
|
||||
u_int8_t action;
|
||||
u_int8_t reason;
|
||||
char ifname[IFNAMSIZ];
|
||||
char ruleset[PF_RULESET_NAME_SIZE];
|
||||
char ruleset[PFLOG_RULESET_NAME_SIZE];
|
||||
u_int32_t rulenr;
|
||||
u_int32_t subrulenr;
|
||||
u_int8_t dir;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: if_pfsync.c,v 1.26 2004/03/28 18:14:20 mcbride Exp $ */
|
||||
/* $OpenBSD: if_pfsync.c,v 1.46 2005/02/20 15:58:38 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Michael Shalayeff
|
||||
@ -37,11 +37,14 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/timeout.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <net/bpf.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/tcp_seq.h>
|
||||
|
||||
#ifdef INET
|
||||
#include <netinet/in.h>
|
||||
@ -58,6 +61,11 @@
|
||||
#include <netinet6/nd6.h>
|
||||
#endif /* INET6 */
|
||||
|
||||
#include "carp.h"
|
||||
#if NCARP > 0
|
||||
extern int carp_suppress_preempt;
|
||||
#endif
|
||||
|
||||
#include <net/pfvar.h>
|
||||
#include <net/if_pfsync.h>
|
||||
|
||||
@ -72,7 +80,6 @@ int pfsyncdebug;
|
||||
#endif
|
||||
|
||||
struct pfsync_softc pfsyncif;
|
||||
int pfsync_sync_ok;
|
||||
struct pfsyncstats pfsyncstats;
|
||||
|
||||
void pfsyncattach(int);
|
||||
@ -91,10 +98,8 @@ void pfsync_send_bus(struct pfsync_softc *, u_int8_t);
|
||||
void pfsync_bulk_update(void *);
|
||||
void pfsync_bulkfail(void *);
|
||||
|
||||
int pfsync_sync_ok;
|
||||
extern int ifqmaxlen;
|
||||
extern struct timeval time;
|
||||
extern struct timeval mono_time;
|
||||
extern int hz;
|
||||
|
||||
void
|
||||
pfsyncattach(int npfsync)
|
||||
@ -108,6 +113,7 @@ pfsyncattach(int npfsync)
|
||||
pfsyncif.sc_statep.s = NULL;
|
||||
pfsyncif.sc_statep_net.s = NULL;
|
||||
pfsyncif.sc_maxupdates = 128;
|
||||
pfsyncif.sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
|
||||
pfsyncif.sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP;
|
||||
pfsyncif.sc_ureq_received = 0;
|
||||
pfsyncif.sc_ureq_sent = 0;
|
||||
@ -193,6 +199,9 @@ pfsync_insert_net_state(struct pfsync_state *sp)
|
||||
st->rule.ptr = r;
|
||||
/* XXX get pointers to nat_rule and anchor */
|
||||
|
||||
/* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */
|
||||
r->states++;
|
||||
|
||||
/* fill in the rest of the state entry */
|
||||
pf_state_host_ntoh(&sp->lan, &st->lan);
|
||||
pf_state_host_ntoh(&sp->gwy, &st->gwy);
|
||||
@ -202,8 +211,8 @@ pfsync_insert_net_state(struct pfsync_state *sp)
|
||||
pf_state_peer_ntoh(&sp->dst, &st->dst);
|
||||
|
||||
bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr));
|
||||
st->creation = ntohl(sp->creation) + time.tv_sec;
|
||||
st->expire = ntohl(sp->expire) + time.tv_sec;
|
||||
st->creation = time_second - ntohl(sp->creation);
|
||||
st->expire = ntohl(sp->expire) + time_second;
|
||||
|
||||
st->af = sp->af;
|
||||
st->proto = sp->proto;
|
||||
@ -214,11 +223,13 @@ pfsync_insert_net_state(struct pfsync_state *sp)
|
||||
|
||||
bcopy(sp->id, &st->id, sizeof(st->id));
|
||||
st->creatorid = sp->creatorid;
|
||||
st->sync_flags = sp->sync_flags | PFSTATE_FROMSYNC;
|
||||
st->sync_flags = PFSTATE_FROMSYNC;
|
||||
|
||||
|
||||
if (pf_insert_state(kif, st)) {
|
||||
pfi_maybe_destroy(kif);
|
||||
/* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */
|
||||
r->states--;
|
||||
pool_put(&pf_state_pl, st);
|
||||
return (EINVAL);
|
||||
}
|
||||
@ -241,7 +252,7 @@ pfsync_input(struct mbuf *m, ...)
|
||||
struct pfsync_state_bus *bus;
|
||||
struct in_addr src;
|
||||
struct mbuf *mp;
|
||||
int iplen, action, error, i, s, count, offp;
|
||||
int iplen, action, error, i, s, count, offp, sfail, stale = 0;
|
||||
|
||||
pfsyncstats.pfsyncs_ipackets++;
|
||||
|
||||
@ -297,6 +308,7 @@ pfsync_input(struct mbuf *m, ...)
|
||||
|
||||
switch (action) {
|
||||
case PFSYNC_ACT_CLR: {
|
||||
struct pf_state *nexts;
|
||||
struct pfi_kif *kif;
|
||||
u_int32_t creatorid;
|
||||
if ((mp = m_pulldown(m, iplen + sizeof(*ph),
|
||||
@ -309,9 +321,13 @@ pfsync_input(struct mbuf *m, ...)
|
||||
|
||||
s = splsoftnet();
|
||||
if (cp->ifname[0] == '\0') {
|
||||
RB_FOREACH(st, pf_state_tree_id, &tree_id) {
|
||||
if (st->creatorid == creatorid)
|
||||
for (st = RB_MIN(pf_state_tree_id, &tree_id);
|
||||
st; st = nexts) {
|
||||
nexts = RB_NEXT(pf_state_tree_id, &tree_id, st);
|
||||
if (st->creatorid == creatorid) {
|
||||
st->timeout = PFTM_PURGE;
|
||||
pf_purge_expired_state(st);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
kif = pfi_lookup_if(cp->ifname);
|
||||
@ -322,13 +338,16 @@ pfsync_input(struct mbuf *m, ...)
|
||||
splx(s);
|
||||
goto done;
|
||||
}
|
||||
RB_FOREACH(st, pf_state_tree_lan_ext,
|
||||
&kif->pfik_lan_ext) {
|
||||
if (st->creatorid == creatorid)
|
||||
for (st = RB_MIN(pf_state_tree_lan_ext,
|
||||
&kif->pfik_lan_ext); st; st = nexts) {
|
||||
nexts = RB_NEXT(pf_state_tree_lan_ext,
|
||||
&kif->pfik_lan_ext, st);
|
||||
if (st->creatorid == creatorid) {
|
||||
st->timeout = PFTM_PURGE;
|
||||
pf_purge_expired_state(st);
|
||||
}
|
||||
}
|
||||
}
|
||||
pf_purge_expired_states();
|
||||
splx(s);
|
||||
|
||||
break;
|
||||
@ -376,6 +395,8 @@ pfsync_input(struct mbuf *m, ...)
|
||||
s = splsoftnet();
|
||||
for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
|
||||
i < count; i++, sp++) {
|
||||
int flags = PFSYNC_FLAG_STALE;
|
||||
|
||||
/* check for invalid values */
|
||||
if (sp->timeout >= PFTM_MAX ||
|
||||
sp->src.state > PF_TCPS_PROXY_DST ||
|
||||
@ -397,12 +418,73 @@ pfsync_input(struct mbuf *m, ...)
|
||||
pfsyncstats.pfsyncs_badstate++;
|
||||
continue;
|
||||
}
|
||||
sfail = 0;
|
||||
if (st->proto == IPPROTO_TCP) {
|
||||
/*
|
||||
* The state should never go backwards except
|
||||
* for syn-proxy states. Neither should the
|
||||
* sequence window slide backwards.
|
||||
*/
|
||||
if (st->src.state > sp->src.state &&
|
||||
(st->src.state < PF_TCPS_PROXY_SRC ||
|
||||
sp->src.state >= PF_TCPS_PROXY_SRC))
|
||||
sfail = 1;
|
||||
else if (SEQ_GT(st->src.seqlo,
|
||||
ntohl(sp->src.seqlo)))
|
||||
sfail = 3;
|
||||
else if (st->dst.state > sp->dst.state) {
|
||||
/* There might still be useful
|
||||
* information about the src state here,
|
||||
* so import that part of the update,
|
||||
* then "fail" so we send the updated
|
||||
* state back to the peer who is missing
|
||||
* our what we know. */
|
||||
pf_state_peer_ntoh(&sp->src, &st->src);
|
||||
/* XXX do anything with timeouts? */
|
||||
sfail = 7;
|
||||
flags = 0;
|
||||
} else if (st->dst.state >= TCPS_SYN_SENT &&
|
||||
SEQ_GT(st->dst.seqlo, ntohl(sp->dst.seqlo)))
|
||||
sfail = 4;
|
||||
} else {
|
||||
/*
|
||||
* Non-TCP protocol state machine always go
|
||||
* forwards
|
||||
*/
|
||||
if (st->src.state > sp->src.state)
|
||||
sfail = 5;
|
||||
else if ( st->dst.state > sp->dst.state)
|
||||
sfail = 6;
|
||||
}
|
||||
if (sfail) {
|
||||
if (pf_status.debug >= PF_DEBUG_MISC)
|
||||
printf("pfsync: %s stale update "
|
||||
"(%d) id: %016llx "
|
||||
"creatorid: %08x\n",
|
||||
(sfail < 7 ? "ignoring"
|
||||
: "partial"), sfail,
|
||||
betoh64(st->id),
|
||||
ntohl(st->creatorid));
|
||||
pfsyncstats.pfsyncs_badstate++;
|
||||
|
||||
if (!(sp->sync_flags & PFSTATE_STALE)) {
|
||||
/* we have a better state, send it */
|
||||
if (sc->sc_mbuf != NULL && !stale)
|
||||
pfsync_sendout(sc);
|
||||
stale++;
|
||||
if (!st->sync_flags)
|
||||
pfsync_pack_state(
|
||||
PFSYNC_ACT_UPD, st, flags);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
pf_state_peer_ntoh(&sp->src, &st->src);
|
||||
pf_state_peer_ntoh(&sp->dst, &st->dst);
|
||||
st->expire = ntohl(sp->expire) + time.tv_sec;
|
||||
st->expire = ntohl(sp->expire) + time_second;
|
||||
st->timeout = sp->timeout;
|
||||
|
||||
}
|
||||
if (stale && sc->sc_mbuf != NULL)
|
||||
pfsync_sendout(sc);
|
||||
splx(s);
|
||||
break;
|
||||
/*
|
||||
@ -427,15 +509,10 @@ pfsync_input(struct mbuf *m, ...)
|
||||
pfsyncstats.pfsyncs_badstate++;
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* XXX
|
||||
* pf_purge_expired_states() is expensive,
|
||||
* we really want to purge the state directly.
|
||||
*/
|
||||
st->timeout = PFTM_PURGE;
|
||||
st->sync_flags |= PFSTATE_FROMSYNC;
|
||||
pf_purge_expired_state(st);
|
||||
}
|
||||
pf_purge_expired_states();
|
||||
splx(s);
|
||||
break;
|
||||
case PFSYNC_ACT_UPD_C: {
|
||||
@ -468,17 +545,71 @@ pfsync_input(struct mbuf *m, ...)
|
||||
st = pf_find_state_byid(&key);
|
||||
if (st == NULL) {
|
||||
/* We don't have this state. Ask for it. */
|
||||
pfsync_request_update(up, &src);
|
||||
error = pfsync_request_update(up, &src);
|
||||
if (error == ENOMEM) {
|
||||
splx(s);
|
||||
goto done;
|
||||
}
|
||||
update_requested = 1;
|
||||
pfsyncstats.pfsyncs_badstate++;
|
||||
continue;
|
||||
}
|
||||
sfail = 0;
|
||||
if (st->proto == IPPROTO_TCP) {
|
||||
/*
|
||||
* The state should never go backwards except
|
||||
* for syn-proxy states. Neither should the
|
||||
* sequence window slide backwards.
|
||||
*/
|
||||
if (st->src.state > up->src.state &&
|
||||
(st->src.state < PF_TCPS_PROXY_SRC ||
|
||||
up->src.state >= PF_TCPS_PROXY_SRC))
|
||||
sfail = 1;
|
||||
else if (st->dst.state > up->dst.state)
|
||||
sfail = 2;
|
||||
else if (SEQ_GT(st->src.seqlo,
|
||||
ntohl(up->src.seqlo)))
|
||||
sfail = 3;
|
||||
else if (st->dst.state >= TCPS_SYN_SENT &&
|
||||
SEQ_GT(st->dst.seqlo, ntohl(up->dst.seqlo)))
|
||||
sfail = 4;
|
||||
} else {
|
||||
/*
|
||||
* Non-TCP protocol state machine always go
|
||||
* forwards
|
||||
*/
|
||||
if (st->src.state > up->src.state)
|
||||
sfail = 5;
|
||||
else if (st->dst.state > up->dst.state)
|
||||
sfail = 6;
|
||||
}
|
||||
if (sfail) {
|
||||
if (pf_status.debug >= PF_DEBUG_MISC)
|
||||
printf("pfsync: ignoring stale update "
|
||||
"(%d) id: %016llx "
|
||||
"creatorid: %08x\n", sfail,
|
||||
betoh64(st->id),
|
||||
ntohl(st->creatorid));
|
||||
pfsyncstats.pfsyncs_badstate++;
|
||||
|
||||
/* we have a better state, send it out */
|
||||
if ((!stale || update_requested) &&
|
||||
sc->sc_mbuf != NULL) {
|
||||
pfsync_sendout(sc);
|
||||
update_requested = 0;
|
||||
}
|
||||
stale++;
|
||||
if (!st->sync_flags)
|
||||
pfsync_pack_state(PFSYNC_ACT_UPD, st,
|
||||
PFSYNC_FLAG_STALE);
|
||||
continue;
|
||||
}
|
||||
pf_state_peer_ntoh(&up->src, &st->src);
|
||||
pf_state_peer_ntoh(&up->dst, &st->dst);
|
||||
st->expire = ntohl(up->expire) + time.tv_sec;
|
||||
st->expire = ntohl(up->expire) + time_second;
|
||||
st->timeout = up->timeout;
|
||||
}
|
||||
if (update_requested)
|
||||
if ((update_requested || stale) && sc->sc_mbuf)
|
||||
pfsync_sendout(sc);
|
||||
splx(s);
|
||||
break;
|
||||
@ -501,15 +632,10 @@ pfsync_input(struct mbuf *m, ...)
|
||||
pfsyncstats.pfsyncs_badstate++;
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* XXX
|
||||
* pf_purge_expired_states() is expensive,
|
||||
* we really want to purge the state directly.
|
||||
*/
|
||||
st->timeout = PFTM_PURGE;
|
||||
st->sync_flags |= PFSTATE_FROMSYNC;
|
||||
pf_purge_expired_state(st);
|
||||
}
|
||||
pf_purge_expired_states();
|
||||
splx(s);
|
||||
break;
|
||||
case PFSYNC_ACT_INS_F:
|
||||
@ -524,7 +650,6 @@ pfsync_input(struct mbuf *m, ...)
|
||||
}
|
||||
|
||||
s = splsoftnet();
|
||||
/* XXX send existing. pfsync_pack_state should handle this. */
|
||||
if (sc->sc_mbuf != NULL)
|
||||
pfsync_sendout(sc);
|
||||
for (i = 0,
|
||||
@ -534,7 +659,7 @@ pfsync_input(struct mbuf *m, ...)
|
||||
key.creatorid = rup->creatorid;
|
||||
|
||||
if (key.id == 0 && key.creatorid == 0) {
|
||||
sc->sc_ureq_received = mono_time.tv_sec;
|
||||
sc->sc_ureq_received = time_uptime;
|
||||
if (pf_status.debug >= PF_DEBUG_MISC)
|
||||
printf("pfsync: received "
|
||||
"bulk update request\n");
|
||||
@ -546,7 +671,9 @@ pfsync_input(struct mbuf *m, ...)
|
||||
pfsyncstats.pfsyncs_badstate++;
|
||||
continue;
|
||||
}
|
||||
pfsync_pack_state(PFSYNC_ACT_UPD, st, 0);
|
||||
if (!st->sync_flags)
|
||||
pfsync_pack_state(PFSYNC_ACT_UPD,
|
||||
st, 0);
|
||||
}
|
||||
}
|
||||
if (sc->sc_mbuf != NULL)
|
||||
@ -574,12 +701,16 @@ pfsync_input(struct mbuf *m, ...)
|
||||
"update start\n");
|
||||
break;
|
||||
case PFSYNC_BUS_END:
|
||||
if (mono_time.tv_sec - ntohl(bus->endtime) >=
|
||||
if (time_uptime - ntohl(bus->endtime) >=
|
||||
sc->sc_ureq_sent) {
|
||||
/* that's it, we're happy */
|
||||
sc->sc_ureq_sent = 0;
|
||||
sc->sc_bulk_tries = 0;
|
||||
timeout_del(&sc->sc_bulkfail_tmo);
|
||||
#if NCARP > 0
|
||||
if (!pfsync_sync_ok)
|
||||
carp_suppress_preempt--;
|
||||
#endif
|
||||
pfsync_sync_ok = 1;
|
||||
if (pf_status.debug >= PF_DEBUG_MISC)
|
||||
printf("pfsync: received valid "
|
||||
@ -643,8 +774,9 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
case SIOCGETPFSYNC:
|
||||
bzero(&pfsyncr, sizeof(pfsyncr));
|
||||
if (sc->sc_sync_ifp)
|
||||
strlcpy(pfsyncr.pfsyncr_syncif,
|
||||
strlcpy(pfsyncr.pfsyncr_syncdev,
|
||||
sc->sc_sync_ifp->if_xname, IFNAMSIZ);
|
||||
pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer;
|
||||
pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates;
|
||||
if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr))))
|
||||
return (error);
|
||||
@ -655,11 +787,17 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr))))
|
||||
return (error);
|
||||
|
||||
if (pfsyncr.pfsyncr_syncpeer.s_addr == 0)
|
||||
sc->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
|
||||
else
|
||||
sc->sc_sync_peer.s_addr =
|
||||
pfsyncr.pfsyncr_syncpeer.s_addr;
|
||||
|
||||
if (pfsyncr.pfsyncr_maxupdates > 255)
|
||||
return (EINVAL);
|
||||
sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates;
|
||||
|
||||
if (pfsyncr.pfsyncr_syncif[0] == 0) {
|
||||
if (pfsyncr.pfsyncr_syncdev[0] == 0) {
|
||||
sc->sc_sync_ifp = NULL;
|
||||
if (sc->sc_mbuf_net != NULL) {
|
||||
/* Don't keep stale pfsync packets around. */
|
||||
@ -669,12 +807,15 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
sc->sc_statep_net.s = NULL;
|
||||
splx(s);
|
||||
}
|
||||
if (imo->imo_num_memberships > 0) {
|
||||
in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
|
||||
imo->imo_multicast_ifp = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ((sifp = ifunit(pfsyncr.pfsyncr_syncif)) == NULL)
|
||||
|
||||
if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL)
|
||||
return (EINVAL);
|
||||
else if (sifp == sc->sc_sync_ifp)
|
||||
break;
|
||||
|
||||
s = splnet();
|
||||
if (sifp->if_mtu < sc->sc_if.if_mtu ||
|
||||
@ -691,12 +832,21 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
imo->imo_multicast_ifp = NULL;
|
||||
}
|
||||
|
||||
if (sc->sc_sync_ifp) {
|
||||
if (sc->sc_sync_ifp &&
|
||||
sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
|
||||
struct in_addr addr;
|
||||
|
||||
if (!(sc->sc_sync_ifp->if_flags & IFF_MULTICAST)) {
|
||||
sc->sc_sync_ifp = NULL;
|
||||
splx(s);
|
||||
return (EADDRNOTAVAIL);
|
||||
}
|
||||
|
||||
addr.s_addr = INADDR_PFSYNC_GROUP;
|
||||
|
||||
if ((imo->imo_membership[0] =
|
||||
in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) {
|
||||
sc->sc_sync_ifp = NULL;
|
||||
splx(s);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
@ -704,14 +854,25 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
imo->imo_multicast_ifp = sc->sc_sync_ifp;
|
||||
imo->imo_multicast_ttl = PFSYNC_DFLTTL;
|
||||
imo->imo_multicast_loop = 0;
|
||||
}
|
||||
|
||||
if (sc->sc_sync_ifp ||
|
||||
sc->sc_sendaddr.s_addr != INADDR_PFSYNC_GROUP) {
|
||||
/* Request a full state table update. */
|
||||
sc->sc_ureq_sent = mono_time.tv_sec;
|
||||
sc->sc_ureq_sent = time_uptime;
|
||||
#if NCARP > 0
|
||||
if (pfsync_sync_ok)
|
||||
carp_suppress_preempt++;
|
||||
#endif
|
||||
pfsync_sync_ok = 0;
|
||||
if (pf_status.debug >= PF_DEBUG_MISC)
|
||||
printf("pfsync: requesting bulk update\n");
|
||||
timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
|
||||
pfsync_request_update(NULL, NULL);
|
||||
error = pfsync_request_update(NULL, NULL);
|
||||
if (error == ENOMEM) {
|
||||
splx(s);
|
||||
return (ENOMEM);
|
||||
}
|
||||
pfsync_sendout(sc);
|
||||
}
|
||||
splx(s);
|
||||
@ -808,7 +969,7 @@ pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp)
|
||||
}
|
||||
|
||||
int
|
||||
pfsync_pack_state(u_int8_t action, struct pf_state *st, int compress)
|
||||
pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags)
|
||||
{
|
||||
struct ifnet *ifp = &pfsyncif.sc_if;
|
||||
struct pfsync_softc *sc = ifp->if_softc;
|
||||
@ -825,7 +986,8 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int compress)
|
||||
* If a packet falls in the forest and there's nobody around to
|
||||
* hear, does it make a sound?
|
||||
*/
|
||||
if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL) {
|
||||
if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL &&
|
||||
sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
|
||||
/* Don't leave any stale pfsync packets hanging around. */
|
||||
if (sc->sc_mbuf != NULL) {
|
||||
m_freem(sc->sc_mbuf);
|
||||
@ -879,9 +1041,9 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int compress)
|
||||
}
|
||||
}
|
||||
|
||||
secs = time.tv_sec;
|
||||
secs = time_second;
|
||||
|
||||
st->pfsync_time = mono_time.tv_sec;
|
||||
st->pfsync_time = time_uptime;
|
||||
TAILQ_REMOVE(&state_updates, st, u.s.entry_updates);
|
||||
TAILQ_INSERT_TAIL(&state_updates, st, u.s.entry_updates);
|
||||
|
||||
@ -924,7 +1086,8 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int compress)
|
||||
sp->allow_opts = st->allow_opts;
|
||||
sp->timeout = st->timeout;
|
||||
|
||||
sp->sync_flags = st->sync_flags & PFSTATE_NOSYNC;
|
||||
if (flags & PFSYNC_FLAG_STALE)
|
||||
sp->sync_flags |= PFSTATE_STALE;
|
||||
}
|
||||
|
||||
pf_state_peer_hton(&st->src, &sp->src);
|
||||
@ -936,7 +1099,7 @@ pfsync_pack_state(u_int8_t action, struct pf_state *st, int compress)
|
||||
sp->expire = htonl(st->expire - secs);
|
||||
|
||||
/* do we need to build "compressed" actions for network transfer? */
|
||||
if (sc->sc_sync_ifp && compress) {
|
||||
if (sc->sc_sync_ifp && flags & PFSYNC_FLAG_COMPRESS) {
|
||||
switch (action) {
|
||||
case PFSYNC_ACT_UPD:
|
||||
newaction = PFSYNC_ACT_UPD_C;
|
||||
@ -1010,24 +1173,20 @@ pfsync_request_update(struct pfsync_state_upd *up, struct in_addr *src)
|
||||
struct pfsync_header *h;
|
||||
struct pfsync_softc *sc = ifp->if_softc;
|
||||
struct pfsync_state_upd_req *rup;
|
||||
int s, ret;
|
||||
int ret = 0;
|
||||
|
||||
if (sc->sc_mbuf == NULL) {
|
||||
if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
|
||||
(void *)&sc->sc_statep.s)) == NULL) {
|
||||
splx(s);
|
||||
(void *)&sc->sc_statep.s)) == NULL)
|
||||
return (ENOMEM);
|
||||
}
|
||||
h = mtod(sc->sc_mbuf, struct pfsync_header *);
|
||||
} else {
|
||||
h = mtod(sc->sc_mbuf, struct pfsync_header *);
|
||||
if (h->action != PFSYNC_ACT_UREQ) {
|
||||
pfsync_sendout(sc);
|
||||
if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
|
||||
(void *)&sc->sc_statep.s)) == NULL) {
|
||||
splx(s);
|
||||
(void *)&sc->sc_statep.s)) == NULL)
|
||||
return (ENOMEM);
|
||||
}
|
||||
h = mtod(sc->sc_mbuf, struct pfsync_header *);
|
||||
}
|
||||
}
|
||||
@ -1087,6 +1246,7 @@ pfsync_timeout(void *v)
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/* This must be called in splnet() */
|
||||
void
|
||||
pfsync_send_bus(struct pfsync_softc *sc, u_int8_t status)
|
||||
{
|
||||
@ -1102,7 +1262,7 @@ pfsync_send_bus(struct pfsync_softc *sc, u_int8_t status)
|
||||
bus = sc->sc_statep.b;
|
||||
bus->creatorid = pf_status.hostid;
|
||||
bus->status = status;
|
||||
bus->endtime = htonl(mono_time.tv_sec - sc->sc_ureq_received);
|
||||
bus->endtime = htonl(time_uptime - sc->sc_ureq_received);
|
||||
pfsync_sendout(sc);
|
||||
}
|
||||
}
|
||||
@ -1136,7 +1296,7 @@ pfsync_bulk_update(void *v)
|
||||
/* send an update and move to end of list */
|
||||
if (!state->sync_flags)
|
||||
pfsync_pack_state(PFSYNC_ACT_UPD, state, 0);
|
||||
state->pfsync_time = mono_time.tv_sec;
|
||||
state->pfsync_time = time_uptime;
|
||||
TAILQ_REMOVE(&state_updates, state, u.s.entry_updates);
|
||||
TAILQ_INSERT_TAIL(&state_updates, state,
|
||||
u.s.entry_updates);
|
||||
@ -1154,16 +1314,28 @@ void
|
||||
pfsync_bulkfail(void *v)
|
||||
{
|
||||
struct pfsync_softc *sc = v;
|
||||
int s, error;
|
||||
|
||||
if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) {
|
||||
/* Try again in a bit */
|
||||
timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
|
||||
pfsync_request_update(NULL, NULL);
|
||||
pfsync_sendout(sc);
|
||||
s = splnet();
|
||||
error = pfsync_request_update(NULL, NULL);
|
||||
if (error == ENOMEM) {
|
||||
if (pf_status.debug >= PF_DEBUG_MISC)
|
||||
printf("pfsync: cannot allocate mbufs for "
|
||||
"bulk update\n");
|
||||
} else
|
||||
pfsync_sendout(sc);
|
||||
splx(s);
|
||||
} else {
|
||||
/* Pretend like the transfer was ok */
|
||||
sc->sc_ureq_sent = 0;
|
||||
sc->sc_bulk_tries = 0;
|
||||
#if NCARP > 0
|
||||
if (!pfsync_sync_ok)
|
||||
carp_suppress_preempt--;
|
||||
#endif
|
||||
pfsync_sync_ok = 1;
|
||||
if (pf_status.debug >= PF_DEBUG_MISC)
|
||||
printf("pfsync: failed to receive "
|
||||
@ -1172,6 +1344,7 @@ pfsync_bulkfail(void *v)
|
||||
}
|
||||
}
|
||||
|
||||
/* This must be called in splnet() */
|
||||
int
|
||||
pfsync_sendout(sc)
|
||||
struct pfsync_softc *sc;
|
||||
@ -1199,9 +1372,8 @@ pfsync_sendout(sc)
|
||||
sc->sc_statep_net.s = NULL;
|
||||
}
|
||||
|
||||
if (sc->sc_sync_ifp) {
|
||||
if (sc->sc_sync_ifp || sc->sc_sync_peer.s_addr != INADDR_PFSYNC_GROUP) {
|
||||
struct ip *ip;
|
||||
struct ifaddr *ifa;
|
||||
struct sockaddr sa;
|
||||
|
||||
M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
|
||||
@ -1221,16 +1393,12 @@ pfsync_sendout(sc)
|
||||
ip->ip_sum = 0;
|
||||
|
||||
bzero(&sa, sizeof(sa));
|
||||
sa.sa_family = AF_INET;
|
||||
ifa = ifaof_ifpforaddr(&sa, sc->sc_sync_ifp);
|
||||
if (ifa == NULL)
|
||||
return (0);
|
||||
ip->ip_src.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr;
|
||||
ip->ip_src.s_addr = INADDR_ANY;
|
||||
|
||||
if (sc->sc_sendaddr.s_addr == INADDR_PFSYNC_GROUP)
|
||||
m->m_flags |= M_MCAST;
|
||||
ip->ip_dst = sc->sc_sendaddr;
|
||||
sc->sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP;
|
||||
sc->sc_sendaddr.s_addr = sc->sc_sync_peer.s_addr;
|
||||
|
||||
pfsyncstats.pfsyncs_opackets++;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: if_pfsync.h,v 1.13 2004/03/22 04:54:17 mcbride Exp $ */
|
||||
/* $OpenBSD: if_pfsync.h,v 1.19 2005/01/20 17:47:38 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Michael Shalayeff
|
||||
@ -85,6 +85,9 @@ struct pfsync_state {
|
||||
u_int8_t updates;
|
||||
} __packed;
|
||||
|
||||
#define PFSYNC_FLAG_COMPRESS 0x01
|
||||
#define PFSYNC_FLAG_STALE 0x02
|
||||
|
||||
struct pfsync_state_upd {
|
||||
u_int32_t id[2];
|
||||
struct pfsync_state_peer src;
|
||||
@ -150,9 +153,10 @@ struct pfsync_softc {
|
||||
struct timeout sc_tmo;
|
||||
struct timeout sc_bulk_tmo;
|
||||
struct timeout sc_bulkfail_tmo;
|
||||
struct in_addr sc_sync_peer;
|
||||
struct in_addr sc_sendaddr;
|
||||
struct mbuf *sc_mbuf; /* current cummulative mbuf */
|
||||
struct mbuf *sc_mbuf_net; /* current cummulative mbuf */
|
||||
struct mbuf *sc_mbuf; /* current cumulative mbuf */
|
||||
struct mbuf *sc_mbuf_net; /* current cumulative mbuf */
|
||||
union sc_statep sc_statep;
|
||||
union sc_statep sc_statep_net;
|
||||
u_int32_t sc_ureq_received;
|
||||
@ -184,7 +188,7 @@ struct pfsync_header {
|
||||
} __packed;
|
||||
|
||||
#define PFSYNC_BULKPACKETS 1 /* # of packets per timeout */
|
||||
#define PFSYNC_MAX_BULKTRIES 12
|
||||
#define PFSYNC_MAX_BULKTRIES 12
|
||||
#define PFSYNC_HDRLEN sizeof(struct pfsync_header)
|
||||
#define PFSYNC_ACTIONS \
|
||||
"CLR ST", "INS ST", "UPD ST", "DEL ST", \
|
||||
@ -194,33 +198,34 @@ struct pfsync_header {
|
||||
#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_int64_t pfsyncs_ipackets; /* total input packets, IPv4 */
|
||||
u_int64_t pfsyncs_ipackets6; /* total input packets, IPv6 */
|
||||
u_int64_t pfsyncs_badif; /* not the right interface */
|
||||
u_int64_t pfsyncs_badttl; /* TTL is not PFSYNC_DFLTTL */
|
||||
u_int64_t pfsyncs_hdrops; /* packets shorter than hdr */
|
||||
u_int64_t pfsyncs_badver; /* bad (incl unsupp) version */
|
||||
u_int64_t pfsyncs_badact; /* bad action */
|
||||
u_int64_t pfsyncs_badlen; /* data length does not match */
|
||||
u_int64_t pfsyncs_badauth; /* bad authentication */
|
||||
u_int64_t pfsyncs_stale; /* stale state */
|
||||
u_int64_t pfsyncs_badval; /* bad values */
|
||||
u_int64_t 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 */
|
||||
u_int64_t pfsyncs_opackets; /* total output packets, IPv4 */
|
||||
u_int64_t pfsyncs_opackets6; /* total output packets, IPv6 */
|
||||
u_int64_t pfsyncs_onomem; /* no memory for an mbuf */
|
||||
u_int64_t pfsyncs_oerrors; /* ip output error */
|
||||
};
|
||||
|
||||
/*
|
||||
* Configuration structure for SIOCSETPFSYNC SIOCGETPFSYNC
|
||||
*/
|
||||
struct pfsyncreq {
|
||||
char pfsyncr_syncif[IFNAMSIZ];
|
||||
int pfsyncr_maxupdates;
|
||||
int pfsyncr_authlevel;
|
||||
char pfsyncr_syncdev[IFNAMSIZ];
|
||||
struct in_addr pfsyncr_syncpeer;
|
||||
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 { \
|
||||
@ -267,12 +272,14 @@ int pfsync_pack_state(u_int8_t, struct pf_state *, int);
|
||||
} while (0)
|
||||
#define pfsync_update_state(st) do { \
|
||||
if (!st->sync_flags) \
|
||||
pfsync_pack_state(PFSYNC_ACT_UPD, (st), 1); \
|
||||
pfsync_pack_state(PFSYNC_ACT_UPD, (st), \
|
||||
PFSYNC_FLAG_COMPRESS); \
|
||||
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); \
|
||||
pfsync_pack_state(PFSYNC_ACT_DEL, (st), \
|
||||
PFSYNC_FLAG_COMPRESS); \
|
||||
st->sync_flags &= ~PFSTATE_FROMSYNC; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,4 @@
|
||||
/* $OpenBSD: pf_if.c,v 1.11 2004/03/15 11:38:23 cedric Exp $ */
|
||||
/* add $OpenBSD: pf_if.c,v 1.19 2004/08/11 12:06:44 henning Exp $ */
|
||||
/* $OpenBSD: pf_if.c,v 1.23 2004/12/22 17:17:55 dhartmei Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -43,7 +42,6 @@
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
@ -77,10 +75,6 @@ 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 *);
|
||||
@ -91,7 +85,6 @@ 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 *);
|
||||
@ -100,7 +93,6 @@ 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
|
||||
|
||||
@ -117,7 +109,6 @@ pfi_initialize(void)
|
||||
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
|
||||
@ -230,7 +221,12 @@ pfi_lookup_create(const char *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)
|
||||
if (q == NULL) {
|
||||
pfi_newgroup(key.pfik_name, PFI_IFLAG_DYNAMIC);
|
||||
q = pfi_lookup_if(key.pfik_name);
|
||||
}
|
||||
p = pfi_lookup_if(name);
|
||||
if (p == NULL && q != NULL)
|
||||
p = pfi_if_create(name, q, PFI_IFLAG_INSTANCE);
|
||||
}
|
||||
splx(s);
|
||||
@ -316,8 +312,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
|
||||
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);
|
||||
ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR);
|
||||
if (ruleset == NULL)
|
||||
senderr(1);
|
||||
|
||||
@ -354,11 +349,14 @@ 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;
|
||||
struct pfi_kif *kif;
|
||||
struct pfr_ktable *kt;
|
||||
|
||||
if (dyn == NULL || kif == NULL || kt == NULL)
|
||||
if (dyn == NULL || dyn->pfid_kif == NULL || dyn->pfid_kt == NULL)
|
||||
panic("pfi_dynaddr_update");
|
||||
|
||||
kif = dyn->pfid_kif;
|
||||
kt = dyn->pfid_kt;
|
||||
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);
|
||||
@ -412,8 +410,6 @@ pfi_instance_add(struct ifnet *ifp, int net, int flags)
|
||||
af = ia->ifa_addr->sa_family;
|
||||
if (af != AF_INET && af != AF_INET6)
|
||||
continue;
|
||||
if (!(ia->ifa_flags & IFA_ROUTE))
|
||||
continue;
|
||||
if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6)
|
||||
continue;
|
||||
if ((flags & PFI_AFLAG_BROADCAST) &&
|
||||
@ -434,14 +430,14 @@ pfi_instance_add(struct ifnet *ifp, int net, int flags)
|
||||
}
|
||||
if (af == AF_INET)
|
||||
got4 = 1;
|
||||
else
|
||||
else if (af == AF_INET6)
|
||||
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 {
|
||||
} else if (af == AF_INET6) {
|
||||
net2 = pfi_unmask(&((struct sockaddr_in6 *)
|
||||
ia->ifa_netmask)->sin6_addr);
|
||||
}
|
||||
@ -574,7 +570,7 @@ pfi_if_create(const char *name, struct pfi_kif *q, int flags)
|
||||
RB_INIT(&p->pfik_ext_gwy);
|
||||
p->pfik_flags = flags;
|
||||
p->pfik_parent = q;
|
||||
p->pfik_tzero = time.tv_sec;
|
||||
p->pfik_tzero = time_second;
|
||||
|
||||
RB_INSERT(pfi_ifhead, &pfi_ifs, p);
|
||||
if (q != NULL) {
|
||||
@ -628,46 +624,6 @@ pfi_copy_group(char *p, const char *q, int m)
|
||||
*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)
|
||||
{
|
||||
@ -714,10 +670,10 @@ pfi_clr_istats(const char *name, int *nzero, int flags)
|
||||
{
|
||||
struct pfi_kif *p;
|
||||
int n = 0, s;
|
||||
long tzero = time.tv_sec;
|
||||
long tzero = time_second;
|
||||
|
||||
s = splsoftnet();
|
||||
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;
|
||||
@ -732,6 +688,44 @@ pfi_clr_istats(const char *name, int *nzero, int flags)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfi_set_flags(const char *name, int flags)
|
||||
{
|
||||
struct pfi_kif *p;
|
||||
int s;
|
||||
|
||||
if (flags & ~PFI_IFLAG_SETABLE_MASK)
|
||||
return (EINVAL);
|
||||
|
||||
s = splsoftnet();
|
||||
RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
|
||||
if (pfi_skip_if(name, p, PFI_FLAG_GROUP|PFI_FLAG_INSTANCE))
|
||||
continue;
|
||||
p->pfik_flags |= flags;
|
||||
}
|
||||
splx(s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfi_clear_flags(const char *name, int flags)
|
||||
{
|
||||
struct pfi_kif *p;
|
||||
int s;
|
||||
|
||||
if (flags & ~PFI_IFLAG_SETABLE_MASK)
|
||||
return (EINVAL);
|
||||
|
||||
s = splsoftnet();
|
||||
RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
|
||||
if (pfi_skip_if(name, p, PFI_FLAG_GROUP|PFI_FLAG_INSTANCE))
|
||||
continue;
|
||||
p->pfik_flags &= ~flags;
|
||||
}
|
||||
splx(s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfi_get_ifaces(const char *name, struct pfi_if *buf, int *size, int flags)
|
||||
{
|
||||
@ -745,7 +739,7 @@ pfi_get_ifaces(const char *name, struct pfi_if *buf, int *size, int flags)
|
||||
continue;
|
||||
if (*size > n++) {
|
||||
if (!p->pfik_tzero)
|
||||
p->pfik_tzero = boottime.tv_sec;
|
||||
p->pfik_tzero = time_second;
|
||||
if (copyout(p, buf++, sizeof(*buf))) {
|
||||
splx(s);
|
||||
return (EFAULT);
|
||||
@ -820,7 +814,9 @@ pfi_dohooks(struct pfi_kif *p)
|
||||
int
|
||||
pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af)
|
||||
{
|
||||
if (af == AF_INET) {
|
||||
switch (af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
switch (dyn->pfid_acnt4) {
|
||||
case 0:
|
||||
return (0);
|
||||
@ -830,7 +826,10 @@ pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af)
|
||||
default:
|
||||
return (pfr_match_addr(dyn->pfid_kt, a, AF_INET));
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
switch (dyn->pfid_acnt6) {
|
||||
case 0:
|
||||
return (0);
|
||||
@ -840,5 +839,9 @@ pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af)
|
||||
default:
|
||||
return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6));
|
||||
}
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,4 @@
|
||||
/* $OpenBSD: pf_norm.c,v 1.80.2.1 2004/04/30 21:46:33 brad Exp $ */
|
||||
/* add $OpenBSD: pf_norm.c,v 1.87 2004/05/11 07:34:11 dhartmei Exp $ */
|
||||
/* $OpenBSD: pf_norm.c,v 1.97 2004/09/21 16:59:12 aaron Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
|
||||
@ -118,8 +117,12 @@ struct mbuf *pf_fragcache(struct mbuf **, struct ip*,
|
||||
int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *,
|
||||
struct tcphdr *, int);
|
||||
|
||||
#define DPFPRINTF(x) if (pf_status.debug >= PF_DEBUG_MISC) \
|
||||
{ printf("%s: ", __func__); printf x ;}
|
||||
#define DPFPRINTF(x) do { \
|
||||
if (pf_status.debug >= PF_DEBUG_MISC) { \
|
||||
printf("%s: ", __func__); \
|
||||
printf x ; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* Globals */
|
||||
struct pool pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
|
||||
@ -173,7 +176,7 @@ void
|
||||
pf_purge_expired_fragments(void)
|
||||
{
|
||||
struct pf_fragment *frag;
|
||||
u_int32_t expire = time.tv_sec -
|
||||
u_int32_t expire = time_second -
|
||||
pf_default_rule.timeout[PFTM_FRAG];
|
||||
|
||||
while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) {
|
||||
@ -284,7 +287,7 @@ pf_find_fragment(struct ip *ip, struct pf_frag_tree *tree)
|
||||
frag = RB_FIND(pf_frag_tree, tree, &key);
|
||||
if (frag != NULL) {
|
||||
/* XXX Are we sure we want to update the timeout? */
|
||||
frag->fr_timeout = time.tv_sec;
|
||||
frag->fr_timeout = time_second;
|
||||
if (BUFFER_FRAGMENTS(frag)) {
|
||||
TAILQ_REMOVE(&pf_fragqueue, frag, frag_next);
|
||||
TAILQ_INSERT_HEAD(&pf_fragqueue, frag, frag_next);
|
||||
@ -349,7 +352,7 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
|
||||
(*frag)->fr_dst = frent->fr_ip->ip_dst;
|
||||
(*frag)->fr_p = frent->fr_ip->ip_p;
|
||||
(*frag)->fr_id = frent->fr_ip->ip_id;
|
||||
(*frag)->fr_timeout = time.tv_sec;
|
||||
(*frag)->fr_timeout = time_second;
|
||||
LIST_INIT(&(*frag)->fr_queue);
|
||||
|
||||
RB_INSERT(pf_frag_tree, &pf_frag_tree, *frag);
|
||||
@ -551,7 +554,7 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
|
||||
(*frag)->fr_dst = h->ip_dst;
|
||||
(*frag)->fr_p = h->ip_p;
|
||||
(*frag)->fr_id = h->ip_id;
|
||||
(*frag)->fr_timeout = time.tv_sec;
|
||||
(*frag)->fr_timeout = time_second;
|
||||
|
||||
cur->fr_off = off;
|
||||
cur->fr_end = max;
|
||||
@ -810,7 +813,8 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
|
||||
}
|
||||
|
||||
int
|
||||
pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
|
||||
pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
|
||||
struct pf_pdesc *pd)
|
||||
{
|
||||
struct mbuf *m = *m0;
|
||||
struct pf_rule *r;
|
||||
@ -837,10 +841,10 @@ 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.not))
|
||||
(struct pf_addr *)&h->ip_src.s_addr, AF_INET, r->src.neg))
|
||||
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.not))
|
||||
(struct pf_addr *)&h->ip_dst.s_addr, AF_INET, r->dst.neg))
|
||||
r = r->skip[PF_SKIP_DST_ADDR].ptr;
|
||||
else
|
||||
break;
|
||||
@ -982,6 +986,8 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
|
||||
h->ip_id = ip_randomid();
|
||||
h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_id, h->ip_id, 0);
|
||||
}
|
||||
if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
|
||||
pd->flags |= PFDESC_IP_REAS;
|
||||
|
||||
return (PF_PASS);
|
||||
|
||||
@ -989,7 +995,8 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
|
||||
/* Enforce a minimum ttl, may cause endless packet loops */
|
||||
if (r->min_ttl && h->ip_ttl < r->min_ttl)
|
||||
h->ip_ttl = r->min_ttl;
|
||||
|
||||
if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
|
||||
pd->flags |= PFDESC_IP_REAS;
|
||||
return (PF_PASS);
|
||||
|
||||
no_mem:
|
||||
@ -1021,7 +1028,7 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason)
|
||||
#ifdef INET6
|
||||
int
|
||||
pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
|
||||
u_short *reason)
|
||||
u_short *reason, struct pf_pdesc *pd)
|
||||
{
|
||||
struct mbuf *m = *m0;
|
||||
struct pf_rule *r;
|
||||
@ -1053,10 +1060,10 @@ 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.not))
|
||||
(struct pf_addr *)&h->ip6_src, AF_INET6, r->src.neg))
|
||||
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.not))
|
||||
(struct pf_addr *)&h->ip6_dst, AF_INET6, r->dst.neg))
|
||||
r = r->skip[PF_SKIP_DST_ADDR].ptr;
|
||||
else
|
||||
break;
|
||||
@ -1171,6 +1178,7 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
|
||||
goto badfrag;
|
||||
|
||||
/* do something about it */
|
||||
/* remember to set pd->flags |= PFDESC_IP_REAS */
|
||||
return (PF_PASS);
|
||||
|
||||
shortpkt:
|
||||
@ -1191,7 +1199,7 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
|
||||
PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL);
|
||||
return (PF_DROP);
|
||||
}
|
||||
#endif
|
||||
#endif /* INET6 */
|
||||
|
||||
int
|
||||
pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
|
||||
@ -1216,12 +1224,12 @@ 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.not))
|
||||
else if (PF_MISMATCHAW(&r->src.addr, pd->src, af, r->src.neg))
|
||||
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.not))
|
||||
else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af, r->dst.neg))
|
||||
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))
|
||||
@ -1236,7 +1244,7 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
|
||||
}
|
||||
}
|
||||
|
||||
if (rm == NULL)
|
||||
if (rm == NULL || rm->action == PF_NOSCRUB)
|
||||
return (PF_PASS);
|
||||
else
|
||||
r->packets++;
|
||||
@ -1309,6 +1317,7 @@ int
|
||||
pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
struct tcphdr *th, struct pf_state_peer *src, struct pf_state_peer *dst)
|
||||
{
|
||||
u_int32_t tsval, tsecr;
|
||||
u_int8_t hdr[60];
|
||||
u_int8_t *opt;
|
||||
|
||||
@ -1362,7 +1371,18 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
if (opt[1] >= TCPOLEN_TIMESTAMP) {
|
||||
src->scrub->pfss_flags |=
|
||||
PFSS_TIMESTAMP;
|
||||
src->scrub->pfss_ts_mod = arc4random();
|
||||
src->scrub->pfss_ts_mod =
|
||||
htonl(arc4random());
|
||||
|
||||
/* note PFSS_PAWS not set yet */
|
||||
memcpy(&tsval, &opt[2],
|
||||
sizeof(u_int32_t));
|
||||
memcpy(&tsecr, &opt[6],
|
||||
sizeof(u_int32_t));
|
||||
src->scrub->pfss_tsval0 = ntohl(tsval);
|
||||
src->scrub->pfss_tsval = ntohl(tsval);
|
||||
src->scrub->pfss_tsecr = ntohl(tsecr);
|
||||
getmicrouptime(&src->scrub->pfss_last);
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
@ -1389,12 +1409,16 @@ pf_normalize_tcp_cleanup(struct pf_state *state)
|
||||
|
||||
int
|
||||
pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
u_short *reason, struct tcphdr *th, struct pf_state_peer *src,
|
||||
struct pf_state_peer *dst, int *writeback)
|
||||
u_short *reason, struct tcphdr *th, struct pf_state *state,
|
||||
struct pf_state_peer *src, struct pf_state_peer *dst, int *writeback)
|
||||
{
|
||||
struct timeval uptime;
|
||||
u_int32_t tsval, tsecr;
|
||||
u_int tsval_from_last;
|
||||
u_int8_t hdr[60];
|
||||
u_int8_t *opt;
|
||||
int copyback = 0;
|
||||
int got_ts = 0;
|
||||
|
||||
KASSERT(src->scrub || dst->scrub);
|
||||
|
||||
@ -1448,32 +1472,46 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
* NAT detection, OS uptime determination or
|
||||
* reboot detection.
|
||||
*/
|
||||
|
||||
if (got_ts) {
|
||||
/* Huh? Multiple timestamps!? */
|
||||
if (pf_status.debug >= PF_DEBUG_MISC) {
|
||||
DPFPRINTF(("multiple TS??"));
|
||||
pf_print_state(state);
|
||||
printf("\n");
|
||||
}
|
||||
REASON_SET(reason, PFRES_TS);
|
||||
return (PF_DROP);
|
||||
}
|
||||
if (opt[1] >= TCPOLEN_TIMESTAMP) {
|
||||
u_int32_t ts_value;
|
||||
if (src->scrub &&
|
||||
memcpy(&tsval, &opt[2],
|
||||
sizeof(u_int32_t));
|
||||
if (tsval && src->scrub &&
|
||||
(src->scrub->pfss_flags &
|
||||
PFSS_TIMESTAMP)) {
|
||||
memcpy(&ts_value, &opt[2],
|
||||
sizeof(u_int32_t));
|
||||
ts_value = htonl(ntohl(ts_value)
|
||||
+ src->scrub->pfss_ts_mod);
|
||||
tsval = ntohl(tsval);
|
||||
pf_change_a(&opt[2],
|
||||
&th->th_sum, ts_value, 0);
|
||||
&th->th_sum,
|
||||
htonl(tsval +
|
||||
src->scrub->pfss_ts_mod),
|
||||
0);
|
||||
copyback = 1;
|
||||
}
|
||||
|
||||
/* Modulate TS reply iff valid (!0) */
|
||||
memcpy(&ts_value, &opt[6],
|
||||
memcpy(&tsecr, &opt[6],
|
||||
sizeof(u_int32_t));
|
||||
if (ts_value && dst->scrub &&
|
||||
if (tsecr && dst->scrub &&
|
||||
(dst->scrub->pfss_flags &
|
||||
PFSS_TIMESTAMP)) {
|
||||
ts_value = htonl(ntohl(ts_value)
|
||||
- dst->scrub->pfss_ts_mod);
|
||||
tsecr = ntohl(tsecr)
|
||||
- dst->scrub->pfss_ts_mod;
|
||||
pf_change_a(&opt[6],
|
||||
&th->th_sum, ts_value, 0);
|
||||
&th->th_sum, htonl(tsecr),
|
||||
0);
|
||||
copyback = 1;
|
||||
}
|
||||
got_ts = 1;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
@ -1492,9 +1530,274 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Must invalidate PAWS checks on connections idle for too long.
|
||||
* The fastest allowed timestamp clock is 1ms. That turns out to
|
||||
* be about 24 days before it wraps. XXX Right now our lowerbound
|
||||
* TS echo check only works for the first 12 days of a connection
|
||||
* when the TS has exhausted half its 32bit space
|
||||
*/
|
||||
#define TS_MAX_IDLE (24*24*60*60)
|
||||
#define TS_MAX_CONN (12*24*60*60) /* XXX remove when better tsecr check */
|
||||
|
||||
getmicrouptime(&uptime);
|
||||
if (src->scrub && (src->scrub->pfss_flags & PFSS_PAWS) &&
|
||||
(uptime.tv_sec - src->scrub->pfss_last.tv_sec > TS_MAX_IDLE ||
|
||||
time_second - state->creation > TS_MAX_CONN)) {
|
||||
if (pf_status.debug >= PF_DEBUG_MISC) {
|
||||
DPFPRINTF(("src idled out of PAWS\n"));
|
||||
pf_print_state(state);
|
||||
printf("\n");
|
||||
}
|
||||
src->scrub->pfss_flags = (src->scrub->pfss_flags & ~PFSS_PAWS)
|
||||
| PFSS_PAWS_IDLED;
|
||||
}
|
||||
if (dst->scrub && (dst->scrub->pfss_flags & PFSS_PAWS) &&
|
||||
uptime.tv_sec - dst->scrub->pfss_last.tv_sec > TS_MAX_IDLE) {
|
||||
if (pf_status.debug >= PF_DEBUG_MISC) {
|
||||
DPFPRINTF(("dst idled out of PAWS\n"));
|
||||
pf_print_state(state);
|
||||
printf("\n");
|
||||
}
|
||||
dst->scrub->pfss_flags = (dst->scrub->pfss_flags & ~PFSS_PAWS)
|
||||
| PFSS_PAWS_IDLED;
|
||||
}
|
||||
|
||||
if (got_ts && src->scrub && dst->scrub &&
|
||||
(src->scrub->pfss_flags & PFSS_PAWS) &&
|
||||
(dst->scrub->pfss_flags & PFSS_PAWS)) {
|
||||
/* Validate that the timestamps are "in-window".
|
||||
* RFC1323 describes TCP Timestamp options that allow
|
||||
* measurement of RTT (round trip time) and PAWS
|
||||
* (protection against wrapped sequence numbers). PAWS
|
||||
* gives us a set of rules for rejecting packets on
|
||||
* long fat pipes (packets that were somehow delayed
|
||||
* in transit longer than the time it took to send the
|
||||
* full TCP sequence space of 4Gb). We can use these
|
||||
* rules and infer a few others that will let us treat
|
||||
* the 32bit timestamp and the 32bit echoed timestamp
|
||||
* as sequence numbers to prevent a blind attacker from
|
||||
* inserting packets into a connection.
|
||||
*
|
||||
* RFC1323 tells us:
|
||||
* - The timestamp on this packet must be greater than
|
||||
* or equal to the last value echoed by the other
|
||||
* endpoint. The RFC says those will be discarded
|
||||
* since it is a dup that has already been acked.
|
||||
* This gives us a lowerbound on the timestamp.
|
||||
* timestamp >= other last echoed timestamp
|
||||
* - The timestamp will be less than or equal to
|
||||
* the last timestamp plus the time between the
|
||||
* last packet and now. The RFC defines the max
|
||||
* clock rate as 1ms. We will allow clocks to be
|
||||
* up to 10% fast and will allow a total difference
|
||||
* or 30 seconds due to a route change. And this
|
||||
* gives us an upperbound on the timestamp.
|
||||
* timestamp <= last timestamp + max ticks
|
||||
* We have to be careful here. Windows will send an
|
||||
* initial timestamp of zero and then initialize it
|
||||
* to a random value after the 3whs; presumably to
|
||||
* avoid a DoS by having to call an expensive RNG
|
||||
* during a SYN flood. Proof MS has at least one
|
||||
* good security geek.
|
||||
*
|
||||
* - The TCP timestamp option must also echo the other
|
||||
* endpoints timestamp. The timestamp echoed is the
|
||||
* one carried on the earliest unacknowledged segment
|
||||
* on the left edge of the sequence window. The RFC
|
||||
* states that the host will reject any echoed
|
||||
* timestamps that were larger than any ever sent.
|
||||
* This gives us an upperbound on the TS echo.
|
||||
* tescr <= largest_tsval
|
||||
* - The lowerbound on the TS echo is a little more
|
||||
* tricky to determine. The other endpoint's echoed
|
||||
* values will not decrease. But there may be
|
||||
* network conditions that re-order packets and
|
||||
* cause our view of them to decrease. For now the
|
||||
* only lowerbound we can safely determine is that
|
||||
* the TS echo will never be less than the orginal
|
||||
* TS. XXX There is probably a better lowerbound.
|
||||
* Remove TS_MAX_CONN with better lowerbound check.
|
||||
* tescr >= other original TS
|
||||
*
|
||||
* It is also important to note that the fastest
|
||||
* timestamp clock of 1ms will wrap its 32bit space in
|
||||
* 24 days. So we just disable TS checking after 24
|
||||
* days of idle time. We actually must use a 12d
|
||||
* connection limit until we can come up with a better
|
||||
* lowerbound to the TS echo check.
|
||||
*/
|
||||
struct timeval delta_ts;
|
||||
int ts_fudge;
|
||||
|
||||
|
||||
/*
|
||||
* PFTM_TS_DIFF is how many seconds of leeway to allow
|
||||
* a host's timestamp. This can happen if the previous
|
||||
* packet got delayed in transit for much longer than
|
||||
* this packet.
|
||||
*/
|
||||
if ((ts_fudge = state->rule.ptr->timeout[PFTM_TS_DIFF]) == 0)
|
||||
ts_fudge = pf_default_rule.timeout[PFTM_TS_DIFF];
|
||||
|
||||
|
||||
/* Calculate max ticks since the last timestamp */
|
||||
#define TS_MAXFREQ 1100 /* RFC max TS freq of 1Khz + 10% skew */
|
||||
#define TS_MICROSECS 1000000 /* microseconds per second */
|
||||
timersub(&uptime, &src->scrub->pfss_last, &delta_ts);
|
||||
tsval_from_last = (delta_ts.tv_sec + ts_fudge) * TS_MAXFREQ;
|
||||
tsval_from_last += delta_ts.tv_usec / (TS_MICROSECS/TS_MAXFREQ);
|
||||
|
||||
|
||||
if ((src->state >= TCPS_ESTABLISHED &&
|
||||
dst->state >= TCPS_ESTABLISHED) &&
|
||||
(SEQ_LT(tsval, dst->scrub->pfss_tsecr) ||
|
||||
SEQ_GT(tsval, src->scrub->pfss_tsval + tsval_from_last) ||
|
||||
(tsecr && (SEQ_GT(tsecr, dst->scrub->pfss_tsval) ||
|
||||
SEQ_LT(tsecr, dst->scrub->pfss_tsval0))))) {
|
||||
/* Bad RFC1323 implementation or an insertion attack.
|
||||
*
|
||||
* - Solaris 2.6 and 2.7 are known to send another ACK
|
||||
* after the FIN,FIN|ACK,ACK closing that carries
|
||||
* an old timestamp.
|
||||
*/
|
||||
|
||||
DPFPRINTF(("Timestamp failed %c%c%c%c\n",
|
||||
SEQ_LT(tsval, dst->scrub->pfss_tsecr) ? '0' : ' ',
|
||||
SEQ_GT(tsval, src->scrub->pfss_tsval +
|
||||
tsval_from_last) ? '1' : ' ',
|
||||
SEQ_GT(tsecr, dst->scrub->pfss_tsval) ? '2' : ' ',
|
||||
SEQ_LT(tsecr, dst->scrub->pfss_tsval0)? '3' : ' '));
|
||||
DPFPRINTF((" tsval: %lu tsecr: %lu +ticks: %lu "
|
||||
"idle: %lus %lums\n",
|
||||
tsval, tsecr, tsval_from_last, delta_ts.tv_sec,
|
||||
delta_ts.tv_usec / 1000));
|
||||
DPFPRINTF((" src->tsval: %lu tsecr: %lu\n",
|
||||
src->scrub->pfss_tsval, src->scrub->pfss_tsecr));
|
||||
DPFPRINTF((" dst->tsval: %lu tsecr: %lu tsval0: %lu"
|
||||
"\n", dst->scrub->pfss_tsval,
|
||||
dst->scrub->pfss_tsecr, dst->scrub->pfss_tsval0));
|
||||
if (pf_status.debug >= PF_DEBUG_MISC) {
|
||||
pf_print_state(state);
|
||||
pf_print_flags(th->th_flags);
|
||||
printf("\n");
|
||||
}
|
||||
REASON_SET(reason, PFRES_TS);
|
||||
return (PF_DROP);
|
||||
}
|
||||
|
||||
/* XXX I'd really like to require tsecr but it's optional */
|
||||
|
||||
} else if (!got_ts && (th->th_flags & TH_RST) == 0 &&
|
||||
((src->state == TCPS_ESTABLISHED && dst->state == TCPS_ESTABLISHED)
|
||||
|| pd->p_len > 0 || (th->th_flags & TH_SYN)) &&
|
||||
src->scrub && dst->scrub &&
|
||||
(src->scrub->pfss_flags & PFSS_PAWS) &&
|
||||
(dst->scrub->pfss_flags & PFSS_PAWS)) {
|
||||
/* Didn't send a timestamp. Timestamps aren't really useful
|
||||
* when:
|
||||
* - connection opening or closing (often not even sent).
|
||||
* but we must not let an attacker to put a FIN on a
|
||||
* data packet to sneak it through our ESTABLISHED check.
|
||||
* - on a TCP reset. RFC suggests not even looking at TS.
|
||||
* - on an empty ACK. The TS will not be echoed so it will
|
||||
* probably not help keep the RTT calculation in sync and
|
||||
* there isn't as much danger when the sequence numbers
|
||||
* got wrapped. So some stacks don't include TS on empty
|
||||
* ACKs :-(
|
||||
*
|
||||
* To minimize the disruption to mostly RFC1323 conformant
|
||||
* stacks, we will only require timestamps on data packets.
|
||||
*
|
||||
* And what do ya know, we cannot require timestamps on data
|
||||
* packets. There appear to be devices that do legitimate
|
||||
* TCP connection hijacking. There are HTTP devices that allow
|
||||
* a 3whs (with timestamps) and then buffer the HTTP request.
|
||||
* If the intermediate device has the HTTP response cache, it
|
||||
* will spoof the response but not bother timestamping its
|
||||
* packets. So we can look for the presence of a timestamp in
|
||||
* the first data packet and if there, require it in all future
|
||||
* packets.
|
||||
*/
|
||||
|
||||
if (pd->p_len > 0 && (src->scrub->pfss_flags & PFSS_DATA_TS)) {
|
||||
/*
|
||||
* Hey! Someone tried to sneak a packet in. Or the
|
||||
* stack changed its RFC1323 behavior?!?!
|
||||
*/
|
||||
if (pf_status.debug >= PF_DEBUG_MISC) {
|
||||
DPFPRINTF(("Did not receive expected RFC1323 "
|
||||
"timestamp\n"));
|
||||
pf_print_state(state);
|
||||
pf_print_flags(th->th_flags);
|
||||
printf("\n");
|
||||
}
|
||||
REASON_SET(reason, PFRES_TS);
|
||||
return (PF_DROP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We will note if a host sends his data packets with or without
|
||||
* 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
|
||||
* packets (seen in a WWW accelerator or cache).
|
||||
*/
|
||||
if (pd->p_len > 0 && src->scrub && (src->scrub->pfss_flags &
|
||||
(PFSS_TIMESTAMP|PFSS_DATA_TS|PFSS_DATA_NOTS)) == PFSS_TIMESTAMP) {
|
||||
if (got_ts)
|
||||
src->scrub->pfss_flags |= PFSS_DATA_TS;
|
||||
else {
|
||||
src->scrub->pfss_flags |= PFSS_DATA_NOTS;
|
||||
if (pf_status.debug >= PF_DEBUG_MISC && dst->scrub &&
|
||||
(dst->scrub->pfss_flags & PFSS_TIMESTAMP)) {
|
||||
/* Don't warn if other host rejected RFC1323 */
|
||||
DPFPRINTF(("Broken RFC1323 stack did not "
|
||||
"timestamp data packet. Disabled PAWS "
|
||||
"security.\n"));
|
||||
pf_print_state(state);
|
||||
pf_print_flags(th->th_flags);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Update PAWS values
|
||||
*/
|
||||
if (got_ts && src->scrub && PFSS_TIMESTAMP == (src->scrub->pfss_flags &
|
||||
(PFSS_PAWS_IDLED|PFSS_TIMESTAMP))) {
|
||||
getmicrouptime(&src->scrub->pfss_last);
|
||||
if (SEQ_GEQ(tsval, src->scrub->pfss_tsval) ||
|
||||
(src->scrub->pfss_flags & PFSS_PAWS) == 0)
|
||||
src->scrub->pfss_tsval = tsval;
|
||||
|
||||
if (tsecr) {
|
||||
if (SEQ_GEQ(tsecr, src->scrub->pfss_tsecr) ||
|
||||
(src->scrub->pfss_flags & PFSS_PAWS) == 0)
|
||||
src->scrub->pfss_tsecr = tsecr;
|
||||
|
||||
if ((src->scrub->pfss_flags & PFSS_PAWS) == 0 &&
|
||||
(SEQ_LT(tsval, src->scrub->pfss_tsval0) ||
|
||||
src->scrub->pfss_tsval0 == 0)) {
|
||||
/* tsval0 MUST be the lowest timestamp */
|
||||
src->scrub->pfss_tsval0 = tsval;
|
||||
}
|
||||
|
||||
/* Only fully initialized after a TS gets echoed */
|
||||
if ((src->scrub->pfss_flags & PFSS_PAWS) == 0)
|
||||
src->scrub->pfss_flags |= PFSS_PAWS;
|
||||
}
|
||||
}
|
||||
|
||||
/* I have a dream.... TCP segment reassembly.... */
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th,
|
||||
int off)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pf_osfp.c,v 1.9 2004/01/04 20:08:42 pvalchev Exp $ */
|
||||
/* $OpenBSD: pf_osfp.c,v 1.10 2004/04/09 19:30:41 frantzen Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
|
||||
@ -233,9 +233,9 @@ void
|
||||
pf_osfp_initialize(void)
|
||||
{
|
||||
pool_init(&pf_osfp_entry_pl, sizeof(struct pf_osfp_entry), 0, 0, 0,
|
||||
"pfosfpen", NULL);
|
||||
"pfosfpen", &pool_allocator_nointr);
|
||||
pool_init(&pf_osfp_pl, sizeof(struct pf_os_fingerprint), 0, 0, 0,
|
||||
"pfosfp", NULL);
|
||||
"pfosfp", &pool_allocator_nointr);
|
||||
SLIST_INIT(&pf_osfp_list);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pf_table.c,v 1.47 2004/03/09 21:44:41 mcbride Exp $ */
|
||||
/* $OpenBSD: pf_table.c,v 1.62 2004/12/07 18:02:04 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Cedric Berger
|
||||
@ -125,6 +125,7 @@ struct pfr_walktree {
|
||||
|
||||
struct pool pfr_ktable_pl;
|
||||
struct pool pfr_kentry_pl;
|
||||
struct pool pfr_kentry_pl2;
|
||||
struct sockaddr_in pfr_sin;
|
||||
struct sockaddr_in6 pfr_sin6;
|
||||
union sockaddr_union pfr_mask;
|
||||
@ -138,7 +139,7 @@ void pfr_enqueue_addrs(struct pfr_ktable *,
|
||||
void pfr_mark_addrs(struct pfr_ktable *);
|
||||
struct pfr_kentry *pfr_lookup_addr(struct pfr_ktable *,
|
||||
struct pfr_addr *, int);
|
||||
struct pfr_kentry *pfr_create_kentry(struct pfr_addr *);
|
||||
struct pfr_kentry *pfr_create_kentry(struct pfr_addr *, int);
|
||||
void pfr_destroy_kentries(struct pfr_kentryworkq *);
|
||||
void pfr_destroy_kentry(struct pfr_kentry *);
|
||||
void pfr_insert_kentries(struct pfr_ktable *,
|
||||
@ -155,6 +156,7 @@ int pfr_unroute_kentry(struct pfr_ktable *,
|
||||
struct pfr_kentry *);
|
||||
int pfr_walktree(struct radix_node *, void *);
|
||||
int pfr_validate_table(struct pfr_table *, int, int);
|
||||
int pfr_fix_anchor(char *);
|
||||
void pfr_commit_ktable(struct pfr_ktable *, long);
|
||||
void pfr_insert_ktables(struct pfr_ktableworkq *);
|
||||
void pfr_insert_ktable(struct pfr_ktable *);
|
||||
@ -187,9 +189,11 @@ void
|
||||
pfr_initialize(void)
|
||||
{
|
||||
pool_init(&pfr_ktable_pl, sizeof(struct pfr_ktable), 0, 0, 0,
|
||||
"pfrktable", NULL);
|
||||
"pfrktable", &pool_allocator_oldnointr);
|
||||
pool_init(&pfr_kentry_pl, sizeof(struct pfr_kentry), 0, 0, 0,
|
||||
"pfrkentry", NULL);
|
||||
"pfrkentry", &pool_allocator_oldnointr);
|
||||
pool_init(&pfr_kentry_pl2, sizeof(struct pfr_kentry), 0, 0, 0,
|
||||
"pfrkentry2", NULL);
|
||||
|
||||
pfr_sin.sin_len = sizeof(pfr_sin);
|
||||
pfr_sin.sin_family = AF_INET;
|
||||
@ -240,7 +244,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
struct pfr_kentry *p, *q;
|
||||
struct pfr_addr ad;
|
||||
int i, rv, s, xadd = 0;
|
||||
long tzero = time.tv_sec;
|
||||
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))
|
||||
@ -272,7 +276,7 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
ad.pfra_fback = PFR_FB_NONE;
|
||||
}
|
||||
if (p == NULL && q == NULL) {
|
||||
p = pfr_create_kentry(&ad);
|
||||
p = pfr_create_kentry(&ad, 0);
|
||||
if (p == NULL)
|
||||
senderr(ENOMEM);
|
||||
if (pfr_route_kentry(tmpkt, p)) {
|
||||
@ -317,7 +321,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
struct pfr_kentryworkq workq;
|
||||
struct pfr_kentry *p;
|
||||
struct pfr_addr ad;
|
||||
int i, rv, s, xdel = 0;
|
||||
int i, rv, s, xdel = 0, log = 1;
|
||||
|
||||
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
|
||||
if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
|
||||
@ -327,7 +331,34 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
return (ESRCH);
|
||||
if (kt->pfrkt_flags & PFR_TFLAG_CONST)
|
||||
return (EPERM);
|
||||
pfr_mark_addrs(kt);
|
||||
/*
|
||||
* there are two algorithms to choose from here.
|
||||
* with:
|
||||
* n: number of addresses to delete
|
||||
* N: number of addresses in the table
|
||||
*
|
||||
* one is O(N) and is better for large 'n'
|
||||
* one is O(n*LOG(N)) and is better for small 'n'
|
||||
*
|
||||
* following code try to decide which one is best.
|
||||
*/
|
||||
for (i = kt->pfrkt_cnt; i > 0; i >>= 1)
|
||||
log++;
|
||||
if (size > kt->pfrkt_cnt/log) {
|
||||
/* full table scan */
|
||||
pfr_mark_addrs(kt);
|
||||
} else {
|
||||
/* iterate over addresses to delete */
|
||||
for (i = 0; i < size; i++) {
|
||||
if (COPYIN(addr+i, &ad, sizeof(ad)))
|
||||
return (EFAULT);
|
||||
if (pfr_validate_addr(&ad))
|
||||
return (EINVAL);
|
||||
p = pfr_lookup_addr(kt, &ad, 1);
|
||||
if (p != NULL)
|
||||
p->pfrke_mark = 0;
|
||||
}
|
||||
}
|
||||
SLIST_INIT(&workq);
|
||||
for (i = 0; i < size; i++) {
|
||||
if (COPYIN(addr+i, &ad, sizeof(ad)))
|
||||
@ -380,7 +411,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
struct pfr_kentry *p, *q;
|
||||
struct pfr_addr ad;
|
||||
int i, rv, s, xadd = 0, xdel = 0, xchange = 0;
|
||||
long tzero = time.tv_sec;
|
||||
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))
|
||||
@ -421,7 +452,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
ad.pfra_fback = PFR_FB_DUPLICATE;
|
||||
goto _skip;
|
||||
}
|
||||
p = pfr_create_kentry(&ad);
|
||||
p = pfr_create_kentry(&ad, 0);
|
||||
if (p == NULL)
|
||||
senderr(ENOMEM);
|
||||
if (pfr_route_kentry(tmpkt, p)) {
|
||||
@ -568,7 +599,7 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
|
||||
struct pfr_walktree w;
|
||||
struct pfr_kentryworkq workq;
|
||||
int rv, s;
|
||||
long tzero = time.tv_sec;
|
||||
long tzero = time_second;
|
||||
|
||||
ACCEPT_FLAGS(PFR_FLAG_ATOMIC); /* XXX PFR_FLAG_CLSTATS disabled */
|
||||
if (pfr_validate_table(tbl, 0, 0))
|
||||
@ -666,14 +697,18 @@ pfr_validate_addr(struct pfr_addr *ad)
|
||||
int i;
|
||||
|
||||
switch (ad->pfra_af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (ad->pfra_net > 32)
|
||||
return (-1);
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (ad->pfra_net > 128)
|
||||
return (-1);
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
@ -736,7 +771,7 @@ pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact)
|
||||
if (ad->pfra_af == AF_INET) {
|
||||
FILLIN_SIN(sa.sin, ad->pfra_ip4addr);
|
||||
head = kt->pfrkt_ip4;
|
||||
} else {
|
||||
} else if ( ad->pfra_af == AF_INET6 ) {
|
||||
FILLIN_SIN6(sa.sin6, ad->pfra_ip6addr);
|
||||
head = kt->pfrkt_ip6;
|
||||
}
|
||||
@ -758,22 +793,26 @@ pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact)
|
||||
}
|
||||
|
||||
struct pfr_kentry *
|
||||
pfr_create_kentry(struct pfr_addr *ad)
|
||||
pfr_create_kentry(struct pfr_addr *ad, int intr)
|
||||
{
|
||||
struct pfr_kentry *ke;
|
||||
|
||||
ke = pool_get(&pfr_kentry_pl, PR_NOWAIT);
|
||||
if (intr)
|
||||
ke = pool_get(&pfr_kentry_pl2, PR_NOWAIT);
|
||||
else
|
||||
ke = pool_get(&pfr_kentry_pl, PR_NOWAIT);
|
||||
if (ke == NULL)
|
||||
return (NULL);
|
||||
bzero(ke, sizeof(*ke));
|
||||
|
||||
if (ad->pfra_af == AF_INET)
|
||||
FILLIN_SIN(ke->pfrke_sa.sin, ad->pfra_ip4addr);
|
||||
else
|
||||
else if (ad->pfra_af == AF_INET6)
|
||||
FILLIN_SIN6(ke->pfrke_sa.sin6, ad->pfra_ip6addr);
|
||||
ke->pfrke_af = ad->pfra_af;
|
||||
ke->pfrke_net = ad->pfra_net;
|
||||
ke->pfrke_not = ad->pfra_not;
|
||||
ke->pfrke_intrpool = intr;
|
||||
return (ke);
|
||||
}
|
||||
|
||||
@ -791,7 +830,10 @@ pfr_destroy_kentries(struct pfr_kentryworkq *workq)
|
||||
void
|
||||
pfr_destroy_kentry(struct pfr_kentry *ke)
|
||||
{
|
||||
pool_put(&pfr_kentry_pl, ke);
|
||||
if (ke->pfrke_intrpool)
|
||||
pool_put(&pfr_kentry_pl2, ke);
|
||||
else
|
||||
pool_put(&pfr_kentry_pl, ke);
|
||||
}
|
||||
|
||||
void
|
||||
@ -814,6 +856,29 @@ pfr_insert_kentries(struct pfr_ktable *kt,
|
||||
kt->pfrkt_cnt += n;
|
||||
}
|
||||
|
||||
int
|
||||
pfr_insert_kentry(struct pfr_ktable *kt, struct pfr_addr *ad, long tzero)
|
||||
{
|
||||
struct pfr_kentry *p;
|
||||
int rv;
|
||||
|
||||
p = pfr_lookup_addr(kt, ad, 1);
|
||||
if (p != NULL)
|
||||
return (0);
|
||||
p = pfr_create_kentry(ad, 1);
|
||||
if (p == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
rv = pfr_route_kentry(kt, p);
|
||||
if (rv)
|
||||
return (rv);
|
||||
|
||||
p->pfrke_tzero = tzero;
|
||||
kt->pfrkt_cnt++;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
pfr_remove_kentries(struct pfr_ktable *kt,
|
||||
struct pfr_kentryworkq *workq)
|
||||
@ -880,14 +945,14 @@ pfr_prepare_network(union sockaddr_union *sa, int af, int net)
|
||||
if (af == AF_INET) {
|
||||
sa->sin.sin_len = sizeof(sa->sin);
|
||||
sa->sin.sin_family = AF_INET;
|
||||
sa->sin.sin_addr.s_addr = htonl(-1 << (32-net));
|
||||
} else {
|
||||
sa->sin.sin_addr.s_addr = net ? htonl(-1 << (32-net)) : 0;
|
||||
} else if (af == AF_INET6) {
|
||||
sa->sin6.sin6_len = sizeof(sa->sin6);
|
||||
sa->sin6.sin6_family = AF_INET6;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (net <= 32) {
|
||||
sa->sin6.sin6_addr.s6_addr32[i] =
|
||||
htonl(-1 << (32-net));
|
||||
net ? htonl(-1 << (32-net)) : 0;
|
||||
break;
|
||||
}
|
||||
sa->sin6.sin6_addr.s6_addr32[i] = 0xFFFFFFFF;
|
||||
@ -907,7 +972,7 @@ pfr_route_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
|
||||
bzero(ke->pfrke_node, sizeof(ke->pfrke_node));
|
||||
if (ke->pfrke_af == AF_INET)
|
||||
head = kt->pfrkt_ip4;
|
||||
else
|
||||
else if (ke->pfrke_af == AF_INET6)
|
||||
head = kt->pfrkt_ip6;
|
||||
|
||||
s = splsoftnet();
|
||||
@ -931,15 +996,15 @@ pfr_unroute_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
|
||||
|
||||
if (ke->pfrke_af == AF_INET)
|
||||
head = kt->pfrkt_ip4;
|
||||
else
|
||||
else if (ke->pfrke_af == AF_INET6)
|
||||
head = kt->pfrkt_ip6;
|
||||
|
||||
s = splsoftnet();
|
||||
if (KENTRY_NETWORK(ke)) {
|
||||
pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net);
|
||||
rn = rn_delete(&ke->pfrke_sa, &mask, head);
|
||||
rn = rn_delete(&ke->pfrke_sa, &mask, head, NULL);
|
||||
} else
|
||||
rn = rn_delete(&ke->pfrke_sa, NULL, head);
|
||||
rn = rn_delete(&ke->pfrke_sa, NULL, head, NULL);
|
||||
splx(s);
|
||||
|
||||
if (rn == NULL) {
|
||||
@ -960,7 +1025,7 @@ pfr_copyout_addr(struct pfr_addr *ad, struct pfr_kentry *ke)
|
||||
ad->pfra_not = ke->pfrke_not;
|
||||
if (ad->pfra_af == AF_INET)
|
||||
ad->pfra_ip4addr = ke->pfrke_sa.sin.sin_addr;
|
||||
else
|
||||
else if (ad->pfra_af == AF_INET6)
|
||||
ad->pfra_ip6addr = ke->pfrke_sa.sin6.sin6_addr;
|
||||
}
|
||||
|
||||
@ -1029,7 +1094,7 @@ pfr_walktree(struct radix_node *rn, void *arg)
|
||||
&ke->pfrke_sa, AF_INET);
|
||||
w->pfrw_dyn->pfid_mask4 = *SUNION2PF(
|
||||
&pfr_mask, AF_INET);
|
||||
} else {
|
||||
} else if (ke->pfrke_af == AF_INET6){
|
||||
if (w->pfrw_dyn->pfid_acnt6++ > 0)
|
||||
break;
|
||||
pfr_prepare_network(&pfr_mask, AF_INET6, ke->pfrke_net);
|
||||
@ -1051,6 +1116,8 @@ pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
|
||||
int s, xdel = 0;
|
||||
|
||||
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ALLRSETS);
|
||||
if (pfr_fix_anchor(filter->pfrt_anchor))
|
||||
return (EINVAL);
|
||||
if (pfr_table_count(filter, flags) < 0)
|
||||
return (ENOENT);
|
||||
|
||||
@ -1084,7 +1151,7 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
|
||||
struct pfr_ktableworkq addq, changeq;
|
||||
struct pfr_ktable *p, *q, *r, key;
|
||||
int i, rv, s, xadd = 0;
|
||||
long tzero = time.tv_sec;
|
||||
long tzero = time_second;
|
||||
|
||||
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
|
||||
SLIST_INIT(&addq);
|
||||
@ -1112,7 +1179,6 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
|
||||
|
||||
/* find or create root table */
|
||||
bzero(key.pfrkt_anchor, sizeof(key.pfrkt_anchor));
|
||||
bzero(key.pfrkt_ruleset, sizeof(key.pfrkt_ruleset));
|
||||
r = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
|
||||
if (r != NULL) {
|
||||
p->pfrkt_root = r;
|
||||
@ -1207,6 +1273,8 @@ pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
|
||||
int n, nn;
|
||||
|
||||
ACCEPT_FLAGS(PFR_FLAG_ALLRSETS);
|
||||
if (pfr_fix_anchor(filter->pfrt_anchor))
|
||||
return (EINVAL);
|
||||
n = nn = pfr_table_count(filter, flags);
|
||||
if (n < 0)
|
||||
return (ENOENT);
|
||||
@ -1237,10 +1305,12 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
|
||||
struct pfr_ktable *p;
|
||||
struct pfr_ktableworkq workq;
|
||||
int s, n, nn;
|
||||
long tzero = time.tv_sec;
|
||||
long tzero = time_second;
|
||||
|
||||
ACCEPT_FLAGS(PFR_FLAG_ATOMIC|PFR_FLAG_ALLRSETS);
|
||||
/* XXX PFR_FLAG_CLSTATS disabled */
|
||||
if (pfr_fix_anchor(filter->pfrt_anchor))
|
||||
return (EINVAL);
|
||||
n = nn = pfr_table_count(filter, flags);
|
||||
if (n < 0)
|
||||
return (ENOENT);
|
||||
@ -1285,7 +1355,7 @@ pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
|
||||
struct pfr_ktableworkq workq;
|
||||
struct pfr_ktable *p, key;
|
||||
int i, s, xzero = 0;
|
||||
long tzero = time.tv_sec;
|
||||
long tzero = time_second;
|
||||
|
||||
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ADDRSTOO);
|
||||
SLIST_INIT(&workq);
|
||||
@ -1375,7 +1445,7 @@ pfr_ina_begin(struct pfr_table *trs, u_int32_t *ticket, int *ndel, int flags)
|
||||
int xdel = 0;
|
||||
|
||||
ACCEPT_FLAGS(PFR_FLAG_DUMMY);
|
||||
rs = pf_find_or_create_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
|
||||
rs = pf_find_or_create_ruleset(trs->pfrt_anchor);
|
||||
if (rs == NULL)
|
||||
return (ENOMEM);
|
||||
SLIST_INIT(&workq);
|
||||
@ -1417,7 +1487,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK,
|
||||
flags & PFR_FLAG_USERIOCTL))
|
||||
return (EINVAL);
|
||||
rs = pf_find_ruleset(tbl->pfrt_anchor, tbl->pfrt_ruleset);
|
||||
rs = pf_find_ruleset(tbl->pfrt_anchor);
|
||||
if (rs == NULL || !rs->topen || ticket != rs->tticket)
|
||||
return (EBUSY);
|
||||
tbl->pfrt_flags |= PFR_TFLAG_INACTIVE;
|
||||
@ -1463,7 +1533,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
|
||||
senderr(EINVAL);
|
||||
if (pfr_lookup_addr(shadow, &ad, 1) != NULL)
|
||||
continue;
|
||||
p = pfr_create_kentry(&ad);
|
||||
p = pfr_create_kentry(&ad, 0);
|
||||
if (p == NULL)
|
||||
senderr(ENOMEM);
|
||||
if (pfr_route_kentry(shadow, p)) {
|
||||
@ -1508,7 +1578,7 @@ pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
|
||||
int xdel = 0;
|
||||
|
||||
ACCEPT_FLAGS(PFR_FLAG_DUMMY);
|
||||
rs = pf_find_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
|
||||
rs = pf_find_ruleset(trs->pfrt_anchor);
|
||||
if (rs == NULL || !rs->topen || ticket != rs->tticket)
|
||||
return (0);
|
||||
SLIST_INIT(&workq);
|
||||
@ -1534,14 +1604,14 @@ int
|
||||
pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
|
||||
int *nchange, int flags)
|
||||
{
|
||||
struct pfr_ktable *p;
|
||||
struct pfr_ktable *p, *q;
|
||||
struct pfr_ktableworkq workq;
|
||||
struct pf_ruleset *rs;
|
||||
int s, xadd = 0, xchange = 0;
|
||||
long tzero = time.tv_sec;
|
||||
long tzero = time_second;
|
||||
|
||||
ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
|
||||
rs = pf_find_ruleset(trs->pfrt_anchor, trs->pfrt_ruleset);
|
||||
rs = pf_find_ruleset(trs->pfrt_anchor);
|
||||
if (rs == NULL || !rs->topen || ticket != rs->tticket)
|
||||
return (EBUSY);
|
||||
|
||||
@ -1560,8 +1630,10 @@ pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
|
||||
if (!(flags & PFR_FLAG_DUMMY)) {
|
||||
if (flags & PFR_FLAG_ATOMIC)
|
||||
s = splsoftnet();
|
||||
SLIST_FOREACH(p, &workq, pfrkt_workq)
|
||||
for (p = SLIST_FIRST(&workq); p != NULL; p = q) {
|
||||
q = SLIST_NEXT(p, pfrkt_workq);
|
||||
pfr_commit_ktable(p, tzero);
|
||||
}
|
||||
if (flags & PFR_FLAG_ATOMIC)
|
||||
splx(s);
|
||||
rs->topen = 0;
|
||||
@ -1648,27 +1720,52 @@ pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved)
|
||||
for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++)
|
||||
if (tbl->pfrt_name[i])
|
||||
return (-1);
|
||||
if (pfr_fix_anchor(tbl->pfrt_anchor))
|
||||
return (-1);
|
||||
if (tbl->pfrt_flags & ~allowedflags)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Rewrite anchors referenced by tables to remove slashes
|
||||
* and check for validity.
|
||||
*/
|
||||
int
|
||||
pfr_fix_anchor(char *anchor)
|
||||
{
|
||||
size_t siz = MAXPATHLEN;
|
||||
int i;
|
||||
|
||||
if (anchor[0] == '/') {
|
||||
char *path;
|
||||
int off;
|
||||
|
||||
path = anchor;
|
||||
off = 1;
|
||||
while (*++path == '/')
|
||||
off++;
|
||||
bcopy(path, anchor, siz - off);
|
||||
memset(anchor + siz - off, 0, off);
|
||||
}
|
||||
if (anchor[siz - 1])
|
||||
return (-1);
|
||||
for (i = strlen(anchor); i < siz; i++)
|
||||
if (anchor[i])
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pfr_table_count(struct pfr_table *filter, int flags)
|
||||
{
|
||||
struct pf_ruleset *rs;
|
||||
struct pf_anchor *ac;
|
||||
|
||||
if (flags & PFR_FLAG_ALLRSETS)
|
||||
return (pfr_ktable_cnt);
|
||||
if (filter->pfrt_ruleset[0]) {
|
||||
rs = pf_find_ruleset(filter->pfrt_anchor,
|
||||
filter->pfrt_ruleset);
|
||||
return ((rs != NULL) ? rs->tables : -1);
|
||||
}
|
||||
if (filter->pfrt_anchor[0]) {
|
||||
ac = pf_find_anchor(filter->pfrt_anchor);
|
||||
return ((ac != NULL) ? ac->tables : -1);
|
||||
rs = pf_find_ruleset(filter->pfrt_anchor);
|
||||
return ((rs != NULL) ? rs->tables : -1);
|
||||
}
|
||||
return (pf_main_ruleset.tables);
|
||||
}
|
||||
@ -1678,13 +1775,7 @@ pfr_skip_table(struct pfr_table *filter, struct pfr_ktable *kt, int flags)
|
||||
{
|
||||
if (flags & PFR_FLAG_ALLRSETS)
|
||||
return (0);
|
||||
if (strncmp(filter->pfrt_anchor, kt->pfrkt_anchor,
|
||||
PF_ANCHOR_NAME_SIZE))
|
||||
return (1);
|
||||
if (!filter->pfrt_ruleset[0])
|
||||
return (0);
|
||||
if (strncmp(filter->pfrt_ruleset, kt->pfrkt_ruleset,
|
||||
PF_RULESET_NAME_SIZE))
|
||||
if (strcmp(filter->pfrt_anchor, kt->pfrkt_anchor))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
@ -1712,10 +1803,12 @@ pfr_insert_ktable(struct pfr_ktable *kt)
|
||||
void
|
||||
pfr_setflags_ktables(struct pfr_ktableworkq *workq)
|
||||
{
|
||||
struct pfr_ktable *p;
|
||||
struct pfr_ktable *p, *q;
|
||||
|
||||
SLIST_FOREACH(p, workq, pfrkt_workq)
|
||||
for (p = SLIST_FIRST(workq); p; p = q) {
|
||||
q = SLIST_NEXT(p, pfrkt_workq);
|
||||
pfr_setflags_ktable(p, p->pfrkt_nflags);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1790,16 +1883,13 @@ pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset)
|
||||
kt->pfrkt_t = *tbl;
|
||||
|
||||
if (attachruleset) {
|
||||
rs = pf_find_or_create_ruleset(tbl->pfrt_anchor,
|
||||
tbl->pfrt_ruleset);
|
||||
rs = pf_find_or_create_ruleset(tbl->pfrt_anchor);
|
||||
if (!rs) {
|
||||
pfr_destroy_ktable(kt, 0);
|
||||
return (NULL);
|
||||
}
|
||||
kt->pfrkt_rs = rs;
|
||||
rs->tables++;
|
||||
if (rs->anchor != NULL)
|
||||
rs->anchor->tables++;
|
||||
}
|
||||
|
||||
if (!rn_inithead((void **)&kt->pfrkt_ip4,
|
||||
@ -1843,8 +1933,6 @@ pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr)
|
||||
pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr);
|
||||
if (kt->pfrkt_rs != NULL) {
|
||||
kt->pfrkt_rs->tables--;
|
||||
if (kt->pfrkt_rs->anchor != NULL)
|
||||
kt->pfrkt_rs->anchor->tables--;
|
||||
pf_remove_if_empty_ruleset(kt->pfrkt_rs);
|
||||
}
|
||||
pool_put(&pfr_ktable_pl, kt);
|
||||
@ -1857,11 +1945,7 @@ pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q)
|
||||
|
||||
if ((d = strncmp(p->pfrkt_name, q->pfrkt_name, PF_TABLE_NAME_SIZE)))
|
||||
return (d);
|
||||
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 (strcmp(p->pfrkt_anchor, q->pfrkt_anchor));
|
||||
}
|
||||
|
||||
struct pfr_ktable *
|
||||
@ -1884,18 +1968,22 @@ pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
|
||||
return (0);
|
||||
|
||||
switch (af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
pfr_sin.sin_addr.s_addr = a->addr32[0];
|
||||
ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4);
|
||||
if (ke && KENTRY_RNF_ROOT(ke))
|
||||
ke = NULL;
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr));
|
||||
ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6);
|
||||
if (ke && KENTRY_RNF_ROOT(ke))
|
||||
ke = NULL;
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
}
|
||||
match = (ke && !ke->pfrke_not);
|
||||
if (match)
|
||||
@ -1917,18 +2005,24 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,
|
||||
return;
|
||||
|
||||
switch (af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
pfr_sin.sin_addr.s_addr = a->addr32[0];
|
||||
ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4);
|
||||
if (ke && KENTRY_RNF_ROOT(ke))
|
||||
ke = NULL;
|
||||
break;
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr));
|
||||
ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6);
|
||||
if (ke && KENTRY_RNF_ROOT(ke))
|
||||
ke = NULL;
|
||||
break;
|
||||
#endif /* INET6 */
|
||||
default:
|
||||
;
|
||||
}
|
||||
if ((ke == NULL || ke->pfrke_not) != notrule) {
|
||||
if (op_pass != PFR_OP_PASS)
|
||||
@ -1952,18 +2046,15 @@ 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) {
|
||||
if (ac != NULL)
|
||||
strlcpy(tbl.pfrt_anchor, ac->name, sizeof(tbl.pfrt_anchor));
|
||||
strlcpy(tbl.pfrt_ruleset, rs->name, sizeof(tbl.pfrt_ruleset));
|
||||
}
|
||||
kt = pfr_lookup_table(&tbl);
|
||||
if (kt == NULL) {
|
||||
kt = pfr_create_ktable(&tbl, time.tv_sec, 1);
|
||||
kt = pfr_create_ktable(&tbl, time_second, 1);
|
||||
if (kt == NULL)
|
||||
return (NULL);
|
||||
if (ac != NULL) {
|
||||
bzero(tbl.pfrt_anchor, sizeof(tbl.pfrt_anchor));
|
||||
bzero(tbl.pfrt_ruleset, sizeof(tbl.pfrt_ruleset));
|
||||
rt = pfr_lookup_table(&tbl);
|
||||
if (rt == NULL) {
|
||||
rt = pfr_create_ktable(&tbl, 0, 1);
|
||||
@ -2001,8 +2092,10 @@ pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter,
|
||||
union sockaddr_union mask;
|
||||
int idx = -1, use_counter = 0;
|
||||
|
||||
addr = (af == AF_INET) ? (struct pf_addr *)&pfr_sin.sin_addr :
|
||||
(struct pf_addr *)&pfr_sin6.sin6_addr;
|
||||
if (af == AF_INET)
|
||||
addr = (struct pf_addr *)&pfr_sin.sin_addr;
|
||||
else if (af == AF_INET6)
|
||||
addr = (struct pf_addr *)&pfr_sin6.sin6_addr;
|
||||
if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
|
||||
kt = kt->pfrkt_root;
|
||||
if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
|
||||
@ -2045,9 +2138,12 @@ 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 ?
|
||||
rn_match(&pfr_sin, kt->pfrkt_ip4) :
|
||||
rn_match(&pfr_sin6, kt->pfrkt_ip6));
|
||||
if (af == AF_INET)
|
||||
ke2 = (struct pfr_kentry *)rn_match(&pfr_sin,
|
||||
kt->pfrkt_ip4);
|
||||
else if (af == AF_INET6)
|
||||
ke2 = (struct pfr_kentry *)rn_match(&pfr_sin6,
|
||||
kt->pfrkt_ip6);
|
||||
/* no need to check KENTRY_RNF_ROOT() here */
|
||||
if (ke2 == ke) {
|
||||
/* lookup return the same block - perfect */
|
||||
@ -2080,12 +2176,16 @@ pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
|
||||
w.pfrw_cnt = idx;
|
||||
|
||||
switch (af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
|
||||
return (w.pfrw_kentry);
|
||||
#endif /* INET */
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
|
||||
return (w.pfrw_kentry);
|
||||
#endif /* INET6 */
|
||||
default:
|
||||
return (NULL);
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
/* $OpenBSD: pfvar.h,v 1.187 2004/03/22 04:54:18 mcbride Exp $ */
|
||||
/* add $OpenBSD: pfvar.h,v 1.194 2004/05/11 07:34:11 dhartmei Exp $ */
|
||||
/* $OpenBSD: pfvar.h,v 1.213 2005/03/03 07:13:39 dhartmei Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -34,11 +33,13 @@
|
||||
#ifndef _NET_PFVAR_H_
|
||||
#define _NET_PFVAR_H_
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/tree.h>
|
||||
|
||||
#include <net/radix.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/ip_ipsp.h>
|
||||
#include <netinet/tcp_fsm.h>
|
||||
|
||||
@ -49,7 +50,7 @@ struct ip;
|
||||
|
||||
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,
|
||||
enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, 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,
|
||||
PF_RULESET_BINAT, PF_RULESET_RDR, PF_RULESET_MAX };
|
||||
@ -70,14 +71,35 @@ 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_MAX, PFTM_PURGE, PFTM_UNTIL_PACKET };
|
||||
PFTM_TS_DIFF, PFTM_MAX, PFTM_PURGE, PFTM_UNTIL_PACKET };
|
||||
|
||||
/* PFTM default values */
|
||||
#define PFTM_TCP_FIRST_PACKET_VAL 120 /* First TCP packet */
|
||||
#define PFTM_TCP_OPENING_VAL 30 /* No response yet */
|
||||
#define PFTM_TCP_ESTABLISHED_VAL 24*60*60/* Established */
|
||||
#define PFTM_TCP_CLOSING_VAL 15 * 60 /* Half closed */
|
||||
#define PFTM_TCP_FIN_WAIT_VAL 45 /* Got both FINs */
|
||||
#define PFTM_TCP_CLOSED_VAL 90 /* Got a RST */
|
||||
#define PFTM_UDP_FIRST_PACKET_VAL 60 /* First UDP packet */
|
||||
#define PFTM_UDP_SINGLE_VAL 30 /* Unidirectional */
|
||||
#define PFTM_UDP_MULTIPLE_VAL 60 /* Bidirectional */
|
||||
#define PFTM_ICMP_FIRST_PACKET_VAL 20 /* First ICMP packet */
|
||||
#define PFTM_ICMP_ERROR_REPLY_VAL 10 /* Got error response */
|
||||
#define PFTM_OTHER_FIRST_PACKET_VAL 60 /* First packet */
|
||||
#define PFTM_OTHER_SINGLE_VAL 30 /* Unidirectional */
|
||||
#define PFTM_OTHER_MULTIPLE_VAL 60 /* Bidirectional */
|
||||
#define PFTM_FRAG_VAL 30 /* Fragment expire */
|
||||
#define PFTM_INTERVAL_VAL 10 /* Expire interval */
|
||||
#define PFTM_SRC_NODE_VAL 0 /* Source tracking */
|
||||
#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 };
|
||||
#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_TABLE, PF_ADDR_RTLABEL };
|
||||
#define PF_POOL_TYPEMASK 0x0f
|
||||
#define PF_POOL_STICKYADDR 0x20
|
||||
#define PF_WSCALE_FLAG 0x80
|
||||
@ -114,6 +136,8 @@ struct pf_addr_wrap {
|
||||
} a;
|
||||
char ifname[IFNAMSIZ];
|
||||
char tblname[PF_TABLE_NAME_SIZE];
|
||||
char rtlabelname[RTLABEL_LEN];
|
||||
u_int32_t rtlabel;
|
||||
} v;
|
||||
union {
|
||||
struct pfi_dynaddr *dyn;
|
||||
@ -275,10 +299,12 @@ struct pfi_dynaddr {
|
||||
#endif /* PF_INET6_ONLY */
|
||||
#endif /* PF_INET_INET6 */
|
||||
|
||||
#define PF_MISMATCHAW(aw, x, af, not) \
|
||||
#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 && \
|
||||
@ -287,7 +313,7 @@ struct pfi_dynaddr {
|
||||
!PF_AZERO(&(aw)->v.a.mask, (af)) && \
|
||||
!PF_MATCHA(0, &(aw)->v.a.addr, \
|
||||
&(aw)->v.a.mask, (x), (af)))) != \
|
||||
(not) \
|
||||
(neg) \
|
||||
)
|
||||
|
||||
struct pf_rule_uid {
|
||||
@ -303,7 +329,7 @@ struct pf_rule_gid {
|
||||
struct pf_rule_addr {
|
||||
struct pf_addr_wrap addr;
|
||||
u_int16_t port[2];
|
||||
u_int8_t not;
|
||||
u_int8_t neg;
|
||||
u_int8_t port_op;
|
||||
};
|
||||
|
||||
@ -445,6 +471,8 @@ union pf_rule_ptr {
|
||||
u_int32_t nr;
|
||||
};
|
||||
|
||||
#define PF_ANCHOR_NAME_SIZE 64
|
||||
|
||||
struct pf_rule {
|
||||
struct pf_rule_addr src;
|
||||
struct pf_rule_addr dst;
|
||||
@ -464,12 +492,12 @@ struct pf_rule {
|
||||
char ifname[IFNAMSIZ];
|
||||
char qname[PF_QNAME_SIZE];
|
||||
char pqname[PF_QNAME_SIZE];
|
||||
#define PF_ANCHOR_NAME_SIZE 16
|
||||
char anchorname[PF_ANCHOR_NAME_SIZE];
|
||||
#define PF_TAG_NAME_SIZE 16
|
||||
char tagname[PF_TAG_NAME_SIZE];
|
||||
char match_tagname[PF_TAG_NAME_SIZE];
|
||||
|
||||
char overload_tblname[PF_TABLE_NAME_SIZE];
|
||||
|
||||
TAILQ_ENTRY(pf_rule) entries;
|
||||
struct pf_pool rpool;
|
||||
|
||||
@ -479,6 +507,7 @@ struct pf_rule {
|
||||
|
||||
struct pfi_kif *kif;
|
||||
struct pf_anchor *anchor;
|
||||
struct pfr_ktable *overload_tbl;
|
||||
|
||||
pf_osfp_t os_fingerprint;
|
||||
|
||||
@ -488,10 +517,16 @@ struct pf_rule {
|
||||
u_int32_t src_nodes;
|
||||
u_int32_t max_src_nodes;
|
||||
u_int32_t max_src_states;
|
||||
u_int32_t max_src_conn;
|
||||
struct {
|
||||
u_int32_t limit;
|
||||
u_int32_t seconds;
|
||||
} max_src_conn_rate;
|
||||
u_int32_t qid;
|
||||
u_int32_t pqid;
|
||||
u_int32_t rt_listid;
|
||||
u_int32_t nr;
|
||||
u_int32_t prob;
|
||||
|
||||
u_int16_t return_icmp;
|
||||
u_int16_t return_icmp6;
|
||||
@ -526,6 +561,12 @@ struct pf_rule {
|
||||
u_int8_t rt;
|
||||
u_int8_t return_ttl;
|
||||
u_int8_t tos;
|
||||
u_int8_t anchor_relative;
|
||||
u_int8_t anchor_wildcard;
|
||||
|
||||
#define PF_FLUSH 0x01
|
||||
#define PF_FLUSH_GLOBAL 0x02
|
||||
u_int8_t flush;
|
||||
};
|
||||
|
||||
/* rule flags */
|
||||
@ -551,6 +592,16 @@ struct pf_rule {
|
||||
|
||||
#define PFSTATE_HIWAT 10000 /* default state table size */
|
||||
|
||||
|
||||
struct pf_threshold {
|
||||
u_int32_t limit;
|
||||
#define PF_THRESHOLD_MULT 1000
|
||||
#define PF_THRESHOLD_MAX 0xffffffff / PF_THRESHOLD_MULT
|
||||
u_int32_t seconds;
|
||||
u_int32_t count;
|
||||
u_int32_t last;
|
||||
};
|
||||
|
||||
struct pf_src_node {
|
||||
RB_ENTRY(pf_src_node) entry;
|
||||
struct pf_addr addr;
|
||||
@ -560,6 +611,8 @@ struct pf_src_node {
|
||||
u_int32_t bytes;
|
||||
u_int32_t packets;
|
||||
u_int32_t states;
|
||||
u_int32_t conn;
|
||||
struct pf_threshold conn_rate;
|
||||
u_int32_t creation;
|
||||
u_int32_t expire;
|
||||
sa_family_t af;
|
||||
@ -569,11 +622,19 @@ struct pf_src_node {
|
||||
#define PFSNODE_HIWAT 10000 /* default source node table size */
|
||||
|
||||
struct pf_state_scrub {
|
||||
struct timeval pfss_last; /* time received last packet */
|
||||
u_int32_t pfss_tsecr; /* last echoed timestamp */
|
||||
u_int32_t pfss_tsval; /* largest timestamp */
|
||||
u_int32_t pfss_tsval0; /* original timestamp */
|
||||
u_int16_t pfss_flags;
|
||||
#define PFSS_TIMESTAMP 0x0001 /* modulate timestamp */
|
||||
u_int8_t pfss_ttl; /* stashed TTL */
|
||||
#define PFSS_TIMESTAMP 0x0001 /* modulate timestamp */
|
||||
#define PFSS_PAWS 0x0010 /* stricter PAWS checks */
|
||||
#define PFSS_PAWS_IDLED 0x0020 /* was idle too long. no PAWS */
|
||||
#define PFSS_DATA_TS 0x0040 /* timestamp on data packets */
|
||||
#define PFSS_DATA_NOTS 0x0080 /* no timestamp on data packets */
|
||||
u_int8_t pfss_ttl; /* stashed TTL */
|
||||
u_int8_t pad;
|
||||
u_int32_t pfss_ts_mod; /* timestamp modulation */
|
||||
u_int32_t pfss_ts_mod; /* timestamp modulation */
|
||||
};
|
||||
|
||||
struct pf_state_host {
|
||||
@ -625,6 +686,7 @@ struct pf_state {
|
||||
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;
|
||||
@ -634,6 +696,7 @@ struct pf_state {
|
||||
u_int8_t sync_flags;
|
||||
#define PFSTATE_NOSYNC 0x01
|
||||
#define PFSTATE_FROMSYNC 0x02
|
||||
#define PFSTATE_STALE 0x04
|
||||
u_int8_t pad;
|
||||
};
|
||||
|
||||
@ -642,9 +705,6 @@ TAILQ_HEAD(pf_rulequeue, pf_rule);
|
||||
struct pf_anchor;
|
||||
|
||||
struct pf_ruleset {
|
||||
TAILQ_ENTRY(pf_ruleset) entries;
|
||||
#define PF_RULESET_NAME_SIZE 16
|
||||
char name[PF_RULESET_NAME_SIZE];
|
||||
struct {
|
||||
struct pf_rulequeue queues[2];
|
||||
struct {
|
||||
@ -659,19 +719,22 @@ struct pf_ruleset {
|
||||
int topen;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(pf_rulesetqueue, pf_ruleset);
|
||||
|
||||
RB_HEAD(pf_anchor_global, pf_anchor);
|
||||
RB_HEAD(pf_anchor_node, pf_anchor);
|
||||
struct pf_anchor {
|
||||
TAILQ_ENTRY(pf_anchor) entries;
|
||||
RB_ENTRY(pf_anchor) entry_global;
|
||||
RB_ENTRY(pf_anchor) entry_node;
|
||||
struct pf_anchor *parent;
|
||||
struct pf_anchor_node children;
|
||||
char name[PF_ANCHOR_NAME_SIZE];
|
||||
struct pf_rulesetqueue rulesets;
|
||||
int tables;
|
||||
char path[MAXPATHLEN];
|
||||
struct pf_ruleset ruleset;
|
||||
int refcnt; /* anchor rules */
|
||||
};
|
||||
|
||||
TAILQ_HEAD(pf_anchorqueue, pf_anchor);
|
||||
RB_PROTOTYPE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare);
|
||||
RB_PROTOTYPE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare);
|
||||
|
||||
#define PF_RESERVED_ANCHOR "_pf"
|
||||
#define PF_INTERFACE_RULESET "_if"
|
||||
|
||||
#define PFR_TFLAG_PERSIST 0x00000001
|
||||
#define PFR_TFLAG_CONST 0x00000002
|
||||
@ -684,8 +747,7 @@ TAILQ_HEAD(pf_anchorqueue, pf_anchor);
|
||||
#define PFR_TFLAG_ALLMASK 0x0000003F
|
||||
|
||||
struct pfr_table {
|
||||
char pfrt_anchor[PF_ANCHOR_NAME_SIZE];
|
||||
char pfrt_ruleset[PF_RULESET_NAME_SIZE];
|
||||
char pfrt_anchor[MAXPATHLEN];
|
||||
char pfrt_name[PF_TABLE_NAME_SIZE];
|
||||
u_int32_t pfrt_flags;
|
||||
u_int8_t pfrt_fback;
|
||||
@ -746,6 +808,7 @@ struct pfr_kentry {
|
||||
u_int8_t pfrke_net;
|
||||
u_int8_t pfrke_not;
|
||||
u_int8_t pfrke_mark;
|
||||
u_int8_t pfrke_intrpool;
|
||||
};
|
||||
|
||||
SLIST_HEAD(pfr_ktableworkq, pfr_ktable);
|
||||
@ -828,6 +891,8 @@ struct pfi_kif {
|
||||
#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 */
|
||||
#define PFI_IFLAG_SETABLE_MASK 0x0100 /* setable via DIOC{SET,CLR}IFFLAG */
|
||||
|
||||
struct pf_pdesc {
|
||||
u_int64_t tot_len; /* Make Mickey money */
|
||||
@ -845,11 +910,14 @@ struct pf_pdesc {
|
||||
struct pf_rule *nat_rule; /* nat/rdr rule applied to packet */
|
||||
struct pf_addr *src;
|
||||
struct pf_addr *dst;
|
||||
struct ether_header
|
||||
*eh;
|
||||
u_int16_t *ip_sum;
|
||||
u_int32_t p_len; /* total length of payload */
|
||||
u_int16_t flags; /* Let SCRUB trigger behavior in
|
||||
* state code. Easier than tags */
|
||||
#define PFDESC_TCP_NORM 0x0001 /* TCP shall be statefully scrubbed */
|
||||
#define PFDESC_IP_REAS 0x0002 /* IP frags would've been reassembled */
|
||||
sa_family_t af;
|
||||
u_int8_t proto;
|
||||
u_int8_t tos;
|
||||
@ -866,7 +934,16 @@ struct pf_pdesc {
|
||||
#define PFRES_SHORT 3 /* Dropping short packet */
|
||||
#define PFRES_NORM 4 /* Dropping by normalizer */
|
||||
#define PFRES_MEMORY 5 /* Dropped due to lacking mem */
|
||||
#define PFRES_MAX 6 /* total+1 */
|
||||
#define PFRES_TS 6 /* Bad TCP Timestamp (RFC1323) */
|
||||
#define PFRES_CONGEST 7 /* Congestion (of ipintrq) */
|
||||
#define PFRES_IPOPTIONS 8 /* IP option */
|
||||
#define PFRES_PROTCKSUM 9 /* Protocol checksum invalid */
|
||||
#define PFRES_BADSTATE 10 /* State mismatch */
|
||||
#define PFRES_STATEINS 11 /* State insertion failure */
|
||||
#define PFRES_MAXSTATES 12 /* State limit */
|
||||
#define PFRES_SRCLIMIT 13 /* Source node/conn limit */
|
||||
#define PFRES_SYNPROXY 14 /* SYN proxy */
|
||||
#define PFRES_MAX 15 /* total+1 */
|
||||
|
||||
#define PFRES_NAMES { \
|
||||
"match", \
|
||||
@ -875,6 +952,36 @@ struct pf_pdesc {
|
||||
"short", \
|
||||
"normalize", \
|
||||
"memory", \
|
||||
"bad-timestamp", \
|
||||
"congestion", \
|
||||
"ip-option", \
|
||||
"proto-cksum", \
|
||||
"state-mismatch", \
|
||||
"state-insert", \
|
||||
"state-limit", \
|
||||
"src-limit", \
|
||||
"synproxy", \
|
||||
NULL \
|
||||
}
|
||||
|
||||
/* Counters for other things we want to keep track of */
|
||||
#define LCNT_STATES 0 /* states */
|
||||
#define LCNT_SRCSTATES 1 /* max-src-states */
|
||||
#define LCNT_SRCNODES 2 /* max-src-nodes */
|
||||
#define LCNT_SRCCONN 3 /* max-src-conn */
|
||||
#define LCNT_SRCCONNRATE 4 /* max-src-conn-rate */
|
||||
#define LCNT_OVERLOAD_TABLE 5 /* entry added to overload table */
|
||||
#define LCNT_OVERLOAD_FLUSH 6 /* state entries flushed */
|
||||
#define LCNT_MAX 7 /* total+1 */
|
||||
|
||||
#define LCNT_NAMES { \
|
||||
"max states per rule", \
|
||||
"max-src-states", \
|
||||
"max-src-nodes", \
|
||||
"max-src-conn", \
|
||||
"max-src-conn-rate", \
|
||||
"overload table insertion", \
|
||||
"overload flush states", \
|
||||
NULL \
|
||||
}
|
||||
|
||||
@ -932,6 +1039,7 @@ struct pf_pdesc {
|
||||
|
||||
struct pf_status {
|
||||
u_int64_t counters[PFRES_MAX];
|
||||
u_int64_t lcounters[LCNT_MAX]; /* limit counters */
|
||||
u_int64_t fcounters[FCNT_MAX];
|
||||
u_int64_t scounters[SCNT_MAX];
|
||||
u_int64_t pcounters[2][2][3];
|
||||
@ -1034,8 +1142,7 @@ struct pfioc_pooladdr {
|
||||
u_int8_t r_action;
|
||||
u_int8_t r_last;
|
||||
u_int8_t af;
|
||||
char anchor[PF_ANCHOR_NAME_SIZE];
|
||||
char ruleset[PF_RULESET_NAME_SIZE];
|
||||
char anchor[MAXPATHLEN];
|
||||
struct pf_pooladdr addr;
|
||||
};
|
||||
|
||||
@ -1044,8 +1151,8 @@ struct pfioc_rule {
|
||||
u_int32_t ticket;
|
||||
u_int32_t pool_ticket;
|
||||
u_int32_t nr;
|
||||
char anchor[PF_ANCHOR_NAME_SIZE];
|
||||
char ruleset[PF_RULESET_NAME_SIZE];
|
||||
char anchor[MAXPATHLEN];
|
||||
char anchor_call[MAXPATHLEN];
|
||||
struct pf_rule rule;
|
||||
};
|
||||
|
||||
@ -1126,15 +1233,10 @@ struct pfioc_qstats {
|
||||
u_int8_t scheduler;
|
||||
};
|
||||
|
||||
struct pfioc_anchor {
|
||||
u_int32_t nr;
|
||||
char name[PF_ANCHOR_NAME_SIZE];
|
||||
};
|
||||
|
||||
struct pfioc_ruleset {
|
||||
u_int32_t nr;
|
||||
char anchor[PF_ANCHOR_NAME_SIZE];
|
||||
char name[PF_RULESET_NAME_SIZE];
|
||||
char path[MAXPATHLEN];
|
||||
char name[PF_ANCHOR_NAME_SIZE];
|
||||
};
|
||||
|
||||
#define PF_RULESET_ALTQ (PF_RULESET_MAX)
|
||||
@ -1144,8 +1246,7 @@ struct pfioc_trans {
|
||||
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];
|
||||
char anchor[MAXPATHLEN];
|
||||
u_int32_t ticket;
|
||||
} *array;
|
||||
};
|
||||
@ -1202,9 +1303,7 @@ struct pfioc_iface {
|
||||
|
||||
#define DIOCSTART _IO ('D', 1)
|
||||
#define DIOCSTOP _IO ('D', 2)
|
||||
#define DIOCBEGINRULES _IOWR('D', 3, struct pfioc_rule)
|
||||
#define DIOCADDRULE _IOWR('D', 4, struct pfioc_rule)
|
||||
#define DIOCCOMMITRULES _IOWR('D', 5, struct pfioc_rule)
|
||||
#define DIOCGETRULES _IOWR('D', 6, struct pfioc_rule)
|
||||
#define DIOCGETRULE _IOWR('D', 7, struct pfioc_rule)
|
||||
/* XXX cut 8 - 17 */
|
||||
@ -1227,9 +1326,7 @@ struct pfioc_iface {
|
||||
#define DIOCKILLSTATES _IOWR('D', 41, struct pfioc_state_kill)
|
||||
#define DIOCSTARTALTQ _IO ('D', 42)
|
||||
#define DIOCSTOPALTQ _IO ('D', 43)
|
||||
#define DIOCBEGINALTQS _IOWR('D', 44, u_int32_t)
|
||||
#define DIOCADDALTQ _IOWR('D', 45, struct pfioc_altq)
|
||||
#define DIOCCOMMITALTQS _IOWR('D', 46, u_int32_t)
|
||||
#define DIOCGETALTQS _IOWR('D', 47, struct pfioc_altq)
|
||||
#define DIOCGETALTQ _IOWR('D', 48, struct pfioc_altq)
|
||||
#define DIOCCHANGEALTQ _IOWR('D', 49, struct pfioc_altq)
|
||||
@ -1239,8 +1336,7 @@ struct pfioc_iface {
|
||||
#define DIOCGETADDRS _IOWR('D', 53, struct pfioc_pooladdr)
|
||||
#define DIOCGETADDR _IOWR('D', 54, struct pfioc_pooladdr)
|
||||
#define DIOCCHANGEADDR _IOWR('D', 55, struct pfioc_pooladdr)
|
||||
#define DIOCGETANCHORS _IOWR('D', 56, struct pfioc_anchor)
|
||||
#define DIOCGETANCHOR _IOWR('D', 57, struct pfioc_anchor)
|
||||
/* XXX cut 55 - 57 */
|
||||
#define DIOCGETRULESETS _IOWR('D', 58, struct pfioc_ruleset)
|
||||
#define DIOCGETRULESET _IOWR('D', 59, struct pfioc_ruleset)
|
||||
#define DIOCRCLRTABLES _IOWR('D', 60, struct pfioc_table)
|
||||
@ -1258,8 +1354,6 @@ struct pfioc_iface {
|
||||
#define DIOCRCLRASTATS _IOWR('D', 72, struct pfioc_table)
|
||||
#define DIOCRTSTADDRS _IOWR('D', 73, struct pfioc_table)
|
||||
#define DIOCRSETTFLAGS _IOWR('D', 74, struct pfioc_table)
|
||||
#define DIOCRINABEGIN _IOWR('D', 75, struct pfioc_table)
|
||||
#define DIOCRINACOMMIT _IOWR('D', 76, struct pfioc_table)
|
||||
#define DIOCRINADEFINE _IOWR('D', 77, struct pfioc_table)
|
||||
#define DIOCOSFPFLUSH _IO('D', 78)
|
||||
#define DIOCOSFPADD _IOWR('D', 79, struct pf_osfp_ioctl)
|
||||
@ -1272,6 +1366,8 @@ struct pfioc_iface {
|
||||
#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)
|
||||
|
||||
#ifdef _KERNEL
|
||||
RB_HEAD(pf_src_tree, pf_src_node);
|
||||
@ -1284,7 +1380,7 @@ RB_PROTOTYPE(pf_state_tree_id, pf_state,
|
||||
extern struct pf_state_tree_id tree_id;
|
||||
extern struct pf_state_queue state_updates;
|
||||
|
||||
extern struct pf_anchorqueue pf_anchors;
|
||||
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];
|
||||
@ -1306,13 +1402,13 @@ extern int pf_tbladdr_setup(struct pf_ruleset *,
|
||||
extern void pf_tbladdr_remove(struct pf_addr_wrap *);
|
||||
extern void pf_tbladdr_copyout(struct pf_addr_wrap *);
|
||||
extern void pf_calc_skip_steps(struct pf_rulequeue *);
|
||||
extern void pf_update_anchor_rules(void);
|
||||
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 void pf_purge_expired_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 **,
|
||||
@ -1322,11 +1418,11 @@ 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 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(char *, char *);
|
||||
extern struct pf_ruleset *pf_find_or_create_ruleset(
|
||||
char[PF_ANCHOR_NAME_SIZE],
|
||||
char[PF_RULESET_NAME_SIZE]);
|
||||
extern struct pf_ruleset *pf_find_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,
|
||||
@ -1340,11 +1436,11 @@ void pf_rm_rule(struct pf_rulequeue *,
|
||||
struct pf_rule *);
|
||||
|
||||
#ifdef INET
|
||||
int pf_test(int, struct ifnet *, struct mbuf **);
|
||||
int pf_test(int, struct ifnet *, struct mbuf **, struct ether_header *);
|
||||
#endif /* INET */
|
||||
|
||||
#ifdef INET6
|
||||
int pf_test6(int, struct ifnet *, struct mbuf **);
|
||||
int pf_test6(int, struct ifnet *, struct mbuf **, struct ether_header *);
|
||||
void pf_poolmask(struct pf_addr *, struct pf_addr*,
|
||||
struct pf_addr *, struct pf_addr *, u_int8_t);
|
||||
void pf_addr_inc(struct pf_addr *, sa_family_t);
|
||||
@ -1363,20 +1459,23 @@ int pf_match_uid(u_int8_t, uid_t, uid_t, uid_t);
|
||||
int pf_match_gid(u_int8_t, gid_t, gid_t, gid_t);
|
||||
|
||||
void pf_normalize_init(void);
|
||||
int pf_normalize_ip(struct mbuf **, int, struct pfi_kif *, u_short *);
|
||||
int pf_normalize_ip6(struct mbuf **, int, struct pfi_kif *, u_short *);
|
||||
int pf_normalize_ip(struct mbuf **, int, struct pfi_kif *, u_short *,
|
||||
struct pf_pdesc *);
|
||||
int pf_normalize_ip6(struct mbuf **, int, struct pfi_kif *, u_short *,
|
||||
struct pf_pdesc *);
|
||||
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 *,
|
||||
struct tcphdr *, struct pf_state_peer *, struct pf_state_peer *);
|
||||
int pf_normalize_tcp_stateful(struct mbuf *, int, struct pf_pdesc *,
|
||||
u_short *, struct tcphdr *, struct pf_state_peer *,
|
||||
struct pf_state_peer *, int *);
|
||||
u_short *, struct tcphdr *, struct pf_state *,
|
||||
struct pf_state_peer *, struct pf_state_peer *, int *);
|
||||
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_rtlabel_match(struct pf_addr *, sa_family_t, struct pf_addr_wrap *);
|
||||
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,
|
||||
@ -1395,6 +1494,7 @@ int pfr_get_tstats(struct pfr_table *, struct pfr_tstats *, int *, int);
|
||||
int pfr_clr_tstats(struct pfr_table *, int, int *, int);
|
||||
int pfr_set_tflags(struct pfr_table *, int, int, int, int *, int *, int);
|
||||
int pfr_clr_addrs(struct pfr_table *, int *, int);
|
||||
int pfr_insert_kentry(struct pfr_ktable *, struct pfr_addr *, long);
|
||||
int pfr_add_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
|
||||
int);
|
||||
int pfr_del_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
|
||||
@ -1430,6 +1530,8 @@ 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);
|
||||
int pfi_match_addr(struct pfi_dynaddr *, struct pf_addr *,
|
||||
sa_family_t);
|
||||
|
||||
@ -1437,6 +1539,7 @@ 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 *);
|
||||
|
Loading…
Reference in New Issue
Block a user