diff options
-rw-r--r-- | include/linux/if_bridge.h | 3 | ||||
-rw-r--r-- | net/bridge/br_input.c | 20 | ||||
-rw-r--r-- | net/bridge/br_private.h | 3 | ||||
-rw-r--r-- | net/core/dev.c | 31 |
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 | ||
107 | extern void brioctl_set(int (*ioctl_hook)(unsigned int, void __user *)); | 107 | extern void brioctl_set(int (*ioctl_hook)(unsigned int, void __user *)); |
108 | extern int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb); | 108 | extern struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p, |
109 | struct sk_buff *skb); | ||
109 | extern int (*br_should_route_hook)(struct sk_buff **pskb); | 110 | extern 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 | */ |
128 | int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb) | 127 | struct 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 | ||
158 | err: | 156 | err: |
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 */ |
184 | extern int br_handle_frame_finish(struct sk_buff *skb); | 184 | extern int br_handle_frame_finish(struct sk_buff *skb); |
185 | extern int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb); | 185 | extern 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 */ |
188 | extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 189 | extern 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) |
1690 | int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb); | 1690 | /* These hooks defined here for ATM */ |
1691 | struct net_bridge; | 1691 | struct net_bridge; |
1692 | struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, | 1692 | struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, |
1693 | unsigned char *addr); | 1693 | unsigned char *addr); |
1694 | void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); | 1694 | void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) __read_mostly; |
1695 | 1695 | ||
1696 | static __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 | */ | ||
1700 | struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p, | ||
1701 | struct sk_buff *skb) __read_mostly; | ||
1702 | static 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) | |||
1818 | ncls: | 1824 | ncls: |
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; |