]> Pileus Git - ~andy/linux/blobdiff - net/bridge/br_private.h
bridge: Validate that vlan is permitted on ingress
[~andy/linux] / net / bridge / br_private.h
index 8d83be5ffedcd8d04fdff6edf715947f56a1fbcc..ed7c764ee9dad5d4c5789c10dfe3cdc6e4e4291b 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/netpoll.h>
 #include <linux/u64_stats_sync.h>
 #include <net/route.h>
+#include <linux/if_vlan.h>
 
 #define BR_HASH_BITS 8
 #define BR_HASH_SIZE (1 << BR_HASH_BITS)
@@ -26,6 +27,7 @@
 
 #define BR_PORT_BITS   10
 #define BR_MAX_PORTS   (1<<BR_PORT_BITS)
+#define BR_VLAN_BITMAP_LEN     BITS_TO_LONGS(VLAN_N_VID)
 
 #define BR_VERSION     "2.3"
 
@@ -63,6 +65,16 @@ struct br_ip
        __be16          proto;
 };
 
+struct net_port_vlans {
+       u16                             port_idx;
+       union {
+               struct net_bridge_port          *port;
+               struct net_bridge               *br;
+       }                               parent;
+       struct rcu_head                 rcu;
+       unsigned long                   vlan_bitmap[BR_VLAN_BITMAP_LEN];
+};
+
 struct net_bridge_fdb_entry
 {
        struct hlist_node               hlist;
@@ -156,6 +168,9 @@ struct net_bridge_port
 #ifdef CONFIG_NET_POLL_CONTROLLER
        struct netpoll                  *np;
 #endif
+#ifdef CONFIG_BRIDGE_VLAN_FILTERING
+       struct net_port_vlans __rcu     *vlan_info;
+#endif
 };
 
 #define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
@@ -197,9 +212,6 @@ struct net_bridge
        bool                            nf_call_ip6tables;
        bool                            nf_call_arptables;
 #endif
-       unsigned long                   flags;
-#define BR_SET_MAC_ADDR                0x00000001
-
        u16                             group_fwd_mask;
 
        /* STP */
@@ -260,6 +272,10 @@ struct net_bridge
        struct timer_list               topology_change_timer;
        struct timer_list               gc_timer;
        struct kobject                  *ifobj;
+#ifdef CONFIG_BRIDGE_VLAN_FILTERING
+       u8                              vlan_enabled;
+       struct net_port_vlans __rcu     *vlan_info;
+#endif
 };
 
 struct br_input_skb_cb {
@@ -526,6 +542,105 @@ static inline bool br_multicast_is_router(struct net_bridge *br)
 {
        return 0;
 }
+static inline void br_mdb_init(void)
+{
+}
+static inline void br_mdb_uninit(void)
+{
+}
+#endif
+
+/* br_vlan.c */
+#ifdef CONFIG_BRIDGE_VLAN_FILTERING
+extern bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
+                              struct sk_buff *skb);
+extern int br_vlan_add(struct net_bridge *br, u16 vid);
+extern int br_vlan_delete(struct net_bridge *br, u16 vid);
+extern void br_vlan_flush(struct net_bridge *br);
+extern int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
+extern int nbp_vlan_add(struct net_bridge_port *port, u16 vid);
+extern int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
+extern void nbp_vlan_flush(struct net_bridge_port *port);
+
+static inline struct net_port_vlans *br_get_vlan_info(
+                                               const struct net_bridge *br)
+{
+       return rcu_dereference(br->vlan_info);
+}
+
+static inline struct net_port_vlans *nbp_get_vlan_info(
+                                               const struct net_bridge_port *p)
+{
+       return rcu_dereference(p->vlan_info);
+}
+
+/* Since bridge now depends on 8021Q module, but the time bridge sees the
+ * skb, the vlan tag will always be present if the frame was tagged.
+ */
+static inline int br_vlan_get_tag(const struct sk_buff *skb, u16 *vid)
+{
+       int err = 0;
+
+       if (vlan_tx_tag_present(skb))
+               *vid = vlan_tx_tag_get(skb) & VLAN_VID_MASK;
+       else {
+               *vid = 0;
+               err = -EINVAL;
+       }
+
+       return err;
+}
+#else
+static inline bool br_allowed_ingress(struct net_bridge *br,
+                                     struct net_port_vlans *v,
+                                     struct sk_buff *skb)
+{
+       return true;
+}
+
+static inline int br_vlan_add(struct net_bridge *br, u16 vid)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline int br_vlan_delete(struct net_bridge *br, u16 vid)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline void br_vlan_flush(struct net_bridge *br)
+{
+}
+
+static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline void nbp_vlan_flush(struct net_bridge_port *port)
+{
+}
+
+static inline struct net_port_vlans *br_get_vlan_info(
+                                               const struct net_bridge *br)
+{
+       return NULL;
+}
+static inline struct net_port_vlans *nbp_get_vlan_info(
+                                               const struct net_bridge_port *p)
+{
+       return NULL;
+}
+
+static inline u16 br_vlan_get_tag(const struct sk_buff *skb)
+{
+       return 0;
+}
 #endif
 
 /* br_netfilter.c */