On Mon, Jan 22, 2018 at 04:23:59PM +0100, Martin Pieuchot wrote:
> Diff below adds a new feature to bridge(4), similar to Cisco's Protected
> Port but with more possibilities.
> 
> The idea is to prevent traffic to flow between some members of a bridge(4).
> For example:
>   - you want to prevent some of your servers to talk to each others, or
>   - you want employees/students/clients to have access to internet and a
>     printer but not to each other, or
>   - you want VMs to have access to an uplink but not to each other
 
I think the last example is really useful and makes sense.

For the other cases there would most likely be a switch between the other
host and the OpenBSD box. Then you need to enforce the policy on that switch.

> With the diff below it is now possible to defined "protected groups".
> Interface that are part of such groups cannot send/receive traffic
> to/from any other member of the group.

Why several protected groups and not just a single one?

> 
> In the example below, em1 and em2 can only send/receive traffic through
> em0 because they are both in the protected group 2.
> 
> bridge0: flags=41<UP,RUNNING>
>         index 9 llprio 3
>         groups: bridge
>         priority 32768 hellotime 2 fwddelay 15 maxage 20 holdcnt 6 proto rstp
>         designated: id 00:00:00:00:00:00 priority 0
>         em0 flags=3<LEARNING,DISCOVER>
>                 port 6 ifpriority 0 ifcost 0
>         em1 flags=3<LEARNING,DISCOVER>
>                 port 7 ifpriority 0 ifcost 0 protected 2
>         em2 flags=3<LEARNING,DISCOVER>
>                 port 8 ifpriority 0 ifcost 0 protected 2
> 
> Adding an interface to a protected group is as simple as:
> 
>   # ifconfig bridge0 protected em1 2 
> 
> Removing it:
> 
>   # ifconfig bridge0 -protected em1
> 
> Comments?  Oks?
> 
> Index: sys/net/if_bridge.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_bridge.c,v
> retrieving revision 1.301
> diff -u -p -r1.301 if_bridge.c
> --- sys/net/if_bridge.c       10 Jan 2018 23:50:39 -0000      1.301
> +++ sys/net/if_bridge.c       22 Jan 2018 14:27:41 -0000
> @@ -409,6 +409,7 @@ bridge_ioctl(struct ifnet *ifp, u_long c
>               }
>               req->ifbr_ifsflags = p->bif_flags;
>               req->ifbr_portno = p->ifp->if_index & 0xfff;
> +             req->ifbr_protected = p->bif_protected;
>               if (p->bif_flags & IFBIF_STP) {
>                       bp = p->bif_stp;
>                       req->ifbr_state = bstp_getstate(bs, bp);
> @@ -496,6 +497,19 @@ bridge_ioctl(struct ifnet *ifp, u_long c
>               brop->ifbop_last_tc_time.tv_sec = bs->bs_last_tc_time.tv_sec;
>               brop->ifbop_last_tc_time.tv_usec = bs->bs_last_tc_time.tv_usec;
>               break;
> +     case SIOCBRDGSIFPROT:
> +             ifs = ifunit(req->ifbr_ifsname);
> +             if (ifs == NULL) {
> +                     error = ENOENT;
> +                     break;
> +             }
> +             p = (struct bridge_iflist *)ifs->if_bridgeport;
> +             if (p == NULL || p->bridge_sc != sc) {
> +                     error = ESRCH;
> +                     break;
> +             }
> +             p->bif_protected = req->ifbr_protected;
> +             break;
>       case SIOCBRDGRTS:
>       case SIOCBRDGGCACHE:
>       case SIOCBRDGGPRI:
> @@ -594,6 +608,7 @@ bridge_bifconf(struct bridge_softc *sc, 
>               strlcpy(breq->ifbr_ifsname, p->ifp->if_xname, IFNAMSIZ);
>               breq->ifbr_ifsflags = p->bif_flags;
>               breq->ifbr_portno = p->ifp->if_index & 0xfff;
> +             breq->ifbr_protected = p->bif_protected;
>               if (p->bif_flags & IFBIF_STP) {
>                       bp = p->bif_stp;
>                       breq->ifbr_state = bstp_getstate(sc->sc_stp, bp);
> @@ -848,6 +863,7 @@ bridgeintr_frame(struct bridge_softc *sc
>       struct bridge_rtnode *dst_p;
>       struct ether_addr *dst, *src;
>       struct ether_header eh;
> +     u_int32_t protected;
>       int len;
>  
>  
> @@ -960,6 +976,7 @@ bridgeintr_frame(struct bridge_softc *sc
>               bridge_broadcast(sc, src_if, &eh, m);
>               return;
>       }
> +     protected = ifl->bif_protected;
>  
>       /*
>        * At this point, we're dealing with a unicast frame going to a
> @@ -975,6 +992,14 @@ bridgeintr_frame(struct bridge_softc *sc
>               m_freem(m);
>               return;
>       }
> +     /*
> +      * Do not transmit if both ports are part of the same protected
> +      * group.
> +      */
> +     if (protected != 0 && protected == ifl->bif_protected) {
> +             m_freem(m);
> +             return;
> +     }
>       if (bridge_filterrule(&ifl->bif_brlout, &eh, m) == BRL_ACTION_BLOCK) {
>               m_freem(m);
>               return;
> @@ -1159,6 +1184,10 @@ bridge_broadcast(struct bridge_softc *sc
>       struct mbuf *mc;
>       struct ifnet *dst_if;
>       int len, used = 0;
> +     u_int32_t protected;
> +
> +     p = (struct bridge_iflist *)ifp->if_bridgeport;
> +     protected = p->bif_protected;
>  
>       TAILQ_FOREACH(p, &sc->sc_iflist, next) {
>               dst_if = p->ifp;
> @@ -1177,6 +1206,13 @@ bridge_broadcast(struct bridge_softc *sc
>               /* Drop non-IP frames if the appropriate flag is set. */
>               if (p->bif_flags & IFBIF_BLOCKNONIP &&
>                   bridge_blocknonip(eh, m))
> +                     continue;
> +
> +             /*
> +              * Do not transmit if both ports are part of the same
> +              * protected group.
> +              */
> +             if (protected != 0 && protected == p->bif_protected)
>                       continue;
>  
>               if (bridge_filterrule(&p->bif_brlout, eh, m) == 
> BRL_ACTION_BLOCK)
> Index: sys/net/if_bridge.h
> ===================================================================
> RCS file: /cvs/src/sys/net/if_bridge.h,v
> retrieving revision 1.55
> diff -u -p -r1.55 if_bridge.h
> --- sys/net/if_bridge.h       20 Jan 2017 05:03:48 -0000      1.55
> +++ sys/net/if_bridge.h       22 Jan 2018 15:13:07 -0000
> @@ -46,6 +46,7 @@ struct ifbreq {
>       char            ifbr_ifsname[IFNAMSIZ]; /* member ifs name */
>       u_int32_t       ifbr_ifsflags;          /* member ifs flags */
>       u_int32_t       ifbr_portno;            /* member port number */
> +     u_int32_t       ifbr_protected;         /* protected group number */
>  
>       u_int8_t        ifbr_state;             /* member stp state */
>       u_int8_t        ifbr_priority;          /* member stp priority */
> @@ -398,6 +399,7 @@ struct bridge_iflist {
>       struct brl_head                 bif_brlout;     /* output rules */
>       struct                          ifnet *ifp;     /* member interface */
>       u_int32_t                       bif_flags;      /* member flags */
> +     u_int32_t                       bif_protected;  /* protected group */
>       void                            *bif_dhcookie;
>  };
>  #define bif_state                    bif_stp->bp_state
> Index: sys/sys/sockio.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/sockio.h,v
> retrieving revision 1.72
> diff -u -p -r1.72 sockio.h
> --- sys/sys/sockio.h  24 Oct 2017 09:36:13 -0000      1.72
> +++ sys/sys/sockio.h  22 Jan 2018 14:09:09 -0000
> @@ -89,6 +89,7 @@
>  #define      SIOCBRDGDADDR    _IOW('i', 71, struct ifbareq)  /* delete addr 
> */
>  #define      SIOCBRDGFLUSH    _IOW('i', 72, struct ifbreq)   /* flush addr 
> cache */
>  #define      SIOCBRDGADDL     _IOW('i', 73, struct ifbreq)   /* add local 
> port */
> +#define      SIOCBRDGSIFPROT  _IOW('i', 74, struct ifbreq)   /* set 
> protected grp */
>  
>  #define SIOCBRDGARL   _IOW('i', 77, struct ifbrlreq) /* add bridge rule */
>  #define SIOCBRDGFRL   _IOW('i', 78, struct ifbrlreq) /* flush brdg rules */
> Index: sbin/ifconfig/brconfig.c
> ===================================================================
> RCS file: /cvs/src/sbin/ifconfig/brconfig.c,v
> retrieving revision 1.16
> diff -u -p -r1.16 brconfig.c
> --- sbin/ifconfig/brconfig.c  31 Jul 2017 02:32:11 -0000      1.16
> +++ sbin/ifconfig/brconfig.c  22 Jan 2018 14:30:38 -0000
> @@ -336,6 +336,8 @@ bridge_list(char *delim)
>               printf("port %u ifpriority %u ifcost %u",
>                   reqp->ifbr_portno, reqp->ifbr_priority,
>                   reqp->ifbr_path_cost);
> +             if (reqp->ifbr_protected)
> +                     printf(" protected %u", reqp->ifbr_protected);
>               if (reqp->ifbr_ifsflags & IFBIF_STP)
>                       printf(" %s role %s",
>                           stpstates[reqp->ifbr_state],
> @@ -452,6 +454,41 @@ bridge_priority(const char *arg, int d)
>       bp.ifbrp_prio = v;
>       if (ioctl(s, SIOCBRDGSPRI, (caddr_t)&bp) < 0)
>               err(1, "%s", name);
> +}
> +
> +void
> +bridge_protect(const char *ifname, const char *val)
> +{
> +     struct ifbreq breq;
> +     unsigned long v;
> +     char *endptr;
> +
> +     strlcpy(breq.ifbr_name, name, sizeof(breq.ifbr_name));
> +     strlcpy(breq.ifbr_ifsname, ifname, sizeof(breq.ifbr_ifsname));
> +
> +     errno = 0;
> +     v = strtoul(val, &endptr, 0);
> +     if (val[0] == '\0' || endptr[0] != '\0' || v == 0 || v > UINT32_MAX ||
> +         (errno == ERANGE && v == ULONG_MAX))
> +             err(1, "invalid arg for protected group: %s", val);
> +     breq.ifbr_protected = v;
> +
> +     if (ioctl(s, SIOCBRDGSIFPROT, (caddr_t)&breq) < 0)
> +             err(1, "%s: %s", name, val);
> +}
> +
> +void
> +bridge_unprotect(const char *ifname, int d)
> +{
> +     struct ifbreq breq;
> +
> +     strlcpy(breq.ifbr_name, name, sizeof(breq.ifbr_name));
> +     strlcpy(breq.ifbr_ifsname, ifname, sizeof(breq.ifbr_ifsname));
> +
> +     breq.ifbr_protected = 0;
> +
> +     if (ioctl(s, SIOCBRDGSIFPROT, (caddr_t)&breq) < 0)
> +             err(1, "%s: %d", name, 0);
>  }
>  
>  void
> Index: sbin/ifconfig/brconfig.h
> ===================================================================
> RCS file: /cvs/src/sbin/ifconfig/brconfig.h,v
> retrieving revision 1.12
> diff -u -p -r1.12 brconfig.h
> --- sbin/ifconfig/brconfig.h  16 Jan 2018 10:33:55 -0000      1.12
> +++ sbin/ifconfig/brconfig.h  22 Jan 2018 14:12:39 -0000
> @@ -52,6 +52,8 @@ void bridge_addrs(const char *, int);
>  void bridge_hellotime(const char *, int);
>  void bridge_fwddelay(const char *, int);
>  void bridge_maxage(const char *, int);
> +void bridge_protect(const char *, const char *);
> +void bridge_unprotect(const char *, int);
>  void bridge_proto(const char *, int);
>  void bridge_ifprio(const char *, const char *);
>  void bridge_ifcost(const char *, const char *);
> Index: sbin/ifconfig/ifconfig.8
> ===================================================================
> RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v
> retrieving revision 1.292
> diff -u -p -r1.292 ifconfig.8
> --- sbin/ifconfig/ifconfig.8  16 Jan 2018 10:33:55 -0000      1.292
> +++ sbin/ifconfig/ifconfig.8  22 Jan 2018 15:11:32 -0000
> @@ -662,6 +662,13 @@ The default is 100 entries.
>  .It Cm maxage Ar time
>  Set the time (in seconds) that a spanning tree protocol configuration is 
> valid.
>  Defaults to 20 seconds, minimum of 6, maximum of 40.
> +.It Cm protected Ar interface Ar id
> +Put
> +.Ar interface
> +in protected mode.
> +A protected interface does not forward traffic to any other protected 
> interface
> +having the same
> +.Ar id .
>  .It Cm proto Ar value
>  Force the spanning tree protocol version.
>  The available values are
> Index: sbin/ifconfig/ifconfig.c
> ===================================================================
> RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
> retrieving revision 1.353
> diff -u -p -r1.353 ifconfig.c
> --- sbin/ifconfig/ifconfig.c  16 Jan 2018 10:33:55 -0000      1.353
> +++ sbin/ifconfig/ifconfig.c  22 Jan 2018 14:17:17 -0000
> @@ -472,6 +472,8 @@ const struct      cmd {
>       { "-edge",      NEXTARG,        0,              unsetedge },
>       { "autoedge",   NEXTARG,        0,              setautoedge },
>       { "-autoedge",  NEXTARG,        0,              unsetautoedge },
> +     { "protected",  NEXTARG2,       0,              NULL, bridge_protect },
> +     { "-protected", NEXTARG,        0,              bridge_unprotect },
>       { "ptp",        NEXTARG,        0,              setptp },
>       { "-ptp",       NEXTARG,        0,              unsetptp },
>       { "autoptp",    NEXTARG,        0,              setautoptp },

Reply via email to