diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 2002-11-29 18:25:24 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 2002-11-29 18:25:24 +0000 |
commit | 9f068907d7c2fd3327baf5ca6957f17a3d51f933 (patch) | |
tree | d067aaee366cadc20a0bb6c5f425719fde658204 | |
parent | 2d67f506b409747d0351bb20e0a3c0513fb28d32 (diff) |
expose state table changes
-rw-r--r-- | sys/conf/GENERIC | 7 | ||||
-rw-r--r-- | sys/conf/files | 8 | ||||
-rw-r--r-- | sys/net/bpf.h | 3 | ||||
-rw-r--r-- | sys/net/if_pfsync.c | 359 | ||||
-rw-r--r-- | sys/net/if_pfsync.h | 84 | ||||
-rw-r--r-- | sys/net/if_types.h | 3 | ||||
-rw-r--r-- | sys/net/pf.c | 12 | ||||
-rw-r--r-- | sys/net/pfvar.h | 4 |
8 files changed, 468 insertions, 12 deletions
diff --git a/sys/conf/GENERIC b/sys/conf/GENERIC index f1898959859..d25b15e4800 100644 --- a/sys/conf/GENERIC +++ b/sys/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.91 2002/09/26 21:44:37 deraadt Exp $ +# $OpenBSD: GENERIC,v 1.92 2002/11/29 18:25:23 mickey Exp $ # # Machine-independent option; used by all architectures for their # GENERIC kernel @@ -75,8 +75,9 @@ option PPP_BSDCOMP # PPP BSD compression option PPP_DEFLATE #option MROUTING # Multicast router -pseudo-device pf 1 # packet filter -pseudo-device pflog 1 # pf log if +pseudo-device pf # packet filter +pseudo-device pflog # pf log if +pseudo-device pfsync # pf sync if pseudo-device loop 2 # network loopback pseudo-device bpfilter 8 # packet filter pseudo-device sl 2 # CSLIP diff --git a/sys/conf/files b/sys/conf/files index eea613f9134..35bc319ecb2 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.257 2002/09/03 16:30:54 mickey Exp $ +# $OpenBSD: files,v 1.258 2002/11/29 18:25:23 mickey Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -336,7 +336,6 @@ pseudo-device tun: ifnet pseudo-device bpfilter: ifnet pseudo-device strip: ifnet pseudo-device enc: ifnet -pseudo-device pflog: ifnet pseudo-device bridge: ifnet, ether pseudo-device vlan: ifnet, ether pseudo-device sppp: ifnet @@ -355,6 +354,10 @@ pseudo-device pf: ifnet file net/pf.c pf needs-flag file net/pf_norm.c pf file net/pf_ioctl.c pf +pseudo-device pflog: ifnet +file net/if_pflog.c pflog needs-flag +pseudo-device pfsync: ifnet +file net/if_pfsync.c pfsync needs-flag pseudo-device bio file dev/bio.c bio needs-flag @@ -644,7 +647,6 @@ file net/route.c file net/rtsock.c file net/slcompress.c sl | ppp | strip file net/if_enc.c enc needs-count -file net/if_pflog.c pflog needs-count file net/if_gre.c gre needs-count #file net/if_ieee1394subr.c ieee1394 file netccitt/ccitt_proto.c ccitt diff --git a/sys/net/bpf.h b/sys/net/bpf.h index 06b319e0226..8c0f26bffe4 100644 --- a/sys/net/bpf.h +++ b/sys/net/bpf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bpf.h,v 1.18 2002/03/14 01:27:09 millert Exp $ */ +/* $OpenBSD: bpf.h,v 1.19 2002/11/29 18:25:22 mickey Exp $ */ /* $NetBSD: bpf.h,v 1.15 1996/12/13 07:57:33 mikel Exp $ */ /* @@ -170,6 +170,7 @@ struct bpf_hdr { #define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ #define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ #define DLT_PFLOG 17 /* Packet filter logging */ +#define DLT_PFSYNC 18 /* Packet filter state syncing */ /* * The instruction encodings. diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c new file mode 100644 index 00000000000..a2b8b25c8cf --- /dev/null +++ b/sys/net/if_pfsync.c @@ -0,0 +1,359 @@ +/* $OpenBSD: if_pfsync.c,v 1.1 2002/11/29 18:25:22 mickey Exp $ */ + +/* + * Copyright (c) 2002 Michael Shalayeff + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bpfilter.h" +#include "pfsync.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/time.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/timeout.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/route.h> +#include <net/bpf.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/in_var.h> +#endif + +#ifdef INET6 +#ifndef INET +#include <netinet/in.h> +#endif +#include <netinet6/nd6.h> +#endif /* INET6 */ + +#include <net/pfvar.h> +#include <net/if_pfsync.h> + +#define PFSYNCMTU \ + (sizeof(struct pfsync_header) + sizeof(struct pf_state) * 4) +#define PFSYNC_MINMTU \ + (sizeof(struct pfsync_header) + sizeof(struct pf_state)) + +#ifdef PFSYNCDEBUG +#define DPRINTF(x) do { if (pfsyncdebug) printf x ; } while (0) +int pfsyncdebug; +#else +#define DPRINTF(x) +#endif + +struct pfsync_softc pfsyncif; + +void pfsyncattach(int); +int pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); +int pfsyncioctl(struct ifnet *, u_long, caddr_t); +void pfsyncrtrequest(int, struct rtentry *, struct sockaddr *); +void pfsyncstart(struct ifnet *); + +struct mbuf *pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action); +int pfsync_sendout(struct pfsync_softc *sc); +void pfsync_timeout(void *v); + +extern int ifqmaxlen; + +void +pfsyncattach(int npfsync) +{ + struct ifnet *ifp; + + pfsyncif.sc_mbuf = NULL; + pfsyncif.sc_ptr = NULL; + pfsyncif.sc_count = 8; + ifp = &pfsyncif.sc_if; + strcpy(ifp->if_xname, "pfsync0"); + ifp->if_softc = &pfsyncif; + ifp->if_mtu = PFSYNCMTU; + ifp->if_ioctl = pfsyncioctl; + ifp->if_output = pfsyncoutput; + ifp->if_start = pfsyncstart; + ifp->if_type = IFT_PFSYNC; + ifp->if_snd.ifq_maxlen = ifqmaxlen; + ifp->if_hdrlen = PFSYNC_HDRLEN; + timeout_set(&pfsyncif.sc_tmo, pfsync_timeout, &pfsyncif); + if_attach(ifp); + if_alloc_sadl(ifp); + +#if NBPFILTER > 0 + bpfattach(&pfsyncif.sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN); +#endif +} + +/* + * Start output on the pfsync interface. + */ +void +pfsyncstart(struct ifnet *ifp) +{ + struct mbuf *m; + int s; + + for (;;) { + s = splimp(); + IF_DROP(&ifp->if_snd); + IF_DEQUEUE(&ifp->if_snd, m); + splx(s); + + if (m == NULL) + return; + else + m_freem(m); + } +} + +int +pfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, + struct rtentry *rt) +{ + m_freem(m); + return (0); +} + +/* ARGSUSED */ +void +pfsyncrtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa) +{ + if (rt) + rt->rt_rmx.rmx_mtu = PFSYNCMTU; +} + +/* ARGSUSED */ +int +pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +{ + struct pfsync_softc *sc = ifp->if_softc; + struct ifreq *ifr = (struct ifreq *)data; + int s; + + switch (cmd) { + case SIOCSIFADDR: + case SIOCAIFADDR: + case SIOCSIFDSTADDR: + case SIOCSIFFLAGS: + if (ifp->if_flags & IFF_UP) + ifp->if_flags |= IFF_RUNNING; + else + ifp->if_flags &= ~IFF_RUNNING; + break; + case SIOCSIFMTU: + if (ifr->ifr_mtu < PFSYNC_MINMTU) + return (EINVAL); + if (ifr->ifr_mtu > MCLBYTES) + ifr->ifr_mtu = MCLBYTES; + s = splnet(); + if (ifr->ifr_mtu < ifp->if_mtu) + pfsync_sendout(sc); + sc->sc_count = (ifr->ifr_mtu - sizeof(struct pfsync_header)) / + sizeof(struct pf_state); + ifp->if_mtu = sizeof(struct pfsync_header) + + sc->sc_count * sizeof(struct pf_state); + splx(s); + break; + default: + return (ENOTTY); + } + + return (0); +} + +struct mbuf * +pfsync_get_mbuf(sc, action) + struct pfsync_softc *sc; + u_int8_t action; +{ + extern int hz; + struct pfsync_header *h; + struct mbuf *m; + int len; + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == NULL) { + sc->sc_if.if_oerrors++; + return (NULL); + } + + len = sc->sc_if.if_mtu; + if (len > MHLEN) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + m_free(m); + sc->sc_if.if_oerrors++; + return (NULL); + } + } + m->m_pkthdr.rcvif = NULL; + m->m_pkthdr.len = m->m_len = len; + MH_ALIGN(m, m->m_len); + + h = mtod(m, struct pfsync_header *); + h->version = PFSYNC_VERSION; + h->af = 0; + h->count = 0; + h->action = action; + + sc->sc_mbuf = m; + sc->sc_ptr = (struct pf_state *)((char *)h + PFSYNC_HDRLEN); + timeout_add(&sc->sc_tmo, hz); + + return (m); +} + +int +pfsync_pack_state(action, st) + u_int8_t action; + struct pf_state *st; +{ + extern struct timeval time; + struct ifnet *ifp = &pfsyncif.sc_if; + struct pfsync_softc *sc = ifp->if_softc; + struct pfsync_header *h; + struct pf_state *sp; + struct pf_rule *r = st->rule.ptr; + struct mbuf *m; + u_long secs; + int s, ret; + + if (action >= PFSYNC_ACT_MAX) + return (EINVAL); + + s = splnet(); + m = sc->sc_mbuf; + if (m == NULL) { + if ((m = pfsync_get_mbuf(sc, action)) == NULL) { + splx(s); + return (ENOMEM); + } + h = mtod(m, struct pfsync_header *); + } else { + h = mtod(m, struct pfsync_header *); + if (h->action != action) { + pfsync_sendout(sc); + if ((m = pfsync_get_mbuf(sc, action)) == NULL) { + splx(s); + return (ENOMEM); + } + h = mtod(m, struct pfsync_header *); + } + } + + sp = sc->sc_ptr++; + h->count++; + bzero(sp, sizeof(*sp)); + + sp->lan = st->lan; HTONS(sp->lan.port); + sp->gwy = st->gwy; HTONS(sp->gwy.port); + sp->ext = st->ext; HTONS(sp->ext.port); + + pf_state_peer_hton(&st->src, &sp->src); + pf_state_peer_hton(&st->dst, &sp->dst); + + sp->rt_addr = st->rt_addr; + secs = time.tv_sec; + sp->creation = htonl(secs - st->creation); + if (st->expire <= secs) + sp->expire = htonl(0); + else + sp->expire = htonl(st->expire - secs); + sp->packets = htonl(st->packets); + sp->bytes = htonl(st->bytes); + if (r == NULL) + sp->rule.nr = htonl(-1); + else + sp->rule.nr = htonl(r->nr); + sp->af = st->af; + sp->proto = st->proto; + sp->direction = st->direction; + sp->log = st->log; + sp->allow_opts = st->allow_opts; + + ret = 0; + if (h->count == sc->sc_count) + ret = pfsync_sendout(sc); + + splx(s); + return (0); +} + +int +pfsync_clear_state(st) + struct pf_state *st; +{ + struct ifnet *ifp = &pfsyncif.sc_if; + struct pfsync_softc *sc = ifp->if_softc; + struct mbuf *m = sc->sc_mbuf; + int s, ret; + + s = splnet(); + if (m == NULL && (m = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR)) == NULL) { + splx(s); + return (ENOMEM); + } + + ret = (pfsync_sendout(sc)); + splx(s); + return (ret); +} + +void +pfsync_timeout(void *v) +{ + struct pfsync_softc *sc = v; + int s; + + s = splnet(); + pfsync_sendout(sc); + splx(s); +} + +int +pfsync_sendout(sc) + struct pfsync_softc *sc; +{ + struct ifnet *ifp = &sc->sc_if; + struct mbuf *m = sc->sc_mbuf; + + timeout_del(&sc->sc_tmo); + sc->sc_mbuf = NULL; + sc->sc_ptr = NULL; + +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m); +#endif + + m_freem(m); + + return (0); +} diff --git a/sys/net/if_pfsync.h b/sys/net/if_pfsync.h new file mode 100644 index 00000000000..d05b202b2d6 --- /dev/null +++ b/sys/net/if_pfsync.h @@ -0,0 +1,84 @@ +/* $OpenBSD: if_pfsync.h,v 1.1 2002/11/29 18:25:22 mickey Exp $ */ + +/* + * Copyright (c) 2001 Michael Shalayeff + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _NET_IF_PFSYNC_H_ +#define _NET_IF_PFSYNC_H_ + +#ifdef _KERNEL +struct pfsync_softc { + struct ifnet sc_if; + + struct timeout sc_tmo; + struct mbuf *sc_mbuf; /* current cummulative mbuf */ + struct pf_state *sc_ptr; /* current ongoing state */ + int sc_count; /* number of states in one mtu */ +}; +#endif + +struct pfsync_header { + u_int8_t version; +#define PFSYNC_VERSION 1 + u_int8_t af; + u_int8_t action; +#define PFSYNC_ACT_CLR 0 +#define PFSYNC_ACT_INS 1 +#define PFSYNC_ACT_UPD 2 +#define PFSYNC_ACT_DEL 3 +#define PFSYNC_ACT_MAX 4 + u_int8_t count; +}; + +#define PFSYNC_HDRLEN sizeof(struct pfsync_header) +#define PFSYNC_ACTIONS \ + "CLR ST", "INS ST", "UPD ST", "DEL ST" + +#define pf_state_peer_hton(s,d) do { \ + (d)->seqlo = htonl((s)->seqlo); \ + (d)->seqhi = htonl((s)->seqhi); \ + (d)->seqdiff = htonl((s)->seqdiff); \ + (d)->max_win = htons((s)->max_win); \ + (d)->state = (s)->state; \ +} while (0) + +#define pf_state_peer_ntoh(s,d) do { \ + (d)->seqlo = ntohl((s)->seqlo); \ + (d)->seqhi = ntohl((s)->seqhi); \ + (d)->seqdiff = ntohl((s)->seqdiff); \ + (d)->max_win = ntohs((s)->max_win); \ + (d)->state = (s)->state; \ +} while (0) + +#ifdef _KERNEL +int pfsync_clear_state __P((struct pf_state *)); +int pfsync_pack_state __P((u_int8_t, struct pf_state *)); +#define pfsync_insert_state(st) pfsync_pack_state(PFSYNC_ACT_INS, (st)) +#define pfsync_update_state(st) pfsync_pack_state(PFSYNC_ACT_UPD, (st)) +#define pfsync_delete_state(st) pfsync_pack_state(PFSYNC_ACT_DEL, (st)) +#endif + +#endif /* _NET_IF_PFSYNC_H_ */ diff --git a/sys/net/if_types.h b/sys/net/if_types.h index 9871575813b..2ca4a5b2b35 100644 --- a/sys/net/if_types.h +++ b/sys/net/if_types.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_types.h,v 1.13 2002/05/30 01:21:08 itojun Exp $ */ +/* $OpenBSD: if_types.h,v 1.14 2002/11/29 18:25:22 mickey Exp $ */ /* $NetBSD: if_types.h,v 1.17 2000/10/26 06:51:31 onoe Exp $ */ /* @@ -268,5 +268,6 @@ #define IFT_FAITH 0xf3 #define IFT_ENC 0xf4 /* Encapsulation */ #define IFT_PFLOG 0xf5 /* Packet filter logging */ +#define IFT_PFSYNC 0xf6 /* Packet filter state syncing */ #endif /* _NET_IF_TYPES_H_ */ diff --git a/sys/net/pf.c b/sys/net/pf.c index 416235f14fb..fc8dd350d78 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.264 2002/11/28 12:07:37 mcbride Exp $ */ +/* $OpenBSD: pf.c,v 1.265 2002/11/29 18:25:22 mickey Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -36,6 +36,7 @@ #include "bpfilter.h" #include "pflog.h" +#include "pfsync.h" #include <sys/param.h> #include <sys/systm.h> @@ -51,7 +52,6 @@ #include <net/if_types.h> #include <net/bpf.h> #include <net/route.h> -#include <net/if_pflog.h> #include <netinet/in.h> #include <netinet/in_var.h> @@ -70,6 +70,8 @@ #include <dev/rndvar.h> #include <net/pfvar.h> +#include <net/if_pflog.h> +#include <net/if_pfsync.h> #ifdef INET6 #include <netinet/ip6.h> @@ -444,6 +446,9 @@ pf_insert_state(struct pf_state *state) pf_status.fcounters[FCNT_STATE_INSERT]++; pf_status.states++; +#if NPFSYNC + pfsync_insert_state(state); +#endif return (0); } @@ -489,6 +494,9 @@ pf_purge_expired_states(void) KASSERT(peer->state == cur->state); RB_REMOVE(pf_state_tree, &tree_lan_ext, peer); +#if NPFSYNC + pfsync_delete_state(cur->state); +#endif if (cur->state->rule.ptr != NULL) cur->state->rule.ptr->states--; pool_put(&pf_state_pl, cur->state); diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 5ddefb2121f..4583e62ecf3 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.105 2002/11/28 12:07:37 mcbride Exp $ */ +/* $OpenBSD: pfvar.h,v 1.106 2002/11/29 18:25:23 mickey Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -371,7 +371,7 @@ struct pf_state { struct pf_state_peer dst; union { struct pf_rule *ptr; - u_int16_t nr; + u_int32_t nr; } rule; struct pf_addr rt_addr; struct ifnet *rt_ifp; |