aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/if_bridge.h3
-rw-r--r--net/bridge/br_input.c20
-rw-r--r--net/bridge/br_private.h3
-rw-r--r--net/core/dev.c31
4 files changed, 32 insertions, 25 deletions
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index fd1b6eb94a5f..4ff211d98769 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -105,7 +105,8 @@ struct __fdb_entry
105#include <linux/netdevice.h> 105#include <linux/netdevice.h>
106 106
107extern void brioctl_set(int (*ioctl_hook)(unsigned int, void __user *)); 107extern void brioctl_set(int (*ioctl_hook)(unsigned int, void __user *));
108extern int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb); 108extern struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
109 struct sk_buff *skb);
109extern int (*br_should_route_hook)(struct sk_buff **pskb); 110extern int (*br_should_route_hook)(struct sk_buff **pskb);
110 111
111#endif 112#endif
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index a260679afad8..2f5c379d9ffa 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -121,13 +121,11 @@ static inline int is_link_local(const unsigned char *dest)
121 121
122/* 122/*
123 * Called via br_handle_frame_hook. 123 * Called via br_handle_frame_hook.
124 * Return 0 if *pskb should be processed furthur 124 * Return NULL if skb is handled
125 * 1 if *pskb is handled
126 * note: already called with rcu_read_lock (preempt_disabled) 125 * note: already called with rcu_read_lock (preempt_disabled)
127 */ 126 */
128int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb) 127struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
129{ 128{
130 struct sk_buff *skb = *pskb;
131 const unsigned char *dest = eth_hdr(skb)->h_dest; 129 const unsigned char *dest = eth_hdr(skb)->h_dest;
132 130
133 if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) 131 if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
@@ -135,15 +133,15 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
135 133
136 if (unlikely(is_link_local(dest))) { 134 if (unlikely(is_link_local(dest))) {
137 skb->pkt_type = PACKET_HOST; 135 skb->pkt_type = PACKET_HOST;
138 return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, 136
139 NULL, br_handle_local_finish) != 0; 137 return (NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
138 NULL, br_handle_local_finish) == 0) ? skb : NULL;
140 } 139 }
141 140
142 if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) { 141 if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) {
143 if (br_should_route_hook) { 142 if (br_should_route_hook) {
144 if (br_should_route_hook(pskb)) 143 if (br_should_route_hook(&skb))
145 return 0; 144 return skb;
146 skb = *pskb;
147 dest = eth_hdr(skb)->h_dest; 145 dest = eth_hdr(skb)->h_dest;
148 } 146 }
149 147
@@ -152,10 +150,10 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
152 150
153 NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, 151 NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
154 br_handle_frame_finish); 152 br_handle_frame_finish);
155 return 1; 153 return NULL;
156 } 154 }
157 155
158err: 156err:
159 kfree_skb(skb); 157 kfree_skb(skb);
160 return 1; 158 return NULL;
161} 159}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 2b73de6c0b47..fab8ce0ce88d 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -182,7 +182,8 @@ extern void br_features_recompute(struct net_bridge *br);
182 182
183/* br_input.c */ 183/* br_input.c */
184extern int br_handle_frame_finish(struct sk_buff *skb); 184extern int br_handle_frame_finish(struct sk_buff *skb);
185extern int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb); 185extern struct sk_buff *br_handle_frame(struct net_bridge_port *p,
186 struct sk_buff *skb);
186 187
187/* br_ioctl.c */ 188/* br_ioctl.c */
188extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); 189extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
diff --git a/net/core/dev.c b/net/core/dev.c
index d23972f56fc7..7f31d0f88424 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1687,31 +1687,37 @@ static inline int deliver_skb(struct sk_buff *skb,
1687} 1687}
1688 1688
1689#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE) 1689#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)
1690int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb); 1690/* These hooks defined here for ATM */
1691struct net_bridge; 1691struct net_bridge;
1692struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, 1692struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
1693 unsigned char *addr); 1693 unsigned char *addr);
1694void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); 1694void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) __read_mostly;
1695 1695
1696static __inline__ int handle_bridge(struct sk_buff **pskb, 1696/*
1697 struct packet_type **pt_prev, int *ret, 1697 * If bridge module is loaded call bridging hook.
1698 struct net_device *orig_dev) 1698 * returns NULL if packet was consumed.
1699 */
1700struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
1701 struct sk_buff *skb) __read_mostly;
1702static inline struct sk_buff *handle_bridge(struct sk_buff *skb,
1703 struct packet_type **pt_prev, int *ret,
1704 struct net_device *orig_dev)
1699{ 1705{
1700 struct net_bridge_port *port; 1706 struct net_bridge_port *port;
1701 1707
1702 if ((*pskb)->pkt_type == PACKET_LOOPBACK || 1708 if (skb->pkt_type == PACKET_LOOPBACK ||
1703 (port = rcu_dereference((*pskb)->dev->br_port)) == NULL) 1709 (port = rcu_dereference(skb->dev->br_port)) == NULL)
1704 return 0; 1710 return skb;
1705 1711
1706 if (*pt_prev) { 1712 if (*pt_prev) {
1707 *ret = deliver_skb(*pskb, *pt_prev, orig_dev); 1713 *ret = deliver_skb(skb, *pt_prev, orig_dev);
1708 *pt_prev = NULL; 1714 *pt_prev = NULL;
1709 } 1715 }
1710 1716
1711 return br_handle_frame_hook(port, pskb); 1717 return br_handle_frame_hook(port, skb);
1712} 1718}
1713#else 1719#else
1714#define handle_bridge(skb, pt_prev, ret, orig_dev) (0) 1720#define handle_bridge(skb, pt_prev, ret, orig_dev) (skb)
1715#endif 1721#endif
1716 1722
1717#ifdef CONFIG_NET_CLS_ACT 1723#ifdef CONFIG_NET_CLS_ACT
@@ -1818,7 +1824,8 @@ int netif_receive_skb(struct sk_buff *skb)
1818ncls: 1824ncls:
1819#endif 1825#endif
1820 1826
1821 if (handle_bridge(&skb, &pt_prev, &ret, orig_dev)) 1827 skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
1828 if (!skb)
1822 goto out; 1829 goto out;
1823 1830
1824 type = skb->protocol; 1831 type = skb->protocol;