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
/\

Reply via email to