diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/bridgectl.c | 52 | ||||
-rw-r--r-- | sys/net/if_bridge.c | 9 | ||||
-rw-r--r-- | sys/net/if_bridge.h | 19 |
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 { |