Inline diff 2012/7/3 sven falempin <sven.falem...@gmail.com>
> 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 /\