mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-10-14 18:41:59 +08:00
Update to FreeBSD head 2016-08-23
Git mirror commit 9fe7c416e6abb28b1398fd3e5687099846800cfd.
This commit is contained in:
@@ -73,7 +73,7 @@
|
||||
* - Currently only supports Ethernet-like interfaces (Ethernet,
|
||||
* 802.11, VLANs on Ethernet, etc.) Figure out a nice way
|
||||
* to bridge other types of interfaces (FDDI-FDDI, and maybe
|
||||
* consider heterogenous bridges).
|
||||
* consider heterogeneous bridges).
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
@@ -83,6 +83,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <rtems/bsd/local/opt_inet6.h>
|
||||
|
||||
#include <rtems/bsd/sys/param.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/protosw.h>
|
||||
@@ -102,7 +103,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/proc.h>
|
||||
#include <rtems/bsd/sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rwlock.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
@@ -113,7 +113,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/pfil.h>
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <netinet/in.h> /* for struct arpcom */
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip.h>
|
||||
@@ -127,15 +127,13 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/ip_carp.h>
|
||||
#endif
|
||||
#include <machine/in_cksum.h>
|
||||
#include <netinet/if_ether.h> /* for struct arpcom */
|
||||
#include <netinet/if_ether.h>
|
||||
#include <net/bridgestp.h>
|
||||
#include <net/if_bridgevar.h>
|
||||
#include <net/if_llc.h>
|
||||
#include <net/if_vlan_var.h>
|
||||
|
||||
#include <net/route.h>
|
||||
#include <netinet/ip_fw.h>
|
||||
#include <netpfil/ipfw/ip_fw_private.h>
|
||||
|
||||
/*
|
||||
* Size of the route hash table. Must be a power of two.
|
||||
@@ -170,7 +168,8 @@ __FBSDID("$FreeBSD$");
|
||||
/*
|
||||
* List of capabilities to possibly mask on the member interface.
|
||||
*/
|
||||
#define BRIDGE_IFCAPS_MASK (IFCAP_TOE|IFCAP_TSO|IFCAP_TXCSUM)
|
||||
#define BRIDGE_IFCAPS_MASK (IFCAP_TOE|IFCAP_TSO|IFCAP_TXCSUM|\
|
||||
IFCAP_TXCSUM_IPV6)
|
||||
|
||||
/*
|
||||
* List of capabilities to strip
|
||||
@@ -230,8 +229,9 @@ struct bridge_softc {
|
||||
u_char sc_defaddr[6]; /* Default MAC address */
|
||||
};
|
||||
|
||||
static struct mtx bridge_list_mtx;
|
||||
eventhandler_tag bridge_detach_cookie = NULL;
|
||||
static VNET_DEFINE(struct mtx, bridge_list_mtx);
|
||||
#define V_bridge_list_mtx VNET(bridge_list_mtx)
|
||||
static eventhandler_tag bridge_detach_cookie;
|
||||
|
||||
int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD;
|
||||
|
||||
@@ -248,11 +248,12 @@ static void bridge_ifdetach(void *arg __unused, struct ifnet *);
|
||||
static void bridge_init(void *);
|
||||
static void bridge_dummynet(struct mbuf *, struct ifnet *);
|
||||
static void bridge_stop(struct ifnet *, int);
|
||||
static void bridge_start(struct ifnet *);
|
||||
static int bridge_transmit(struct ifnet *, struct mbuf *);
|
||||
static void bridge_qflush(struct ifnet *);
|
||||
static struct mbuf *bridge_input(struct ifnet *, struct mbuf *);
|
||||
static int bridge_output(struct ifnet *, struct mbuf *, struct sockaddr *,
|
||||
struct rtentry *);
|
||||
static void bridge_enqueue(struct bridge_softc *, struct ifnet *,
|
||||
static int bridge_enqueue(struct bridge_softc *, struct ifnet *,
|
||||
struct mbuf *);
|
||||
static void bridge_rtdelete(struct bridge_softc *, struct ifnet *ifp, int);
|
||||
|
||||
@@ -275,7 +276,7 @@ static void bridge_rtflush(struct bridge_softc *, int);
|
||||
static int bridge_rtdaddr(struct bridge_softc *, const uint8_t *,
|
||||
uint16_t);
|
||||
|
||||
static int bridge_rtable_init(struct bridge_softc *);
|
||||
static void bridge_rtable_init(struct bridge_softc *);
|
||||
static void bridge_rtable_fini(struct bridge_softc *);
|
||||
|
||||
static int bridge_rtnode_addr_cmp(const uint8_t *, const uint8_t *);
|
||||
@@ -353,43 +354,64 @@ static struct bstp_cb_ops bridge_ops = {
|
||||
SYSCTL_DECL(_net_link);
|
||||
static SYSCTL_NODE(_net_link, IFT_BRIDGE, bridge, CTLFLAG_RW, 0, "Bridge");
|
||||
|
||||
static int pfil_onlyip = 1; /* only pass IP[46] packets when pfil is enabled */
|
||||
static int pfil_bridge = 1; /* run pfil hooks on the bridge interface */
|
||||
static int pfil_member = 1; /* run pfil hooks on the member interface */
|
||||
static int pfil_ipfw = 0; /* layer2 filter with ipfw */
|
||||
static int pfil_ipfw_arp = 0; /* layer2 filter with ipfw */
|
||||
static int pfil_local_phys = 0; /* run pfil hooks on the physical interface for
|
||||
locally destined packets */
|
||||
static int log_stp = 0; /* log STP state changes */
|
||||
static int bridge_inherit_mac = 0; /* share MAC with first bridge member */
|
||||
TUNABLE_INT("net.link.bridge.pfil_onlyip", &pfil_onlyip);
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_onlyip, CTLFLAG_RW,
|
||||
&pfil_onlyip, 0, "Only pass IP packets when pfil is enabled");
|
||||
TUNABLE_INT("net.link.bridge.ipfw_arp", &pfil_ipfw_arp);
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, ipfw_arp, CTLFLAG_RW,
|
||||
&pfil_ipfw_arp, 0, "Filter ARP packets through IPFW layer2");
|
||||
TUNABLE_INT("net.link.bridge.pfil_bridge", &pfil_bridge);
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_bridge, CTLFLAG_RW,
|
||||
&pfil_bridge, 0, "Packet filter on the bridge interface");
|
||||
TUNABLE_INT("net.link.bridge.pfil_member", &pfil_member);
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_member, CTLFLAG_RW,
|
||||
&pfil_member, 0, "Packet filter on the member interface");
|
||||
TUNABLE_INT("net.link.bridge.pfil_local_phys", &pfil_local_phys);
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_local_phys, CTLFLAG_RW,
|
||||
&pfil_local_phys, 0,
|
||||
/* only pass IP[46] packets when pfil is enabled */
|
||||
static VNET_DEFINE(int, pfil_onlyip) = 1;
|
||||
#define V_pfil_onlyip VNET(pfil_onlyip)
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_onlyip,
|
||||
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_onlyip), 0,
|
||||
"Only pass IP packets when pfil is enabled");
|
||||
|
||||
/* run pfil hooks on the bridge interface */
|
||||
static VNET_DEFINE(int, pfil_bridge) = 1;
|
||||
#define V_pfil_bridge VNET(pfil_bridge)
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_bridge,
|
||||
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_bridge), 0,
|
||||
"Packet filter on the bridge interface");
|
||||
|
||||
/* layer2 filter with ipfw */
|
||||
static VNET_DEFINE(int, pfil_ipfw);
|
||||
#define V_pfil_ipfw VNET(pfil_ipfw)
|
||||
|
||||
/* layer2 ARP filter with ipfw */
|
||||
static VNET_DEFINE(int, pfil_ipfw_arp);
|
||||
#define V_pfil_ipfw_arp VNET(pfil_ipfw_arp)
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, ipfw_arp,
|
||||
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_ipfw_arp), 0,
|
||||
"Filter ARP packets through IPFW layer2");
|
||||
|
||||
/* run pfil hooks on the member interface */
|
||||
static VNET_DEFINE(int, pfil_member) = 1;
|
||||
#define V_pfil_member VNET(pfil_member)
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_member,
|
||||
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_member), 0,
|
||||
"Packet filter on the member interface");
|
||||
|
||||
/* run pfil hooks on the physical interface for locally destined packets */
|
||||
static VNET_DEFINE(int, pfil_local_phys);
|
||||
#define V_pfil_local_phys VNET(pfil_local_phys)
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_local_phys,
|
||||
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(pfil_local_phys), 0,
|
||||
"Packet filter on the physical interface for locally destined packets");
|
||||
TUNABLE_INT("net.link.bridge.log_stp", &log_stp);
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, log_stp, CTLFLAG_RW,
|
||||
&log_stp, 0, "Log STP state changes");
|
||||
TUNABLE_INT("net.link.bridge.inherit_mac", &bridge_inherit_mac);
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, inherit_mac, CTLFLAG_RW,
|
||||
&bridge_inherit_mac, 0,
|
||||
|
||||
/* log STP state changes */
|
||||
static VNET_DEFINE(int, log_stp);
|
||||
#define V_log_stp VNET(log_stp)
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, log_stp,
|
||||
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(log_stp), 0,
|
||||
"Log STP state changes");
|
||||
|
||||
/* share MAC with first bridge member */
|
||||
static VNET_DEFINE(int, bridge_inherit_mac);
|
||||
#define V_bridge_inherit_mac VNET(bridge_inherit_mac)
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, inherit_mac,
|
||||
CTLFLAG_RWTUN | CTLFLAG_VNET, &VNET_NAME(bridge_inherit_mac), 0,
|
||||
"Inherit MAC address from the first bridge member");
|
||||
|
||||
static VNET_DEFINE(int, allow_llz_overlap) = 0;
|
||||
#define V_allow_llz_overlap VNET(allow_llz_overlap)
|
||||
SYSCTL_VNET_INT(_net_link_bridge, OID_AUTO, allow_llz_overlap, CTLFLAG_RW,
|
||||
&VNET_NAME(allow_llz_overlap), 0, "Allow overlap of link-local scope "
|
||||
SYSCTL_INT(_net_link_bridge, OID_AUTO, allow_llz_overlap,
|
||||
CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_VNET, &VNET_NAME(allow_llz_overlap), 0,
|
||||
"Allow overlap of link-local scope "
|
||||
"zones of a bridge interface and the member interfaces");
|
||||
|
||||
struct bridge_control {
|
||||
@@ -487,12 +509,43 @@ const struct bridge_control bridge_control_table[] = {
|
||||
BC_F_COPYIN|BC_F_SUSER },
|
||||
|
||||
};
|
||||
const int bridge_control_table_size =
|
||||
sizeof(bridge_control_table) / sizeof(bridge_control_table[0]);
|
||||
const int bridge_control_table_size = nitems(bridge_control_table);
|
||||
|
||||
LIST_HEAD(, bridge_softc) bridge_list;
|
||||
static VNET_DEFINE(LIST_HEAD(, bridge_softc), bridge_list);
|
||||
#define V_bridge_list VNET(bridge_list)
|
||||
#define BRIDGE_LIST_LOCK_INIT(x) mtx_init(&V_bridge_list_mtx, \
|
||||
"if_bridge list", NULL, MTX_DEF)
|
||||
#define BRIDGE_LIST_LOCK_DESTROY(x) mtx_destroy(&V_bridge_list_mtx)
|
||||
#define BRIDGE_LIST_LOCK(x) mtx_lock(&V_bridge_list_mtx)
|
||||
#define BRIDGE_LIST_UNLOCK(x) mtx_unlock(&V_bridge_list_mtx)
|
||||
|
||||
IFC_SIMPLE_DECLARE(bridge, 0);
|
||||
static VNET_DEFINE(struct if_clone *, bridge_cloner);
|
||||
#define V_bridge_cloner VNET(bridge_cloner)
|
||||
|
||||
static const char bridge_name[] = "bridge";
|
||||
|
||||
static void
|
||||
vnet_bridge_init(const void *unused __unused)
|
||||
{
|
||||
|
||||
BRIDGE_LIST_LOCK_INIT();
|
||||
LIST_INIT(&V_bridge_list);
|
||||
V_bridge_cloner = if_clone_simple(bridge_name,
|
||||
bridge_clone_create, bridge_clone_destroy, 0);
|
||||
}
|
||||
VNET_SYSINIT(vnet_bridge_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
|
||||
vnet_bridge_init, NULL);
|
||||
|
||||
static void
|
||||
vnet_bridge_uninit(const void *unused __unused)
|
||||
{
|
||||
|
||||
if_clone_detach(V_bridge_cloner);
|
||||
V_bridge_cloner = NULL;
|
||||
BRIDGE_LIST_LOCK_DESTROY();
|
||||
}
|
||||
VNET_SYSUNINIT(vnet_bridge_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY,
|
||||
vnet_bridge_uninit, NULL);
|
||||
|
||||
static int
|
||||
bridge_modevent(module_t mod, int type, void *data)
|
||||
@@ -500,12 +553,9 @@ bridge_modevent(module_t mod, int type, void *data)
|
||||
|
||||
switch (type) {
|
||||
case MOD_LOAD:
|
||||
mtx_init(&bridge_list_mtx, "if_bridge list", NULL, MTX_DEF);
|
||||
if_clone_attach(&bridge_cloner);
|
||||
bridge_rtnode_zone = uma_zcreate("bridge_rtnode",
|
||||
sizeof(struct bridge_rtnode), NULL, NULL, NULL, NULL,
|
||||
UMA_ALIGN_PTR, 0);
|
||||
LIST_INIT(&bridge_list);
|
||||
bridge_input_p = bridge_input;
|
||||
bridge_output_p = bridge_output;
|
||||
bridge_dn_p = bridge_dummynet;
|
||||
@@ -517,13 +567,11 @@ bridge_modevent(module_t mod, int type, void *data)
|
||||
case MOD_UNLOAD:
|
||||
EVENTHANDLER_DEREGISTER(ifnet_departure_event,
|
||||
bridge_detach_cookie);
|
||||
if_clone_detach(&bridge_cloner);
|
||||
uma_zdestroy(bridge_rtnode_zone);
|
||||
bridge_input_p = NULL;
|
||||
bridge_output_p = NULL;
|
||||
bridge_dn_p = NULL;
|
||||
bridge_linkstate_p = NULL;
|
||||
mtx_destroy(&bridge_list_mtx);
|
||||
break;
|
||||
default:
|
||||
return (EOPNOTSUPP);
|
||||
@@ -541,19 +589,19 @@ DECLARE_MODULE(if_bridge, bridge_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
|
||||
MODULE_DEPEND(if_bridge, bridgestp, 1, 1, 1);
|
||||
|
||||
/*
|
||||
* handler for net.link.bridge.pfil_ipfw
|
||||
* handler for net.link.bridge.ipfw
|
||||
*/
|
||||
static int
|
||||
sysctl_pfil_ipfw(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
int enable = pfil_ipfw;
|
||||
int enable = V_pfil_ipfw;
|
||||
int error;
|
||||
|
||||
error = sysctl_handle_int(oidp, &enable, 0, req);
|
||||
enable = (enable) ? 1 : 0;
|
||||
enable &= 1;
|
||||
|
||||
if (enable != pfil_ipfw) {
|
||||
pfil_ipfw = enable;
|
||||
if (enable != V_pfil_ipfw) {
|
||||
V_pfil_ipfw = enable;
|
||||
|
||||
/*
|
||||
* Disable pfil so that ipfw doesnt run twice, if the user
|
||||
@@ -561,17 +609,19 @@ sysctl_pfil_ipfw(SYSCTL_HANDLER_ARGS)
|
||||
* pfil_member. Also allow non-ip packets as ipfw can filter by
|
||||
* layer2 type.
|
||||
*/
|
||||
if (pfil_ipfw) {
|
||||
pfil_onlyip = 0;
|
||||
pfil_bridge = 0;
|
||||
pfil_member = 0;
|
||||
if (V_pfil_ipfw) {
|
||||
V_pfil_onlyip = 0;
|
||||
V_pfil_bridge = 0;
|
||||
V_pfil_member = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
SYSCTL_PROC(_net_link_bridge, OID_AUTO, ipfw, CTLTYPE_INT|CTLFLAG_RW,
|
||||
&pfil_ipfw, 0, &sysctl_pfil_ipfw, "I", "Layer2 filter with IPFW");
|
||||
SYSCTL_PROC(_net_link_bridge, OID_AUTO, ipfw,
|
||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_VNET,
|
||||
&VNET_NAME(pfil_ipfw), 0, &sysctl_pfil_ipfw, "I",
|
||||
"Layer2 filter with IPFW");
|
||||
|
||||
/*
|
||||
* bridge_clone_create:
|
||||
@@ -606,15 +656,13 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
|
||||
LIST_INIT(&sc->sc_spanlist);
|
||||
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, ifc->ifc_name, unit);
|
||||
if_initname(ifp, bridge_name, unit);
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_ioctl = bridge_ioctl;
|
||||
ifp->if_start = bridge_start;
|
||||
ifp->if_transmit = bridge_transmit;
|
||||
ifp->if_qflush = bridge_qflush;
|
||||
ifp->if_init = bridge_init;
|
||||
ifp->if_type = IFT_BRIDGE;
|
||||
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||
IFQ_SET_READY(&ifp->if_snd);
|
||||
|
||||
/*
|
||||
* Generate an ethernet address with a locally administered address.
|
||||
@@ -626,7 +674,7 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
|
||||
*/
|
||||
fb = 0;
|
||||
getcredhostid(curthread->td_ucred, &hostid);
|
||||
for (retry = 1; retry != 0;) {
|
||||
do {
|
||||
if (fb || hostid == 0) {
|
||||
arc4rand(sc->sc_defaddr, ETHER_ADDR_LEN, 1);
|
||||
sc->sc_defaddr[0] &= ~1;/* clear multicast bit */
|
||||
@@ -642,15 +690,17 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
|
||||
|
||||
fb = 1;
|
||||
retry = 0;
|
||||
mtx_lock(&bridge_list_mtx);
|
||||
LIST_FOREACH(sc2, &bridge_list, sc_list) {
|
||||
BRIDGE_LIST_LOCK();
|
||||
LIST_FOREACH(sc2, &V_bridge_list, sc_list) {
|
||||
bifp = sc2->sc_ifp;
|
||||
if (memcmp(sc->sc_defaddr,
|
||||
IF_LLADDR(bifp), ETHER_ADDR_LEN) == 0)
|
||||
IF_LLADDR(bifp), ETHER_ADDR_LEN) == 0) {
|
||||
retry = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mtx_unlock(&bridge_list_mtx);
|
||||
}
|
||||
BRIDGE_LIST_UNLOCK();
|
||||
} while (retry == 1);
|
||||
|
||||
bstp_attach(&sc->sc_stp, &bridge_ops);
|
||||
ether_ifattach(ifp, sc->sc_defaddr);
|
||||
@@ -658,9 +708,9 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
|
||||
ifp->if_baudrate = 0;
|
||||
ifp->if_type = IFT_BRIDGE;
|
||||
|
||||
mtx_lock(&bridge_list_mtx);
|
||||
LIST_INSERT_HEAD(&bridge_list, sc, sc_list);
|
||||
mtx_unlock(&bridge_list_mtx);
|
||||
BRIDGE_LIST_LOCK();
|
||||
LIST_INSERT_HEAD(&V_bridge_list, sc, sc_list);
|
||||
BRIDGE_LIST_UNLOCK();
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -692,13 +742,13 @@ bridge_clone_destroy(struct ifnet *ifp)
|
||||
|
||||
callout_drain(&sc->sc_brcallout);
|
||||
|
||||
mtx_lock(&bridge_list_mtx);
|
||||
BRIDGE_LIST_LOCK();
|
||||
LIST_REMOVE(sc, sc_list);
|
||||
mtx_unlock(&bridge_list_mtx);
|
||||
BRIDGE_LIST_UNLOCK();
|
||||
|
||||
bstp_detach(&sc->sc_stp);
|
||||
ether_ifdetach(ifp);
|
||||
if_free_type(ifp, IFT_ETHER);
|
||||
if_free(ifp);
|
||||
|
||||
/* Tear down the routing table. */
|
||||
bridge_rtable_fini(sc);
|
||||
@@ -818,7 +868,7 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
BRIDGE_LOCK(sc);
|
||||
LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
|
||||
if (bif->bif_ifp->if_mtu != ifr->ifr_mtu) {
|
||||
log(LOG_NOTICE, "%s: invalid MTU: %lu(%s)"
|
||||
log(LOG_NOTICE, "%s: invalid MTU: %u(%s)"
|
||||
" != %d\n", sc->sc_ifp->if_xname,
|
||||
bif->bif_ifp->if_mtu,
|
||||
bif->bif_ifp->if_xname, ifr->ifr_mtu);
|
||||
@@ -960,7 +1010,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif,
|
||||
* the mac address of the bridge to the address of the next member, or
|
||||
* to its default address if no members are left.
|
||||
*/
|
||||
if (bridge_inherit_mac && sc->sc_ifaddr == ifs) {
|
||||
if (V_bridge_inherit_mac && sc->sc_ifaddr == ifs) {
|
||||
if (LIST_EMPTY(&sc->sc_iflist)) {
|
||||
bcopy(sc->sc_defaddr,
|
||||
IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN);
|
||||
@@ -986,9 +1036,12 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif,
|
||||
case IFT_ETHER:
|
||||
case IFT_L2VLAN:
|
||||
/*
|
||||
* Take the interface out of promiscuous mode.
|
||||
* Take the interface out of promiscuous mode, but only
|
||||
* if it was promiscuous in the first place. It might
|
||||
* not be if we're in the bridge_ioctl_add() error path.
|
||||
*/
|
||||
(void) ifpromisc(ifs, 0);
|
||||
if (ifs->if_flags & IFF_PROMISC)
|
||||
(void) ifpromisc(ifs, 0);
|
||||
break;
|
||||
|
||||
case IFT_GIF:
|
||||
@@ -1108,7 +1161,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
|
||||
if (LIST_EMPTY(&sc->sc_iflist))
|
||||
sc->sc_ifp->if_mtu = ifs->if_mtu;
|
||||
else if (sc->sc_ifp->if_mtu != ifs->if_mtu) {
|
||||
if_printf(sc->sc_ifp, "invalid MTU: %lu(%s) != %lu\n",
|
||||
if_printf(sc->sc_ifp, "invalid MTU: %u(%s) != %u\n",
|
||||
ifs->if_mtu, ifs->if_xname, sc->sc_ifp->if_mtu);
|
||||
return (EINVAL);
|
||||
}
|
||||
@@ -1126,7 +1179,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
|
||||
* member and the MAC address of the bridge has not been changed from
|
||||
* the default randomly generated one.
|
||||
*/
|
||||
if (bridge_inherit_mac && LIST_EMPTY(&sc->sc_iflist) &&
|
||||
if (V_bridge_inherit_mac && LIST_EMPTY(&sc->sc_iflist) &&
|
||||
!memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr, ETHER_ADDR_LEN)) {
|
||||
bcopy(IF_LLADDR(ifs), IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN);
|
||||
sc->sc_ifaddr = ifs;
|
||||
@@ -1156,10 +1209,8 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
if (error)
|
||||
bridge_delete_member(sc, bif, 0);
|
||||
free(bif, M_DEVBUF);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
@@ -1751,7 +1802,13 @@ bridge_ifdetach(void *arg __unused, struct ifnet *ifp)
|
||||
|
||||
if (ifp->if_flags & IFF_RENAMING)
|
||||
return;
|
||||
|
||||
if (V_bridge_cloner == NULL) {
|
||||
/*
|
||||
* This detach handler can be called after
|
||||
* vnet_bridge_uninit(). Just return in that case.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
/* Check if the interface is a bridge member */
|
||||
if (sc != NULL) {
|
||||
BRIDGE_LOCK(sc);
|
||||
@@ -1765,8 +1822,8 @@ bridge_ifdetach(void *arg __unused, struct ifnet *ifp)
|
||||
}
|
||||
|
||||
/* Check if the interface is a span port */
|
||||
mtx_lock(&bridge_list_mtx);
|
||||
LIST_FOREACH(sc, &bridge_list, sc_list) {
|
||||
BRIDGE_LIST_LOCK();
|
||||
LIST_FOREACH(sc, &V_bridge_list, sc_list) {
|
||||
BRIDGE_LOCK(sc);
|
||||
LIST_FOREACH(bif, &sc->sc_spanlist, bif_next)
|
||||
if (ifp == bif->bif_ifp) {
|
||||
@@ -1776,7 +1833,7 @@ bridge_ifdetach(void *arg __unused, struct ifnet *ifp)
|
||||
|
||||
BRIDGE_UNLOCK(sc);
|
||||
}
|
||||
mtx_unlock(&bridge_list_mtx);
|
||||
BRIDGE_LIST_UNLOCK();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1832,20 +1889,19 @@ bridge_stop(struct ifnet *ifp, int disable)
|
||||
* Enqueue a packet on a bridge member interface.
|
||||
*
|
||||
*/
|
||||
static void
|
||||
static int
|
||||
bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m)
|
||||
{
|
||||
int len, err = 0;
|
||||
short mflags;
|
||||
struct mbuf *m0;
|
||||
|
||||
len = m->m_pkthdr.len;
|
||||
mflags = m->m_flags;
|
||||
|
||||
/* We may be sending a fragment so traverse the mbuf */
|
||||
for (; m; m = m0) {
|
||||
m0 = m->m_nextpkt;
|
||||
m->m_nextpkt = NULL;
|
||||
len = m->m_pkthdr.len;
|
||||
mflags = m->m_flags;
|
||||
|
||||
/*
|
||||
* If underlying interface can not do VLAN tag insertion itself
|
||||
@@ -1857,7 +1913,7 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m)
|
||||
if (m == NULL) {
|
||||
if_printf(dst_ifp,
|
||||
"unable to prepend VLAN header\n");
|
||||
dst_ifp->if_oerrors++;
|
||||
if_inc_counter(dst_ifp, IFCOUNTER_OERRORS, 1);
|
||||
continue;
|
||||
}
|
||||
m->m_flags &= ~M_VLANTAG;
|
||||
@@ -1865,16 +1921,17 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m)
|
||||
|
||||
if ((err = dst_ifp->if_transmit(dst_ifp, m))) {
|
||||
m_freem(m0);
|
||||
if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if_inc_counter(sc->sc_ifp, IFCOUNTER_OPACKETS, 1);
|
||||
if_inc_counter(sc->sc_ifp, IFCOUNTER_OBYTES, len);
|
||||
if (mflags & M_MCAST)
|
||||
if_inc_counter(sc->sc_ifp, IFCOUNTER_OMCASTS, 1);
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
sc->sc_ifp->if_opackets++;
|
||||
sc->sc_ifp->if_obytes += len;
|
||||
if (mflags & M_MCAST)
|
||||
sc->sc_ifp->if_omcasts++;
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2000,9 +2057,9 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
|
||||
used = 1;
|
||||
mc = m;
|
||||
} else {
|
||||
mc = m_copypacket(m, M_DONTWAIT);
|
||||
mc = m_copypacket(m, M_NOWAIT);
|
||||
if (mc == NULL) {
|
||||
sc->sc_ifp->if_oerrors++;
|
||||
if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -2033,44 +2090,42 @@ sendunicast:
|
||||
}
|
||||
|
||||
/*
|
||||
* bridge_start:
|
||||
* bridge_transmit:
|
||||
*
|
||||
* Start output on a bridge.
|
||||
* Do output on a bridge.
|
||||
*
|
||||
*/
|
||||
static void
|
||||
bridge_start(struct ifnet *ifp)
|
||||
static int
|
||||
bridge_transmit(struct ifnet *ifp, struct mbuf *m)
|
||||
{
|
||||
struct bridge_softc *sc;
|
||||
struct mbuf *m;
|
||||
struct ether_header *eh;
|
||||
struct ifnet *dst_if;
|
||||
int error = 0;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
for (;;) {
|
||||
IFQ_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == 0)
|
||||
break;
|
||||
ETHER_BPF_MTAP(ifp, m);
|
||||
ETHER_BPF_MTAP(ifp, m);
|
||||
|
||||
eh = mtod(m, struct ether_header *);
|
||||
dst_if = NULL;
|
||||
eh = mtod(m, struct ether_header *);
|
||||
|
||||
BRIDGE_LOCK(sc);
|
||||
if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) {
|
||||
dst_if = bridge_rtlookup(sc, eh->ether_dhost, 1);
|
||||
}
|
||||
BRIDGE_LOCK(sc);
|
||||
if (((m->m_flags & (M_BCAST|M_MCAST)) == 0) &&
|
||||
(dst_if = bridge_rtlookup(sc, eh->ether_dhost, 1)) != NULL) {
|
||||
BRIDGE_UNLOCK(sc);
|
||||
error = bridge_enqueue(sc, dst_if, m);
|
||||
} else
|
||||
bridge_broadcast(sc, ifp, m, 0);
|
||||
|
||||
if (dst_if == NULL)
|
||||
bridge_broadcast(sc, ifp, m, 0);
|
||||
else {
|
||||
BRIDGE_UNLOCK(sc);
|
||||
bridge_enqueue(sc, dst_if, m);
|
||||
}
|
||||
}
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* The ifp->if_qflush entry point for if_bridge(4) is no-op.
|
||||
*/
|
||||
static void
|
||||
bridge_qflush(struct ifnet *ifp __unused)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2094,8 +2149,8 @@ bridge_forward(struct bridge_softc *sc, struct bridge_iflist *sbif,
|
||||
src_if = m->m_pkthdr.rcvif;
|
||||
ifp = sc->sc_ifp;
|
||||
|
||||
ifp->if_ipackets++;
|
||||
ifp->if_ibytes += m->m_pkthdr.len;
|
||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
|
||||
vlan = VLANTAGOF(m);
|
||||
|
||||
if ((sbif->bif_flags & IFBIF_STP) &&
|
||||
@@ -2147,7 +2202,7 @@ bridge_forward(struct bridge_softc *sc, struct bridge_iflist *sbif,
|
||||
goto drop;
|
||||
|
||||
/* ...forward it to all interfaces. */
|
||||
ifp->if_imcasts++;
|
||||
if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1);
|
||||
dst_if = NULL;
|
||||
}
|
||||
|
||||
@@ -2255,8 +2310,8 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
|
||||
if ((bifp->if_flags & IFF_MONITOR) != 0) {
|
||||
m->m_pkthdr.rcvif = bifp;
|
||||
ETHER_BPF_MTAP(bifp, m);
|
||||
bifp->if_ipackets++;
|
||||
bifp->if_ibytes += m->m_pkthdr.len;
|
||||
if_inc_counter(bifp, IFCOUNTER_IPACKETS, 1);
|
||||
if_inc_counter(bifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
|
||||
m_freem(m);
|
||||
return (NULL);
|
||||
}
|
||||
@@ -2291,7 +2346,7 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
|
||||
* for bridge processing; return the original packet for
|
||||
* local processing.
|
||||
*/
|
||||
mc = m_dup(m, M_DONTWAIT);
|
||||
mc = m_dup(m, M_NOWAIT);
|
||||
if (mc == NULL) {
|
||||
BRIDGE_UNLOCK(sc);
|
||||
return (m);
|
||||
@@ -2308,7 +2363,7 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
|
||||
*/
|
||||
KASSERT(bifp->if_bridge == NULL,
|
||||
("loop created in bridge_input"));
|
||||
mc2 = m_dup(m, M_DONTWAIT);
|
||||
mc2 = m_dup(m, M_NOWAIT);
|
||||
if (mc2 != NULL) {
|
||||
/* Keep the layer3 header aligned */
|
||||
int i = min(mc2->m_pkthdr.len, max_protohdr);
|
||||
@@ -2357,9 +2412,10 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
|
||||
) { \
|
||||
if ((iface)->if_type == IFT_BRIDGE) { \
|
||||
ETHER_BPF_MTAP(iface, m); \
|
||||
iface->if_ipackets++; \
|
||||
if_inc_counter(iface, IFCOUNTER_IPACKETS, 1); \
|
||||
if_inc_counter(iface, IFCOUNTER_IBYTES, m->m_pkthdr.len); \
|
||||
/* Filter on the physical interface. */ \
|
||||
if (pfil_local_phys && \
|
||||
if (V_pfil_local_phys && \
|
||||
(PFIL_HOOKED(&V_inet_pfil_hook) \
|
||||
OR_PFIL_HOOKED_INET6)) { \
|
||||
if (bridge_pfil(&m, NULL, ifp, \
|
||||
@@ -2485,9 +2541,9 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
|
||||
mc = m;
|
||||
used = 1;
|
||||
} else {
|
||||
mc = m_dup(m, M_DONTWAIT);
|
||||
mc = m_dup(m, M_NOWAIT);
|
||||
if (mc == NULL) {
|
||||
sc->sc_ifp->if_oerrors++;
|
||||
if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -2507,7 +2563,7 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
|
||||
i = min(mc->m_pkthdr.len, max_protohdr);
|
||||
mc = m_copyup(mc, i, ETHER_ALIGN);
|
||||
if (mc == NULL) {
|
||||
sc->sc_ifp->if_oerrors++;
|
||||
if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -2548,9 +2604,9 @@ bridge_span(struct bridge_softc *sc, struct mbuf *m)
|
||||
if ((dst_if->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
continue;
|
||||
|
||||
mc = m_copypacket(m, M_DONTWAIT);
|
||||
mc = m_copypacket(m, M_NOWAIT);
|
||||
if (mc == NULL) {
|
||||
sc->sc_ifp->if_oerrors++;
|
||||
if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2793,24 +2849,19 @@ bridge_rtdelete(struct bridge_softc *sc, struct ifnet *ifp, int full)
|
||||
*
|
||||
* Initialize the route table for this bridge.
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
bridge_rtable_init(struct bridge_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
sc->sc_rthash = malloc(sizeof(*sc->sc_rthash) * BRIDGE_RTHASH_SIZE,
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (sc->sc_rthash == NULL)
|
||||
return (ENOMEM);
|
||||
M_DEVBUF, M_WAITOK);
|
||||
|
||||
for (i = 0; i < BRIDGE_RTHASH_SIZE; i++)
|
||||
LIST_INIT(&sc->sc_rthash[i]);
|
||||
|
||||
sc->sc_rthash_key = arc4random();
|
||||
|
||||
LIST_INIT(&sc->sc_rtlist);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3018,9 +3069,11 @@ bridge_state_change(struct ifnet *ifp, int state)
|
||||
"discarding"
|
||||
};
|
||||
|
||||
if (log_stp)
|
||||
CURVNET_SET(ifp->if_vnet);
|
||||
if (V_log_stp)
|
||||
log(LOG_NOTICE, "%s: state changed to %s on %s\n",
|
||||
sc->sc_ifp->if_xname, stpstates[state], ifp->if_xname);
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3034,7 +3087,6 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
|
||||
{
|
||||
int snap, error, i, hlen;
|
||||
struct ether_header *eh1, eh2;
|
||||
struct ip_fw_args args;
|
||||
struct ip *ip;
|
||||
struct llc llc1;
|
||||
u_int16_t ether_type;
|
||||
@@ -3047,7 +3099,7 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
|
||||
KASSERT(M_WRITABLE(*mp), ("%s: modifying a shared mbuf", __func__));
|
||||
#endif
|
||||
|
||||
if (pfil_bridge == 0 && pfil_member == 0 && pfil_ipfw == 0)
|
||||
if (V_pfil_bridge == 0 && V_pfil_member == 0 && V_pfil_ipfw == 0)
|
||||
return (0); /* filtering is disabled */
|
||||
|
||||
i = min((*mp)->m_pkthdr.len, max_protohdr);
|
||||
@@ -3089,7 +3141,7 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
|
||||
switch (ether_type) {
|
||||
case ETHERTYPE_ARP:
|
||||
case ETHERTYPE_REVARP:
|
||||
if (pfil_ipfw_arp == 0)
|
||||
if (V_pfil_ipfw_arp == 0)
|
||||
return (0); /* Automatically pass */
|
||||
break;
|
||||
|
||||
@@ -3104,10 +3156,20 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
|
||||
* packets, these will not be checked by pfil(9) and
|
||||
* passed unconditionally so the default is to drop.
|
||||
*/
|
||||
if (pfil_onlyip)
|
||||
if (V_pfil_onlyip)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Run the packet through pfil before stripping link headers */
|
||||
if (PFIL_HOOKED(&V_link_pfil_hook) && V_pfil_ipfw != 0 &&
|
||||
dir == PFIL_OUT && ifp != NULL) {
|
||||
|
||||
error = pfil_run_hooks(&V_link_pfil_hook, mp, ifp, dir, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* packet consumed by filter */
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Strip off the Ethernet header and keep a copy. */
|
||||
m_copydata(*mp, 0, ETHER_HDR_LEN, (caddr_t) &eh2);
|
||||
m_adj(*mp, ETHER_HDR_LEN);
|
||||
@@ -3138,63 +3200,6 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* XXX this section is also in if_ethersubr.c */
|
||||
// XXX PFIL_OUT or DIR_OUT ?
|
||||
if (V_ip_fw_chk_ptr && pfil_ipfw != 0 &&
|
||||
dir == PFIL_OUT && ifp != NULL) {
|
||||
struct m_tag *mtag;
|
||||
|
||||
error = -1;
|
||||
/* fetch the start point from existing tags, if any */
|
||||
mtag = m_tag_locate(*mp, MTAG_IPFW_RULE, 0, NULL);
|
||||
if (mtag == NULL) {
|
||||
args.rule.slot = 0;
|
||||
} else {
|
||||
struct ipfw_rule_ref *r;
|
||||
|
||||
/* XXX can we free the tag after use ? */
|
||||
mtag->m_tag_id = PACKET_TAG_NONE;
|
||||
r = (struct ipfw_rule_ref *)(mtag + 1);
|
||||
/* packet already partially processed ? */
|
||||
if (r->info & IPFW_ONEPASS)
|
||||
goto ipfwpass;
|
||||
args.rule = *r;
|
||||
}
|
||||
|
||||
args.m = *mp;
|
||||
args.oif = ifp;
|
||||
args.next_hop = NULL;
|
||||
args.next_hop6 = NULL;
|
||||
args.eh = &eh2;
|
||||
args.inp = NULL; /* used by ipfw uid/gid/jail rules */
|
||||
i = V_ip_fw_chk_ptr(&args);
|
||||
*mp = args.m;
|
||||
|
||||
if (*mp == NULL)
|
||||
return (error);
|
||||
|
||||
if (ip_dn_io_ptr && (i == IP_FW_DUMMYNET)) {
|
||||
|
||||
/* put the Ethernet header back on */
|
||||
M_PREPEND(*mp, ETHER_HDR_LEN, M_DONTWAIT);
|
||||
if (*mp == NULL)
|
||||
return (error);
|
||||
bcopy(&eh2, mtod(*mp, caddr_t), ETHER_HDR_LEN);
|
||||
|
||||
/*
|
||||
* Pass the pkt to dummynet, which consumes it. The
|
||||
* packet will return to us via bridge_dummynet().
|
||||
*/
|
||||
args.oif = ifp;
|
||||
ip_dn_io_ptr(mp, DIR_FWD | PROTO_IFB, &args);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (i != IP_FW_PASS) /* drop */
|
||||
goto bad;
|
||||
}
|
||||
|
||||
ipfwpass:
|
||||
error = 0;
|
||||
|
||||
/*
|
||||
@@ -3202,15 +3207,6 @@ ipfwpass:
|
||||
*/
|
||||
switch (ether_type) {
|
||||
case ETHERTYPE_IP:
|
||||
/*
|
||||
* before calling the firewall, swap fields the same as
|
||||
* IP does. here we assume the header is contiguous
|
||||
*/
|
||||
ip = mtod(*mp, struct ip *);
|
||||
|
||||
ip->ip_len = ntohs(ip->ip_len);
|
||||
ip->ip_off = ntohs(ip->ip_off);
|
||||
|
||||
/*
|
||||
* Run pfil on the member interface and the bridge, both can
|
||||
* be skipped by clearing pfil_member or pfil_bridge.
|
||||
@@ -3218,21 +3214,21 @@ ipfwpass:
|
||||
* Keep the order:
|
||||
* in_if -> bridge_if -> out_if
|
||||
*/
|
||||
if (pfil_bridge && dir == PFIL_OUT && bifp != NULL)
|
||||
if (V_pfil_bridge && dir == PFIL_OUT && bifp != NULL)
|
||||
error = pfil_run_hooks(&V_inet_pfil_hook, mp, bifp,
|
||||
dir, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* filter may consume */
|
||||
break;
|
||||
|
||||
if (pfil_member && ifp != NULL)
|
||||
if (V_pfil_member && ifp != NULL)
|
||||
error = pfil_run_hooks(&V_inet_pfil_hook, mp, ifp,
|
||||
dir, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* filter may consume */
|
||||
break;
|
||||
|
||||
if (pfil_bridge && dir == PFIL_IN && bifp != NULL)
|
||||
if (V_pfil_bridge && dir == PFIL_IN && bifp != NULL)
|
||||
error = pfil_run_hooks(&V_inet_pfil_hook, mp, bifp,
|
||||
dir, NULL);
|
||||
|
||||
@@ -3240,7 +3236,7 @@ ipfwpass:
|
||||
break;
|
||||
|
||||
/* check if we need to fragment the packet */
|
||||
if (pfil_member && ifp != NULL && dir == PFIL_OUT) {
|
||||
if (V_pfil_member && ifp != NULL && dir == PFIL_OUT) {
|
||||
i = (*mp)->m_pkthdr.len;
|
||||
if (i > ifp->if_mtu) {
|
||||
error = bridge_fragment(ifp, *mp, &eh2, snap,
|
||||
@@ -3249,20 +3245,18 @@ ipfwpass:
|
||||
}
|
||||
}
|
||||
|
||||
/* Recalculate the ip checksum and restore byte ordering */
|
||||
/* Recalculate the ip checksum. */
|
||||
ip = mtod(*mp, struct ip *);
|
||||
hlen = ip->ip_hl << 2;
|
||||
if (hlen < sizeof(struct ip))
|
||||
goto bad;
|
||||
if (hlen > (*mp)->m_len) {
|
||||
if ((*mp = m_pullup(*mp, hlen)) == 0)
|
||||
if ((*mp = m_pullup(*mp, hlen)) == NULL)
|
||||
goto bad;
|
||||
ip = mtod(*mp, struct ip *);
|
||||
if (ip == NULL)
|
||||
goto bad;
|
||||
}
|
||||
ip->ip_len = htons(ip->ip_len);
|
||||
ip->ip_off = htons(ip->ip_off);
|
||||
ip->ip_sum = 0;
|
||||
if (hlen == sizeof(struct ip))
|
||||
ip->ip_sum = in_cksum_hdr(ip);
|
||||
@@ -3272,21 +3266,21 @@ ipfwpass:
|
||||
break;
|
||||
#ifdef INET6
|
||||
case ETHERTYPE_IPV6:
|
||||
if (pfil_bridge && dir == PFIL_OUT && bifp != NULL)
|
||||
if (V_pfil_bridge && dir == PFIL_OUT && bifp != NULL)
|
||||
error = pfil_run_hooks(&V_inet6_pfil_hook, mp, bifp,
|
||||
dir, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* filter may consume */
|
||||
break;
|
||||
|
||||
if (pfil_member && ifp != NULL)
|
||||
if (V_pfil_member && ifp != NULL)
|
||||
error = pfil_run_hooks(&V_inet6_pfil_hook, mp, ifp,
|
||||
dir, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* filter may consume */
|
||||
break;
|
||||
|
||||
if (pfil_bridge && dir == PFIL_IN && bifp != NULL)
|
||||
if (V_pfil_bridge && dir == PFIL_IN && bifp != NULL)
|
||||
error = pfil_run_hooks(&V_inet6_pfil_hook, mp, bifp,
|
||||
dir, NULL);
|
||||
break;
|
||||
@@ -3307,13 +3301,13 @@ ipfwpass:
|
||||
* Finally, put everything back the way it was and return
|
||||
*/
|
||||
if (snap) {
|
||||
M_PREPEND(*mp, sizeof(struct llc), M_DONTWAIT);
|
||||
M_PREPEND(*mp, sizeof(struct llc), M_NOWAIT);
|
||||
if (*mp == NULL)
|
||||
return (error);
|
||||
bcopy(&llc1, mtod(*mp, caddr_t), sizeof(struct llc));
|
||||
}
|
||||
|
||||
M_PREPEND(*mp, ETHER_HDR_LEN, M_DONTWAIT);
|
||||
M_PREPEND(*mp, ETHER_HDR_LEN, M_NOWAIT);
|
||||
if (*mp == NULL)
|
||||
return (error);
|
||||
bcopy(&eh2, mtod(*mp, caddr_t), ETHER_HDR_LEN);
|
||||
@@ -3375,7 +3369,7 @@ bridge_ip_checkbasic(struct mbuf **mp)
|
||||
goto bad;
|
||||
}
|
||||
if (hlen > m->m_len) {
|
||||
if ((m = m_pullup(m, hlen)) == 0) {
|
||||
if ((m = m_pullup(m, hlen)) == NULL) {
|
||||
KMOD_IPSTAT_INC(ips_badhlen);
|
||||
goto bad;
|
||||
}
|
||||
@@ -3499,8 +3493,8 @@ bridge_fragment(struct ifnet *ifp, struct mbuf *m, struct ether_header *eh,
|
||||
goto out;
|
||||
ip = mtod(m, struct ip *);
|
||||
|
||||
error = ip_fragment(ip, &m, ifp->if_mtu, ifp->if_hwassist,
|
||||
CSUM_DELAY_IP);
|
||||
m->m_pkthdr.csum_flags |= CSUM_IP;
|
||||
error = ip_fragment(ip, &m, ifp->if_mtu, ifp->if_hwassist);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
@@ -3508,7 +3502,7 @@ bridge_fragment(struct ifnet *ifp, struct mbuf *m, struct ether_header *eh,
|
||||
for (m0 = m; m0; m0 = m0->m_nextpkt) {
|
||||
if (error == 0) {
|
||||
if (snap) {
|
||||
M_PREPEND(m0, sizeof(struct llc), M_DONTWAIT);
|
||||
M_PREPEND(m0, sizeof(struct llc), M_NOWAIT);
|
||||
if (m0 == NULL) {
|
||||
error = ENOBUFS;
|
||||
continue;
|
||||
@@ -3516,7 +3510,7 @@ bridge_fragment(struct ifnet *ifp, struct mbuf *m, struct ether_header *eh,
|
||||
bcopy(llc, mtod(m0, caddr_t),
|
||||
sizeof(struct llc));
|
||||
}
|
||||
M_PREPEND(m0, ETHER_HDR_LEN, M_DONTWAIT);
|
||||
M_PREPEND(m0, ETHER_HDR_LEN, M_NOWAIT);
|
||||
if (m0 == NULL) {
|
||||
error = ENOBUFS;
|
||||
continue;
|
||||
|
Reference in New Issue
Block a user