Add ipf packet-filtering option to if_bridge. The option is controlled at
compile-time by BRIDGE_IPF, and at runtime by brconfig with the {ipf,-ipf} option on a per-bridge basis. As a side-effect, add PFIL_HOOKS processing to if_bridge.
This commit is contained in:
parent
baa98646a0
commit
6b857c229e
@ -1,4 +1,4 @@
|
|||||||
.\" $NetBSD: brconfig.8,v 1.5 2002/11/06 05:23:57 enami Exp $
|
.\" $NetBSD: brconfig.8,v 1.6 2003/02/15 00:46:30 perseant Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright 2001 Wasabi Systems, Inc.
|
.\" Copyright 2001 Wasabi Systems, Inc.
|
||||||
.\" All rights reserved.
|
.\" All rights reserved.
|
||||||
@ -142,6 +142,12 @@ For packets without the
|
|||||||
attribute, the only packets forwarded on the interface are broadcast
|
attribute, the only packets forwarded on the interface are broadcast
|
||||||
or multicast packets and packets for which the destination address
|
or multicast packets and packets for which the destination address
|
||||||
is known to be on the interface's segment.
|
is known to be on the interface's segment.
|
||||||
|
.It Cm ipf
|
||||||
|
Enable IPF packet filtering on the bridge. The current implementation passes
|
||||||
|
all ARP and RARP packets through the bridge while filtering IP and ICMP
|
||||||
|
packets through IPF.
|
||||||
|
.It Cm -ipf
|
||||||
|
Disable IPF packet filtering on the bridge (the default).
|
||||||
.It Cm learn Ar interface
|
.It Cm learn Ar interface
|
||||||
Mark an interface as a
|
Mark an interface as a
|
||||||
.Dq learning
|
.Dq learning
|
||||||
@ -230,7 +236,8 @@ create
|
|||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr bridge 4 ,
|
.Xr bridge 4 ,
|
||||||
.Xr ifconfig.if 5 ,
|
.Xr ifconfig.if 5 ,
|
||||||
.Xr ifconfig 8
|
.Xr ifconfig 8 ,
|
||||||
|
.Xr ipf 8
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: brconfig.c,v 1.2 2002/11/06 05:26:54 enami Exp $ */
|
/* $NetBSD: brconfig.c,v 1.3 2003/02/15 00:46:31 perseant Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2001 Wasabi Systems, Inc.
|
* Copyright 2001 Wasabi Systems, Inc.
|
||||||
@ -87,6 +87,7 @@ void cmd_priority(const struct command *, int, const char *, char **);
|
|||||||
void cmd_ifpriority(const struct command *, int, const char *, char **);
|
void cmd_ifpriority(const struct command *, int, const char *, char **);
|
||||||
void cmd_timeout(const struct command *, int, const char *, char **);
|
void cmd_timeout(const struct command *, int, const char *, char **);
|
||||||
void cmd_stp(const struct command *, int, const char *, char **);
|
void cmd_stp(const struct command *, int, const char *, char **);
|
||||||
|
void cmd_ipf(const struct command *, int, const char *, char **);
|
||||||
|
|
||||||
const struct command command_table[] = {
|
const struct command command_table[] = {
|
||||||
{ "add", 1, 0, cmd_add },
|
{ "add", 1, 0, cmd_add },
|
||||||
@ -119,6 +120,9 @@ const struct command command_table[] = {
|
|||||||
{ "stp", 1, 0, cmd_stp },
|
{ "stp", 1, 0, cmd_stp },
|
||||||
{ "-stp", 1, CMD_INVERT, cmd_stp },
|
{ "-stp", 1, CMD_INVERT, cmd_stp },
|
||||||
|
|
||||||
|
{ "ipf", 0, 0, cmd_ipf },
|
||||||
|
{ "-ipf", 0, CMD_INVERT, cmd_ipf },
|
||||||
|
|
||||||
{ NULL, 0, 0, NULL },
|
{ NULL, 0, 0, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -248,6 +252,7 @@ usage(void)
|
|||||||
"<bridge> deladdr <address>",
|
"<bridge> deladdr <address>",
|
||||||
"<bridge> flush",
|
"<bridge> flush",
|
||||||
"<bridge> flushall",
|
"<bridge> flushall",
|
||||||
|
"<bridge> ipf|-ipf",
|
||||||
"<bridge> discover|-discover <interface>",
|
"<bridge> discover|-discover <interface>",
|
||||||
"<bridge> learn|-learn <interface>",
|
"<bridge> learn|-learn <interface>",
|
||||||
"<bridge> stp|-stp <interface>",
|
"<bridge> stp|-stp <interface>",
|
||||||
@ -788,3 +793,18 @@ cmd_timeout(const struct command *cmd, int sock, const char *bridge,
|
|||||||
if (do_cmd(sock, bridge, BRDGSTO, ¶m, sizeof(param), 1) < 0)
|
if (do_cmd(sock, bridge, BRDGSTO, ¶m, sizeof(param), 1) < 0)
|
||||||
err(1, "%s %s", cmd->cmd_keyword, argv[0]);
|
err(1, "%s %s", cmd->cmd_keyword, argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cmd_ipf(const struct command *cmd, int sock, const char *bridge,
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
struct ifbrparam param;
|
||||||
|
|
||||||
|
if (do_cmd(sock, bridge, BRDGGFILT, ¶m, sizeof(param), 0) < 0)
|
||||||
|
err(1, "%s", cmd->cmd_keyword);
|
||||||
|
|
||||||
|
param.ifbrp_filter &= ~IFBF_FILT_USEIPF;
|
||||||
|
param.ifbrp_filter |= (cmd->cmd_flags & CMD_INVERT) ? 0 : IFBF_FILT_USEIPF;
|
||||||
|
if (do_cmd(sock, bridge, BRDGSFILT, ¶m, sizeof(param), 1) < 0)
|
||||||
|
err(1, "%s %x", cmd->cmd_keyword, param.ifbrp_filter);
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: if_bridge.c,v 1.8 2002/08/24 19:00:31 martin Exp $ */
|
/* $NetBSD: if_bridge.c,v 1.9 2003/02/15 00:46:30 perseant Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2001 Wasabi Systems, Inc.
|
* Copyright 2001 Wasabi Systems, Inc.
|
||||||
@ -82,7 +82,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.8 2002/08/24 19:00:31 martin Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.9 2003/02/15 00:46:30 perseant Exp $");
|
||||||
|
|
||||||
#include "bpfilter.h"
|
#include "bpfilter.h"
|
||||||
#include "rnd.h"
|
#include "rnd.h"
|
||||||
@ -112,6 +112,17 @@ __KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.8 2002/08/24 19:00:31 martin Exp $")
|
|||||||
#include <net/if_ether.h>
|
#include <net/if_ether.h>
|
||||||
#include <net/if_bridgevar.h>
|
#include <net/if_bridgevar.h>
|
||||||
|
|
||||||
|
#ifdef BRIDGE_IPF /* Used for bridge_ip[6]_checkbasic */
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/in_systm.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/ip_var.h>
|
||||||
|
|
||||||
|
#include <netinet/ip6.h>
|
||||||
|
#include <netinet6/in6_var.h>
|
||||||
|
#include <netinet6/ip6_var.h>
|
||||||
|
#endif /* BRIDGE_IPF */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Size of the route hash table. Must be a power of two.
|
* Size of the route hash table. Must be a power of two.
|
||||||
*/
|
*/
|
||||||
@ -218,6 +229,15 @@ int bridge_ioctl_sfd(struct bridge_softc *, void *);
|
|||||||
int bridge_ioctl_gma(struct bridge_softc *, void *);
|
int bridge_ioctl_gma(struct bridge_softc *, void *);
|
||||||
int bridge_ioctl_sma(struct bridge_softc *, void *);
|
int bridge_ioctl_sma(struct bridge_softc *, void *);
|
||||||
int bridge_ioctl_sifprio(struct bridge_softc *, void *);
|
int bridge_ioctl_sifprio(struct bridge_softc *, void *);
|
||||||
|
#ifdef BRIDGE_IPF
|
||||||
|
int bridge_ioctl_gfilt(struct bridge_softc *, void *);
|
||||||
|
int bridge_ioctl_sfilt(struct bridge_softc *, void *);
|
||||||
|
static int bridge_ipf(void *, struct mbuf **, struct ifnet *, int);
|
||||||
|
static int bridge_ip_checkbasic(struct mbuf **mp);
|
||||||
|
# ifdef INET6
|
||||||
|
static int bridge_ip6_checkbasic(struct mbuf **mp);
|
||||||
|
# endif /* INET6 */
|
||||||
|
#endif /* BRIDGE_IPF */
|
||||||
|
|
||||||
struct bridge_control {
|
struct bridge_control {
|
||||||
int (*bc_func)(struct bridge_softc *, void *);
|
int (*bc_func)(struct bridge_softc *, void *);
|
||||||
@ -286,6 +306,12 @@ const struct bridge_control bridge_control_table[] = {
|
|||||||
|
|
||||||
{ bridge_ioctl_sifprio, sizeof(struct ifbreq),
|
{ bridge_ioctl_sifprio, sizeof(struct ifbreq),
|
||||||
BC_F_COPYIN|BC_F_SUSER },
|
BC_F_COPYIN|BC_F_SUSER },
|
||||||
|
#ifdef BRIDGE_IPF
|
||||||
|
{ bridge_ioctl_gfilt, sizeof(struct ifbrparam),
|
||||||
|
BC_F_COPYOUT },
|
||||||
|
{ bridge_ioctl_sfilt, sizeof(struct ifbrparam),
|
||||||
|
BC_F_COPYIN|BC_F_SUSER },
|
||||||
|
#endif /* BRIDGE_IPF */
|
||||||
};
|
};
|
||||||
const int bridge_control_table_size =
|
const int bridge_control_table_size =
|
||||||
sizeof(bridge_control_table) / sizeof(bridge_control_table[0]);
|
sizeof(bridge_control_table) / sizeof(bridge_control_table[0]);
|
||||||
@ -334,6 +360,7 @@ bridge_clone_create(struct if_clone *ifc, int unit)
|
|||||||
sc->sc_bridge_forward_delay = BSTP_DEFAULT_FORWARD_DELAY;
|
sc->sc_bridge_forward_delay = BSTP_DEFAULT_FORWARD_DELAY;
|
||||||
sc->sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
|
sc->sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
|
||||||
sc->sc_hold_time = BSTP_DEFAULT_HOLD_TIME;
|
sc->sc_hold_time = BSTP_DEFAULT_HOLD_TIME;
|
||||||
|
sc->sc_filter_flags = 0;
|
||||||
|
|
||||||
/* Initialize our routing table. */
|
/* Initialize our routing table. */
|
||||||
bridge_rtable_init(sc);
|
bridge_rtable_init(sc);
|
||||||
@ -953,6 +980,44 @@ bridge_ioctl_sifprio(struct bridge_softc *sc, void *arg)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BRIDGE_IPF
|
||||||
|
int
|
||||||
|
bridge_ioctl_gfilt(struct bridge_softc *sc, void *arg)
|
||||||
|
{
|
||||||
|
struct ifbrparam *param = arg;
|
||||||
|
|
||||||
|
param->ifbrp_filter = sc->sc_filter_flags;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
bridge_ioctl_sfilt(struct bridge_softc *sc, void *arg)
|
||||||
|
{
|
||||||
|
struct ifbrparam *param = arg;
|
||||||
|
uint32_t nflags, oflags;
|
||||||
|
|
||||||
|
if (param->ifbrp_filter & ~IFBF_FILT_MASK)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
nflags = param->ifbrp_filter;
|
||||||
|
oflags = sc->sc_filter_flags;
|
||||||
|
|
||||||
|
if ((nflags & IFBF_FILT_USEIPF) && !(oflags & IFBF_FILT_USEIPF)) {
|
||||||
|
pfil_add_hook((void *)bridge_ipf, NULL, PFIL_IN|PFIL_OUT,
|
||||||
|
&sc->sc_if.if_pfil);
|
||||||
|
}
|
||||||
|
if (!(nflags & IFBF_FILT_USEIPF) && (oflags & IFBF_FILT_USEIPF)) {
|
||||||
|
pfil_remove_hook((void *)bridge_ipf, NULL, PFIL_IN|PFIL_OUT,
|
||||||
|
&sc->sc_if.if_pfil);
|
||||||
|
}
|
||||||
|
|
||||||
|
sc->sc_filter_flags = nflags;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
#endif /* BRIDGE_IPF */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bridge_ifdetach:
|
* bridge_ifdetach:
|
||||||
*
|
*
|
||||||
@ -1028,6 +1093,15 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m)
|
|||||||
int len, error;
|
int len, error;
|
||||||
short mflags;
|
short mflags;
|
||||||
|
|
||||||
|
#ifdef PFIL_HOOKS
|
||||||
|
if (pfil_run_hooks(&sc->sc_if.if_pfil, &m, dst_ifp, PFIL_OUT) != 0) {
|
||||||
|
m_freem(m);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m == NULL)
|
||||||
|
return;
|
||||||
|
#endif /* PFIL_HOOKS */
|
||||||
|
|
||||||
#ifdef ALTQ
|
#ifdef ALTQ
|
||||||
/*
|
/*
|
||||||
* If ALTQ is enabled on the member interface, do
|
* If ALTQ is enabled on the member interface, do
|
||||||
@ -1271,6 +1345,15 @@ bridge_forward(struct bridge_softc *sc, struct mbuf *m)
|
|||||||
dst_if = NULL;
|
dst_if = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PFIL_HOOKS
|
||||||
|
if (pfil_run_hooks(&sc->sc_if.if_pfil, &m, m->m_pkthdr.rcvif, PFIL_IN) != 0) {
|
||||||
|
m_freem(m);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m == NULL)
|
||||||
|
return;
|
||||||
|
#endif /* PFIL_HOOKS */
|
||||||
|
|
||||||
if (dst_if == NULL) {
|
if (dst_if == NULL) {
|
||||||
bridge_broadcast(sc, src_if, m);
|
bridge_broadcast(sc, src_if, m);
|
||||||
return;
|
return;
|
||||||
@ -1801,3 +1884,271 @@ bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt)
|
|||||||
sc->sc_brtcnt--;
|
sc->sc_brtcnt--;
|
||||||
pool_put(&bridge_rtnode_pool, brt);
|
pool_put(&bridge_rtnode_pool, brt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BRIDGE_IPF
|
||||||
|
extern struct pfil_head inet_pfil_hook; /* XXX */
|
||||||
|
extern struct pfil_head inet6_pfil_hook; /* XXX */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send bridge packets through IPF if they are one of the types IPF can deal
|
||||||
|
* with, or if they are ARP or REVARP. (IPF will pass ARP and REVARP without
|
||||||
|
* question.)
|
||||||
|
*/
|
||||||
|
static int bridge_ipf(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
|
||||||
|
{
|
||||||
|
int snap, error;
|
||||||
|
struct ether_header *eh;
|
||||||
|
struct mbuf *m1, *m2;
|
||||||
|
u_int16_t ether_type;
|
||||||
|
|
||||||
|
snap = 0;
|
||||||
|
error = -1; /* Default error if not error == 0 */
|
||||||
|
eh = mtod(*mp, struct ether_header *);
|
||||||
|
ether_type = ntohs(eh->ether_type);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for SNAP/LLC.
|
||||||
|
*/
|
||||||
|
if (ether_type < ETHERMTU) {
|
||||||
|
struct llc *llc = (struct llc *)(eh + 1);
|
||||||
|
|
||||||
|
if ((*mp)->m_len >= ETHER_HDR_LEN + 8 &&
|
||||||
|
llc->llc_dsap == LLC_SNAP_LSAP &&
|
||||||
|
llc->llc_ssap == LLC_SNAP_LSAP &&
|
||||||
|
llc->llc_control == LLC_UI) {
|
||||||
|
ether_type = htons(llc->llc_un.type_snap.ether_type);
|
||||||
|
snap = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're trying to filter bridge traffic, don't look at anything
|
||||||
|
* other than IP and ARP traffic. If the filter doesn't understand
|
||||||
|
* IPv6, don't allow IPv6 through the bridge either. This is lame
|
||||||
|
* since if we really wanted, say, an AppleTalk filter, we are hosed,
|
||||||
|
* but of course we don't have an AppleTalk filter to begin with.
|
||||||
|
* (Note that since IPF doesn't understand ARP it will pass *ALL*
|
||||||
|
* ARP traffic.)
|
||||||
|
*/
|
||||||
|
switch (ether_type) {
|
||||||
|
case ETHERTYPE_ARP:
|
||||||
|
case ETHERTYPE_REVARP:
|
||||||
|
return 0; /* Automatically pass */
|
||||||
|
case ETHERTYPE_IP:
|
||||||
|
# ifdef INET6
|
||||||
|
case ETHERTYPE_IPV6:
|
||||||
|
# endif /* INET6 */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Strip off the Ethernet header---but keep a copy. */
|
||||||
|
if ((m1 = m_split(*mp, sizeof(struct ether_header), M_NOWAIT)) == NULL)
|
||||||
|
goto bad;
|
||||||
|
/* Strip off snap header, if present */
|
||||||
|
if (snap) {
|
||||||
|
if ((m2 = m_split(m1, sizeof(struct llc), M_NOWAIT)) == NULL)
|
||||||
|
goto bad2;
|
||||||
|
} else
|
||||||
|
m2 = m1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check basic packet sanity, if the packet is outbound, and
|
||||||
|
* run IPF filter.
|
||||||
|
*/
|
||||||
|
if (ether_type == ETHERTYPE_IP &&
|
||||||
|
(dir == PFIL_OUT || bridge_ip_checkbasic(&m2) == 0)) {
|
||||||
|
error = pfil_run_hooks(&inet_pfil_hook, &m2, ifp, dir);
|
||||||
|
if (error) goto bad2;
|
||||||
|
}
|
||||||
|
# ifdef INET6
|
||||||
|
if (ether_type == ETHERTYPE_IPV6 &&
|
||||||
|
(dir == PFIL_OUT || bridge_ip6_checkbasic(&m2) == 0)) {
|
||||||
|
error = pfil_run_hooks(&inet6_pfil_hook, &m2, ifp, dir);
|
||||||
|
if (error) goto bad2;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
if (m2 == NULL) goto bad2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finally, put everything back the way it was and return
|
||||||
|
*/
|
||||||
|
if (snap)
|
||||||
|
m_cat(m1, m2);
|
||||||
|
else
|
||||||
|
m1 = m2;
|
||||||
|
m_cat(*mp, m1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
bad2:
|
||||||
|
if (snap)
|
||||||
|
m_freem(m1);
|
||||||
|
m_freem(m2);
|
||||||
|
bad:
|
||||||
|
m_freem(*mp);
|
||||||
|
*mp = NULL;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform basic checks on header size since
|
||||||
|
* IPF assumes ip_input has already processed
|
||||||
|
* it for it. Cut-and-pasted from ip_input.c.
|
||||||
|
* Given how simple the IPv6 version is,
|
||||||
|
* does the IPv4 version really need to be
|
||||||
|
* this complicated?
|
||||||
|
*
|
||||||
|
* XXX Should we update ipstat here, or not?
|
||||||
|
* XXX Right now we update ipstat but not
|
||||||
|
* XXX csum_counter.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
bridge_ip_checkbasic(struct mbuf **mp)
|
||||||
|
{
|
||||||
|
struct mbuf *m = *mp;
|
||||||
|
struct ip *ip;
|
||||||
|
int len, hlen;
|
||||||
|
|
||||||
|
if (*mp == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (IP_HDR_ALIGNED_P(mtod(m, caddr_t)) == 0) {
|
||||||
|
if ((m = m_copyup(m, sizeof(struct ip),
|
||||||
|
(max_linkhdr + 3) & ~3)) == NULL) {
|
||||||
|
/* XXXJRT new stat, please */
|
||||||
|
ipstat.ips_toosmall++;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
} else if (__predict_false(m->m_len < sizeof (struct ip))) {
|
||||||
|
if ((m = m_pullup(m, sizeof (struct ip))) == NULL) {
|
||||||
|
ipstat.ips_toosmall++;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ip = mtod(m, struct ip *);
|
||||||
|
if (ip == NULL) goto bad;
|
||||||
|
|
||||||
|
if (ip->ip_v != IPVERSION) {
|
||||||
|
ipstat.ips_badvers++;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
hlen = ip->ip_hl << 2;
|
||||||
|
if (hlen < sizeof(struct ip)) { /* minimum header length */
|
||||||
|
ipstat.ips_badhlen++;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
if (hlen > m->m_len) {
|
||||||
|
if ((m = m_pullup(m, hlen)) == 0) {
|
||||||
|
ipstat.ips_badhlen++;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
ip = mtod(m, struct ip *);
|
||||||
|
if (ip == NULL) goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (m->m_pkthdr.csum_flags &
|
||||||
|
((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_IPv4) |
|
||||||
|
M_CSUM_IPv4_BAD)) {
|
||||||
|
case M_CSUM_IPv4|M_CSUM_IPv4_BAD:
|
||||||
|
/* INET_CSUM_COUNTER_INCR(&ip_hwcsum_bad); */
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
case M_CSUM_IPv4:
|
||||||
|
/* Checksum was okay. */
|
||||||
|
/* INET_CSUM_COUNTER_INCR(&ip_hwcsum_ok); */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Must compute it ourselves. */
|
||||||
|
/* INET_CSUM_COUNTER_INCR(&ip_swcsum); */
|
||||||
|
if (in_cksum(m, hlen) != 0)
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve the packet length. */
|
||||||
|
len = ntohs(ip->ip_len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for additional length bogosity
|
||||||
|
*/
|
||||||
|
if (len < hlen) {
|
||||||
|
ipstat.ips_badlen++;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the amount of data in the buffers
|
||||||
|
* is as at least much as the IP header would have us expect.
|
||||||
|
* Drop packet if shorter than we expect.
|
||||||
|
*/
|
||||||
|
if (m->m_pkthdr.len < len) {
|
||||||
|
ipstat.ips_tooshort++;
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checks out, proceed */
|
||||||
|
*mp = m;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
*mp = m;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef INET6
|
||||||
|
/*
|
||||||
|
* Same as above, but for IPv6.
|
||||||
|
* Cut-and-pasted from ip6_input.c.
|
||||||
|
* XXX Should we update ip6stat, or not?
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
bridge_ip6_checkbasic(struct mbuf **mp)
|
||||||
|
{
|
||||||
|
struct mbuf *m = *mp;
|
||||||
|
struct ip6 *ip6;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the IPv6 header is not aligned, slurp it up into a new
|
||||||
|
* mbuf with space for link headers, in the event we forward
|
||||||
|
* it. Otherwise, if it is aligned, make sure the entire base
|
||||||
|
* IPv6 header is in the first mbuf of the chain.
|
||||||
|
*/
|
||||||
|
if (IP6_HDR_ALIGNED_P(mtod(m, caddr_t)) == 0) {
|
||||||
|
struct ifnet *inifp = m->m_pkthdr.rcvif;
|
||||||
|
if ((m = m_copyup(m, sizeof(struct ip6_hdr),
|
||||||
|
(max_linkhdr + 3) & ~3)) == NULL) {
|
||||||
|
/* XXXJRT new stat, please */
|
||||||
|
ip6stat.ip6s_toosmall++;
|
||||||
|
in6_ifstat_inc(inifp, ifs6_in_hdrerr);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
} else if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) {
|
||||||
|
struct ifnet *inifp = m->m_pkthdr.rcvif;
|
||||||
|
if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
|
||||||
|
ip6stat.ip6s_toosmall++;
|
||||||
|
in6_ifstat_inc(inifp, ifs6_in_hdrerr);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ip6 = mtod(m, struct ip6_hdr *);
|
||||||
|
|
||||||
|
if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
|
||||||
|
ip6stat.ip6s_badvers++;
|
||||||
|
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checks out, proceed */
|
||||||
|
*mp = m;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
*mp = m;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
# endif /* INET6 */
|
||||||
|
#endif /* BRIDGE_IPF */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: if_bridgevar.h,v 1.1 2001/08/17 21:37:28 thorpej Exp $ */
|
/* $NetBSD: if_bridgevar.h,v 1.2 2003/02/15 00:46:30 perseant Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2001 Wasabi Systems, Inc.
|
* Copyright 2001 Wasabi Systems, Inc.
|
||||||
@ -102,6 +102,8 @@
|
|||||||
#define BRDGGMA 19 /* get max age (ifbrparam) */
|
#define BRDGGMA 19 /* get max age (ifbrparam) */
|
||||||
#define BRDGSMA 20 /* set max age (ifbrparam) */
|
#define BRDGSMA 20 /* set max age (ifbrparam) */
|
||||||
#define BRDGSIFPRIO 21 /* set if priority (ifbreq) */
|
#define BRDGSIFPRIO 21 /* set if priority (ifbreq) */
|
||||||
|
#define BRDGGFILT 22 /* get filter flags (ifbrparam) */
|
||||||
|
#define BRDGSFILT 23 /* set filter flags (ifbrparam) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generic bridge control request.
|
* Generic bridge control request.
|
||||||
@ -125,6 +127,10 @@ struct ifbreq {
|
|||||||
#define IFBF_FLUSHDYN 0x00 /* flush learned addresses only */
|
#define IFBF_FLUSHDYN 0x00 /* flush learned addresses only */
|
||||||
#define IFBF_FLUSHALL 0x01 /* flush all addresses */
|
#define IFBF_FLUSHALL 0x01 /* flush all addresses */
|
||||||
|
|
||||||
|
/* BRDGSFILT */
|
||||||
|
#define IFBF_FILT_USEIPF 0x00000001 /* enable ipf on bridge */
|
||||||
|
#define IFBF_FILT_MASK 0x00000001 /* mask of valid values */
|
||||||
|
|
||||||
/* STP port states */
|
/* STP port states */
|
||||||
#define BSTP_IFSTATE_DISABLED 0
|
#define BSTP_IFSTATE_DISABLED 0
|
||||||
#define BSTP_IFSTATE_LISTENING 1
|
#define BSTP_IFSTATE_LISTENING 1
|
||||||
@ -190,6 +196,7 @@ struct ifbrparam {
|
|||||||
#define ifbrp_hellotime ifbrp_ifbrpu.ifbrpu_int8 /* hello time (sec) */
|
#define ifbrp_hellotime ifbrp_ifbrpu.ifbrpu_int8 /* hello time (sec) */
|
||||||
#define ifbrp_fwddelay ifbrp_ifbrpu.ifbrpu_int8 /* fwd time (sec) */
|
#define ifbrp_fwddelay ifbrp_ifbrpu.ifbrpu_int8 /* fwd time (sec) */
|
||||||
#define ifbrp_maxage ifbrp_ifbrpu.ifbrpu_int8 /* max age (sec) */
|
#define ifbrp_maxage ifbrp_ifbrpu.ifbrpu_int8 /* max age (sec) */
|
||||||
|
#define ifbrp_filter ifbrp_ifbrpu.ifbrpu_int32 /* filtering flags */
|
||||||
|
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
/*
|
/*
|
||||||
@ -287,6 +294,7 @@ struct bridge_softc {
|
|||||||
LIST_HEAD(, bridge_rtnode) *sc_rthash; /* our forwarding table */
|
LIST_HEAD(, bridge_rtnode) *sc_rthash; /* our forwarding table */
|
||||||
LIST_HEAD(, bridge_rtnode) sc_rtlist; /* list version of above */
|
LIST_HEAD(, bridge_rtnode) sc_rtlist; /* list version of above */
|
||||||
uint32_t sc_rthash_key; /* key for hash */
|
uint32_t sc_rthash_key; /* key for hash */
|
||||||
|
uint32_t sc_filter_flags; /* ipf and flags */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const uint8_t bstp_etheraddr[];
|
extern const uint8_t bstp_etheraddr[];
|
||||||
|
Loading…
Reference in New Issue
Block a user