summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/net/bridgectl.c52
-rw-r--r--sys/net/if_bridge.c9
-rw-r--r--sys/net/if_bridge.h19
3 files changed, 77 insertions, 3 deletions
diff --git a/sys/net/bridgectl.c b/sys/net/bridgectl.c
index 86949163bf8..5e431fe5f03 100644
--- a/sys/net/bridgectl.c
+++ b/sys/net/bridgectl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bridgectl.c,v 1.6 2017/05/04 15:00:24 bluhm Exp $ */
+/* $OpenBSD: bridgectl.c,v 1.7 2018/02/05 03:51:53 henning Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -573,6 +573,7 @@ bridge_brlconf(struct bridge_softc *sc, struct ifbrlconf *bc)
req.ifbr_flags = n->brl_flags;
req.ifbr_src = n->brl_src;
req.ifbr_dst = n->brl_dst;
+ req.ifbr_arpf = n->brl_arpf;
#if NPF > 0
req.ifbr_tagname[0] = '\0';
if (n->brl_tag)
@@ -596,6 +597,7 @@ bridge_brlconf(struct bridge_softc *sc, struct ifbrlconf *bc)
req.ifbr_flags = n->brl_flags;
req.ifbr_src = n->brl_src;
req.ifbr_dst = n->brl_dst;
+ req.ifbr_arpf = n->brl_arpf;
#if NPF > 0
req.ifbr_tagname[0] = '\0';
if (n->brl_tag)
@@ -615,12 +617,59 @@ done:
}
u_int8_t
+bridge_arpfilter(struct brl_node *n, struct ether_header *eh, struct mbuf *m)
+{
+ struct ether_arp ea;
+
+ if (!(n->brl_arpf.brla_flags & (BRLA_ARP|BRLA_RARP)))
+ return (1);
+
+ if (ntohs(eh->ether_type) != ETHERTYPE_ARP)
+ return (0);
+ if (m->m_pkthdr.len <= ETHER_HDR_LEN + sizeof(ea))
+ return (0); /* log error? */
+ m_copydata(m, ETHER_HDR_LEN, sizeof(ea), (caddr_t)&ea);
+
+ if (ntohs(ea.arp_hrd) != ARPHRD_ETHER ||
+ ntohs(ea.arp_pro) != ETHERTYPE_IP ||
+ ea.arp_hln != ETHER_ADDR_LEN ||
+ ea.arp_pln != sizeof(struct in_addr))
+ return (0);
+ if ((n->brl_arpf.brla_flags & BRLA_ARP) &&
+ ntohs(ea.arp_op) != ARPOP_REQUEST &&
+ ntohs(ea.arp_op) != ARPOP_REPLY)
+ return (0);
+ if ((n->brl_arpf.brla_flags & BRLA_RARP) &&
+ ntohs(ea.arp_op) != ARPOP_REVREQUEST &&
+ ntohs(ea.arp_op) != ARPOP_REVREPLY)
+ return (0);
+ if (n->brl_arpf.brla_op && ntohs(ea.arp_op) != n->brl_arpf.brla_op)
+ return (0);
+ if (n->brl_arpf.brla_flags & BRLA_SHA &&
+ bcmp(ea.arp_sha, &n->brl_arpf.brla_sha, ETHER_ADDR_LEN))
+ return (0);
+ if (n->brl_arpf.brla_flags & BRLA_THA &&
+ bcmp(ea.arp_tha, &n->brl_arpf.brla_tha, ETHER_ADDR_LEN))
+ return (0);
+ if (n->brl_arpf.brla_flags & BRLA_SPA &&
+ bcmp(ea.arp_spa, &n->brl_arpf.brla_spa, sizeof(struct in_addr)))
+ return (0);
+ if (n->brl_arpf.brla_flags & BRLA_TPA &&
+ bcmp(ea.arp_tpa, &n->brl_arpf.brla_tpa, sizeof(struct in_addr)))
+ return (0);
+
+ return (1);
+}
+
+u_int8_t
bridge_filterrule(struct brl_head *h, struct ether_header *eh, struct mbuf *m)
{
struct brl_node *n;
u_int8_t flags;
SIMPLEQ_FOREACH(n, h, brl_next) {
+ if (!bridge_arpfilter(n, eh, m))
+ continue;
flags = n->brl_flags & (BRL_FLAG_SRCVALID|BRL_FLAG_DSTVALID);
if (flags == 0)
goto return_action;
@@ -663,6 +712,7 @@ bridge_addrule(struct bridge_iflist *bif, struct ifbrlreq *req, int out)
bcopy(&req->ifbr_dst, &n->brl_dst, sizeof(struct ether_addr));
n->brl_action = req->ifbr_action;
n->brl_flags = req->ifbr_flags;
+ n->brl_arpf = req->ifbr_arpf;
#if NPF > 0
if (req->ifbr_tagname[0])
n->brl_tag = pf_tagname2tag(req->ifbr_tagname, 1);
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index fa37dfd12e9..a54f5babd5d 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.301 2018/01/10 23:50:39 dlg Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.302 2018/02/05 03:51:53 henning Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -699,6 +699,7 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
struct ether_addr *dst;
struct bridge_softc *sc;
struct bridge_tunneltag *brtag;
+ struct bridge_iflist *ifl;
int error;
/* ifp must be a member interface of the bridge. */
@@ -785,6 +786,12 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
}
}
+ ifl = (struct bridge_iflist *)dst_if->if_bridgeport;
+ KASSERT(ifl != NULL);
+ if (bridge_filterrule(&ifl->bif_brlout, eh, mc) ==
+ BRL_ACTION_BLOCK)
+ continue;
+
error = bridge_ifenqueue(sc, dst_if, mc);
if (error)
continue;
diff --git a/sys/net/if_bridge.h b/sys/net/if_bridge.h
index 55a3fa70a9a..75596a5b040 100644
--- a/sys/net/if_bridge.h
+++ b/sys/net/if_bridge.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.h,v 1.55 2017/01/20 05:03:48 claudio Exp $ */
+/* $OpenBSD: if_bridge.h,v 1.56 2018/02/05 03:51:53 henning Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -196,6 +196,21 @@ struct ifbropreq {
/*
* Bridge mac rules
*/
+struct ifbrarpf {
+ u_int16_t brla_flags;
+ u_int16_t brla_op;
+ struct ether_addr brla_sha;
+ struct in_addr brla_spa;
+ struct ether_addr brla_tha;
+ struct in_addr brla_tpa;
+};
+#define BRLA_ARP 0x01
+#define BRLA_RARP 0x02
+#define BRLA_SHA 0x10
+#define BRLA_SPA 0x20
+#define BRLA_THA 0x40
+#define BRLA_TPA 0x80
+
struct ifbrlreq {
char ifbr_name[IFNAMSIZ]; /* bridge ifs name */
char ifbr_ifsname[IFNAMSIZ]; /* member ifs name */
@@ -204,6 +219,7 @@ struct ifbrlreq {
struct ether_addr ifbr_src; /* source mac */
struct ether_addr ifbr_dst; /* destination mac */
char ifbr_tagname[PF_TAG_NAME_SIZE]; /* pf tagname */
+ struct ifbrarpf ifbr_arpf; /* arp filter */
};
#define BRL_ACTION_BLOCK 0x01 /* block frame */
#define BRL_ACTION_PASS 0x02 /* pass frame */
@@ -269,6 +285,7 @@ struct brl_node {
u_int16_t brl_tag; /* pf tag ID */
u_int8_t brl_action; /* what to do with match */
u_int8_t brl_flags; /* comparision flags */
+ struct ifbrarpf brl_arpf; /* arp filter */
};
struct bstp_timer {