Inline diff
2012/7/3 sven falempin <[email protected]>
> This diff enables the possibilty of using a mask on bridges rules.
>
> I have test it like this :
>
> $ cat /etc/hostname.bridge0
>
>
> up
> add re0
> add vether0
> rule pass out on vether0 src 78:2b:4f:00:00:00 mask ff:ff:ff:00:00:00 tag
> booz
> rule block out on vether0 src 78:2b:00:00:00:00 mask ff:ff:00:00:00:00
> $ cat /etc/hostname.vether0
> inet 172.16.0.2 255.255.0.0
> $ cat /etc/hostname.re0
> inet 10.15.0.3 255.255.0.0
>
> then from a machine on the 10.15/24 network i add an alias to access
> 172.16/24 through bridge0
>
> blocking and tagging are ok.
>
> Unexpected result:
> - block on re0 just block everything, not just the bridging (forwarding
> to vether
> - this is not dynamic (after a flushrule i cannot block - this is not
> related to the patch)
>
> --
>
> ---------------------------------------------------------------------------------------------------------------------
> () ascii ribbon campaign - against html e-mail
> /\
>
>
Index: ./sys/net/if_bridge.c
===================================================================
RCS file: /cvs/src/sys/net/if_bridge.c,v
retrieving revision 1.193
diff -u -r1.193 if_bridge.c
--- ./sys/net/if_bridge.c 4 Jul 2011 06:54:49 -0000 1.193
+++ ./sys/net/if_bridge.c 3 Jul 2012 22:52:25 -0000
@@ -76,6 +76,8 @@
#include <netinet6/ip6_var.h>
#endif
+#include <sys/syslog.h>
+
#if NPF > 0
#include <net/pfvar.h>
#define BRIDGE_IN PF_IN
@@ -145,6 +147,8 @@
struct ifbrlreq *, int out);
int bridge_flushrule(struct bridge_iflist *);
int bridge_brlconf(struct bridge_softc *, struct ifbrlconf *);
+int bridge_test_ea(struct ether_addr *, struct ether_addr *,
+ struct ether_addr *);
u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *,
struct mbuf *);
struct mbuf *bridge_ip(struct bridge_softc *, int, struct ifnet *,
@@ -910,6 +914,8 @@
req.ifbr_flags = n->brl_flags;
req.ifbr_src = n->brl_src;
req.ifbr_dst = n->brl_dst;
+ req.ifbr_src_mask = n->brl_src_mask;
+ req.ifbr_dst_mask = n->brl_dst_mask;
#if NPF > 0
req.ifbr_tagname[0] = '\0';
if (n->brl_tag)
@@ -933,6 +939,8 @@
req.ifbr_flags = n->brl_flags;
req.ifbr_src = n->brl_src;
req.ifbr_dst = n->brl_dst;
+ req.ifbr_src_mask = n->brl_src_mask;
+ req.ifbr_dst_mask = n->brl_dst_mask;
#if NPF > 0
req.ifbr_tagname[0] = '\0';
if (n->brl_tag)
@@ -2204,33 +2212,36 @@
return (1);
}
+//inline
+int
+bridge_test_ea(struct ether_addr *ea_packet, struct ether_addr *ea_rules,
+ struct ether_addr *ea_mask) {
+ int i;
+ struct ether_addr ea_cmp;
+ for (i = 0; i < ETHER_ADDR_LEN; ++i) {
+ ea_cmp.ether_addr_octet[i] = ea_mask->ether_addr_octet[i]
+ & ea_packet->ether_addr_octet[i];
+ }
+ return (bcmp(&ea_cmp, ea_rules, ETHER_ADDR_LEN));
+}
+
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) {
- flags = n->brl_flags & (BRL_FLAG_SRCVALID|BRL_FLAG_DSTVALID);
- if (flags == 0)
- goto return_action;
- if (flags == (BRL_FLAG_SRCVALID|BRL_FLAG_DSTVALID)) {
- if (bcmp(eh->ether_shost, &n->brl_src, ETHER_ADDR_LEN))
- continue;
- if (bcmp(eh->ether_dhost, &n->brl_dst, ETHER_ADDR_LEN))
- continue;
- goto return_action;
- }
- if (flags == BRL_FLAG_SRCVALID) {
- if (bcmp(eh->ether_shost, &n->brl_src, ETHER_ADDR_LEN))
+ if ( n->brl_flags & BRL_FLAG_SRCVALID ) {
+ if (bridge_test_ea( (struct ether_addr *)eh->ether_shost,
+ &n->brl_src, &n->brl_src_mask))
continue;
- goto return_action;
}
- if (flags == BRL_FLAG_DSTVALID) {
- if (bcmp(eh->ether_dhost, &n->brl_dst, ETHER_ADDR_LEN))
+ if (n->brl_flags & BRL_FLAG_DSTVALID) {
+ if (bridge_test_ea( (struct ether_addr *)eh->ether_dhost,
+ &n->brl_dst, &n->brl_dst_mask))
continue;
- goto return_action;
}
+ goto return_action;
}
return (BRL_ACTION_PASS);
@@ -2249,8 +2260,10 @@
n = malloc(sizeof(*n), M_DEVBUF, M_NOWAIT);
if (n == NULL)
return (ENOMEM);
- bcopy(&req->ifbr_src, &n->brl_src, sizeof(struct ether_addr));
- bcopy(&req->ifbr_dst, &n->brl_dst, sizeof(struct ether_addr));
+ n->brl_src = req->ifbr_src;
+ n->brl_dst = req->ifbr_dst;
+ n->brl_src_mask = req->ifbr_src_mask;
+ n->brl_dst_mask = req->ifbr_dst_mask;
n->brl_action = req->ifbr_action;
n->brl_flags = req->ifbr_flags;
#if NPF > 0
Index: ./sys/net/if_bridge.h
===================================================================
RCS file: /cvs/src/sys/net/if_bridge.h,v
retrieving revision 1.34
diff -u -r1.34 if_bridge.h
--- ./sys/net/if_bridge.h 20 Nov 2010 14:23:09 -0000 1.34
+++ ./sys/net/if_bridge.h 3 Jul 2012 22:52:25 -0000
@@ -194,7 +194,9 @@
u_int8_t ifbr_action; /* disposition */
u_int8_t ifbr_flags; /* flags */
struct ether_addr ifbr_src; /* source mac */
+ struct ether_addr ifbr_src_mask; /* source mac mask */
struct ether_addr ifbr_dst; /* destination mac */
+ struct ether_addr ifbr_dst_mask; /* destination mac mask */
char ifbr_tagname[PF_TAG_NAME_SIZE]; /* pf tagname */
};
#define BRL_ACTION_BLOCK 0x01 /* block frame */
@@ -257,7 +259,9 @@
struct brl_node {
SIMPLEQ_ENTRY(brl_node) brl_next; /* next rule */
struct ether_addr brl_src; /* source mac address */
+ struct ether_addr brl_src_mask; /* source mac address mask */
struct ether_addr brl_dst; /* destination mac address */
+ struct ether_addr brl_dst_mask; /* destination mac address mask */
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 */
Index: ./sbin/ifconfig/brconfig.c
===================================================================
RCS file: /cvs/src/sbin/ifconfig/brconfig.c,v
retrieving revision 1.3
diff -u -r1.3 brconfig.c
--- ./sbin/ifconfig/brconfig.c 14 Dec 2009 19:22:20 -0000 1.3
+++ ./sbin/ifconfig/brconfig.c 3 Jul 2012 22:52:25 -0000
@@ -760,6 +760,8 @@
void
bridge_showrule(struct ifbrlreq *r)
{
+ struct ether_addr zea;
+ memset(&zea, 0xFFFFFFFF, sizeof(struct ether_addr));
if (r->ifbr_action == BRL_ACTION_BLOCK)
printf("block ");
else if (r->ifbr_action == BRL_ACTION_PASS)
@@ -779,10 +781,16 @@
printf("on %s", r->ifbr_ifsname);
- if (r->ifbr_flags & BRL_FLAG_SRCVALID)
+ if (r->ifbr_flags & BRL_FLAG_SRCVALID) {
printf(" src %s", ether_ntoa(&r->ifbr_src));
- if (r->ifbr_flags & BRL_FLAG_DSTVALID)
+ if (bcmp(&r->ifbr_src_mask,&zea,sizeof(zea)))
+ printf(" mask %s", ether_ntoa(&r->ifbr_src_mask));
+ }
+ if (r->ifbr_flags & BRL_FLAG_DSTVALID) {
printf(" dst %s", ether_ntoa(&r->ifbr_dst));
+ if (bcmp(&r->ifbr_dst_mask,&zea,sizeof(zea)))
+ printf(" mask %s", ether_ntoa(&r->ifbr_dst_mask));
+ }
if (r->ifbr_tagname[0])
printf(" tag %s", r->ifbr_tagname);
@@ -793,7 +801,8 @@
* Parse a rule definition and send it upwards.
*
* Syntax:
- * {block|pass} {in|out|in/out} on {ifs} [src {mac}] [dst {mac}]
+ * {block|pass} {in|out|in/out} on {ifs}
+ * [src {mac} [mask {mac}]] [dst {mac} [mask {mac}]] [tag {tagname}]
*/
int
bridge_rule(int targc, char **targv, int ln)
@@ -801,7 +810,8 @@
char **argv = targv;
int argc = targc;
struct ifbrlreq rule;
- struct ether_addr *ea, *dea;
+ struct ether_addr *ea, *dea = NULL;
+ u_int8_t pflag = 0;
if (argc == 0) {
warnx("invalid rule\n");
@@ -810,6 +820,8 @@
rule.ifbr_tagname[0] = 0;
rule.ifbr_flags = 0;
rule.ifbr_action = 0;
+ memset(&rule.ifbr_src_mask, 0xFFFFFFFF, sizeof(rule.ifbr_src_mask));
+ memset(&rule.ifbr_dst_mask, 0xFFFFFFFF, sizeof(rule.ifbr_src_mask));
strlcpy(rule.ifbr_name, name, sizeof(rule.ifbr_name));
if (strcmp(argv[0], "block") == 0)
@@ -847,21 +859,35 @@
argc--; argv++;
while (argc) {
+ if (argc < 2) {
+ warnx("missing %s value\n",argv[0]);
+ goto bad_rule;
+ }
if (strcmp(argv[0], "dst") == 0) {
if (rule.ifbr_flags & BRL_FLAG_DSTVALID)
goto bad_rule;
- rule.ifbr_flags |= BRL_FLAG_DSTVALID;
+ pflag = BRL_FLAG_DSTVALID;
dea = &rule.ifbr_dst;
} else if (strcmp(argv[0], "src") == 0) {
if (rule.ifbr_flags & BRL_FLAG_SRCVALID)
goto bad_rule;
- rule.ifbr_flags |= BRL_FLAG_SRCVALID;
+ pflag = BRL_FLAG_SRCVALID;
dea = &rule.ifbr_src;
- } else if (strcmp(argv[0], "tag") == 0) {
- if (argc < 2) {
- warnx("missing tag name\n");
+ } else if (strcmp(argv[0], "mask") == 0) {
+ if (dea == NULL) {
+ warnx("no src or dst mac address before mask\n");
+ goto bad_rule;
+ }
+ if ( pflag == 0 ) {
+ warnx("multiple mask definition\n");
goto bad_rule;
}
+ pflag = 0;
+ if (rule.ifbr_flags & BRL_FLAG_SRCVALID)
+ dea = &rule.ifbr_src_mask;
+ else
+ dea = &rule.ifbr_dst_mask;
+ } else if (strcmp(argv[0], "tag") == 0) {
if (rule.ifbr_tagname[0]) {
warnx("tag already defined\n");
goto bad_rule;
@@ -876,10 +902,8 @@
goto bad_rule;
argc--; argv++;
-
- if (argc == 0)
- goto bad_rule;
if (dea != NULL) {
+ rule.ifbr_flags |= pflag;
ea = ether_aton(argv[0]);
if (ea == NULL) {
warnx("invalid address: %s", argv[0]);
Index: ./sbin/ifconfig/ifconfig.8
===================================================================
RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.228
diff -u -r1.228 ifconfig.8
--- ./sbin/ifconfig/ifconfig.8 31 May 2012 17:50:59 -0000 1.228
+++ ./sbin/ifconfig/ifconfig.8 3 Jul 2012 22:52:25 -0000
@@ -688,6 +688,7 @@
.Cm on Ar interface
.Op Cm src Ar address
.Op Cm dst Ar address
+.Op Cm mask Ar address
.Op Cm tag Ar tagname
.Xc
Add a filtering rule to an interface.
@@ -703,6 +704,7 @@
and, if given, the tag of the rule.
If no source or destination address is specified, the
rule will match all frames (good for creating a catchall policy).
+mask is only valid after a given src or dst.
.It Cm rulefile Ar filename
Load a set of rules from the file
.Ar filename .
--
---------------------------------------------------------------------------------------------------------------------
() ascii ribbon campaign - against html e-mail
/\