--- zzzz-none-000/linux-4.4.60/net/bridge/br_private.h 2017-04-08 07:53:53.000000000 +0000 +++ dragonfly-4020-701/linux-4.4.60/net/bridge/br_private.h 2018-11-08 13:36:17.000000000 +0000 @@ -19,8 +19,12 @@ #include #include #include +#include /* struct inet_skb_param */ #include #include +#include +#include +#include #define BR_HASH_BITS 8 #define BR_HASH_SIZE (1 << BR_HASH_BITS) @@ -139,6 +143,9 @@ struct hlist_node hlist; struct net_bridge_port *dst; +#ifdef CONFIG_AVM_BRIDGE_MULTICAST_TO_UNICAST + struct hlist_head pg_list; +#endif unsigned long updated; unsigned long used; mac_addr addr; @@ -150,6 +157,16 @@ struct rcu_head rcu; }; +#ifdef CONFIG_AVM_BRIDGE_MULTICAST_TO_UNICAST +struct net_bridge_group_recipient { + struct net_bridge_port_group *group; + struct list_head list; + struct hlist_node fdb_list; + struct rcu_head rcu; + struct net_bridge_fdb_entry *recipient; +}; +#endif + struct net_bridge_port_group { struct net_bridge_port *port; struct net_bridge_port_group __rcu *next; @@ -157,6 +174,11 @@ struct rcu_head rcu; struct timer_list timer; struct br_ip addr; +#ifdef CONFIG_AVM_BRIDGE_MULTICAST_TO_UNICAST + /* the start_free is used as temp storage during rcu free */ + struct list_head recipients, *free_start; + u16 num_recipients; +#endif unsigned char state; }; @@ -219,6 +241,9 @@ struct timer_list multicast_router_timer; struct hlist_head mglist; struct hlist_node rlist; +#ifdef CONFIG_AVM_BRIDGE_MULTICAST_TO_UNICAST + u16 multicast_to_unicast_threshold; +#endif #endif #ifdef CONFIG_SYSFS @@ -267,6 +292,12 @@ bool nf_call_ip6tables; bool nf_call_arptables; #endif +#ifdef CONFIG_AVM_BRIDGE_FLOOD_RATELIMITER + atomic_t avm_flood_credits; + int avm_flood_credits_max; + int avm_flood_credits_recov_rate; + struct timer_list avm_flood_rl_timer; +#endif u16 group_fwd_mask; u16 group_fwd_mask_required; @@ -362,6 +393,24 @@ #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) +/* Add members here that must survive bridge netfilter hooks on output. Some of them + * overwrite skb->cb for their own stuff (add the appropriate structs to the union) */ +struct br_output_skb_cb { + union { + struct br_input_skb_cb input; +#ifdef CONFIG_BRIDGE_NETFILTER + struct inet_skb_parm dummy1; /* Used by br_validate_ipv4() */ + struct inet6_skb_parm dummy2; /* Used by br_validate_ipv6() */ + struct net_device *dummy3; /* Used by br_nf_forward_arp() */ +#endif + } u; +#ifdef CONFIG_AVM_BRIDGE_MULTICAST_TO_UNICAST + struct net_bridge_port_group *pg; +#endif +}; + +#define BR_OUTPUT_SKB_CB(__skb) ((struct br_output_skb_cb *)(__skb)->cb) + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING # define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb) (BR_INPUT_SKB_CB(__skb)->mrouters_only) #else @@ -504,6 +553,7 @@ void br_manage_promisc(struct net_bridge *br); /* br_input.c */ +int br_pass_frame_up(struct sk_buff *skb); int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb); rx_handler_result_t br_handle_frame(struct sk_buff **pskb); @@ -551,7 +601,8 @@ struct net_bridge_mdb_entry * br_multicast_new_group(struct net_bridge *br, struct net_bridge_port *port, struct br_ip *group); -void br_multicast_free_pg(struct rcu_head *head); +void br_multicast_delete_pg(struct net_bridge_port_group *pg); +void br_multicast_delete_recipient(struct net_bridge_group_recipient *p); struct net_bridge_port_group * br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group, struct net_bridge_port_group __rcu *next, @@ -902,13 +953,41 @@ /* br_netfilter.c */ #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) +extern int brnf_call_ebtables; int br_nf_core_init(void); void br_nf_core_fini(void); void br_netfilter_rtable_init(struct net_bridge *); +bool br_netfilter_run_hooks(void); #else static inline int br_nf_core_init(void) { return 0; } static inline void br_nf_core_fini(void) {} #define br_netfilter_rtable_init(x) +#define br_netfilter_run_hooks() false +#endif + +static inline int +BR_HOOK(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, + struct sk_buff *skb, struct net_device *in, struct net_device *out, + int (*okfn)(struct net *, struct sock *, struct sk_buff *)) +{ + if (!br_netfilter_run_hooks()) + return okfn(net, sk, skb); + + return NF_HOOK(pf, hook, net, sk, skb, in, out, okfn); +} + +/* br_bcast_rl.c */ +#ifdef CONFIG_AVM_BRIDGE_FLOOD_RATELIMITER +int br_flood_rl_init(void); +void br_flood_rl_fini(void); +void br_flood_rl_setup(struct net_bridge *br); +ssize_t br_flood_rl_set_credits(struct net_bridge *br, unsigned long v); +unsigned int br_flood_rl(struct net_bridge *br, struct sk_buff *skb, struct net_device *src_dev); +#else +#define br_flood_rl_init() (0) +#define br_flood_rl_fini() do { } while (0) +#define br_flood_rl_setup(br) do { } while (0) +#define br_flood_rl(br, skb, dev) (1) #endif /* br_stp.c */ @@ -979,6 +1058,29 @@ static inline int br_sysfs_renameif(struct net_bridge_port *p) { return 0; } static inline int br_sysfs_addbr(struct net_device *dev) { return 0; } static inline void br_sysfs_delbr(struct net_device *dev) { return; } +static inline void br_isol_remove_port(struct net_bridge_port *p) { return; } #endif /* CONFIG_SYSFS */ +#define __br_get(__hook, __default, __args ...) \ + (__hook ? (__hook(__args)) : (__default)) + +static inline void __br_notify(int group, int type, const void *data) +{ + br_notify_hook_t *notify_hook = rcu_dereference(br_notify_hook); + + if (notify_hook) + notify_hook(group, type, data); +} + + +#ifdef CONFIG_AVM_BRIDGE_ISOLATION +ssize_t br_isol_show(struct net_bridge_port *p, char *buf); +int br_isol_store(struct net_bridge_port *p, unsigned long v); +void br_isol_remove_port(struct net_bridge_port *p); +unsigned int br_isol_hook(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state); +#else +static inline void br_isol_remove_port(struct net_bridge_port *p) { return; } +#endif /* CONFIG_AVM_BRIDGE_ISOLATION */ + #endif