diff options
author | David S. Miller <davem@davemloft.net> | 2011-07-04 04:44:29 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-07-06 01:34:52 -0400 |
commit | ce06b03e60fc19c680d1bf873e779bf11c2fc518 (patch) | |
tree | 7028330a054a0d614a85c315de01a297f0daf4f0 /net/packet/af_packet.c | |
parent | f8bae99ee5030625a4e7f0d87784191882292f0e (diff) |
packet: Add helpers to register/unregister ->prot_hook
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 103 |
1 files changed, 59 insertions, 44 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 461b16fa1c52..bb281bf330aa 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -222,6 +222,55 @@ struct packet_skb_cb { | |||
222 | 222 | ||
223 | #define PACKET_SKB_CB(__skb) ((struct packet_skb_cb *)((__skb)->cb)) | 223 | #define PACKET_SKB_CB(__skb) ((struct packet_skb_cb *)((__skb)->cb)) |
224 | 224 | ||
225 | static inline struct packet_sock *pkt_sk(struct sock *sk) | ||
226 | { | ||
227 | return (struct packet_sock *)sk; | ||
228 | } | ||
229 | |||
230 | /* register_prot_hook must be invoked with the po->bind_lock held, | ||
231 | * or from a context in which asynchronous accesses to the packet | ||
232 | * socket is not possible (packet_create()). | ||
233 | */ | ||
234 | static void register_prot_hook(struct sock *sk) | ||
235 | { | ||
236 | struct packet_sock *po = pkt_sk(sk); | ||
237 | if (!po->running) { | ||
238 | dev_add_pack(&po->prot_hook); | ||
239 | sock_hold(sk); | ||
240 | po->running = 1; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | /* {,__}unregister_prot_hook() must be invoked with the po->bind_lock | ||
245 | * held. If the sync parameter is true, we will temporarily drop | ||
246 | * the po->bind_lock and do a synchronize_net to make sure no | ||
247 | * asynchronous packet processing paths still refer to the elements | ||
248 | * of po->prot_hook. If the sync parameter is false, it is the | ||
249 | * callers responsibility to take care of this. | ||
250 | */ | ||
251 | static void __unregister_prot_hook(struct sock *sk, bool sync) | ||
252 | { | ||
253 | struct packet_sock *po = pkt_sk(sk); | ||
254 | |||
255 | po->running = 0; | ||
256 | __dev_remove_pack(&po->prot_hook); | ||
257 | __sock_put(sk); | ||
258 | |||
259 | if (sync) { | ||
260 | spin_unlock(&po->bind_lock); | ||
261 | synchronize_net(); | ||
262 | spin_lock(&po->bind_lock); | ||
263 | } | ||
264 | } | ||
265 | |||
266 | static void unregister_prot_hook(struct sock *sk, bool sync) | ||
267 | { | ||
268 | struct packet_sock *po = pkt_sk(sk); | ||
269 | |||
270 | if (po->running) | ||
271 | __unregister_prot_hook(sk, sync); | ||
272 | } | ||
273 | |||
225 | static inline __pure struct page *pgv_to_page(void *addr) | 274 | static inline __pure struct page *pgv_to_page(void *addr) |
226 | { | 275 | { |
227 | if (is_vmalloc_addr(addr)) | 276 | if (is_vmalloc_addr(addr)) |
@@ -324,11 +373,6 @@ static inline void packet_increment_head(struct packet_ring_buffer *buff) | |||
324 | buff->head = buff->head != buff->frame_max ? buff->head+1 : 0; | 373 | buff->head = buff->head != buff->frame_max ? buff->head+1 : 0; |
325 | } | 374 | } |
326 | 375 | ||
327 | static inline struct packet_sock *pkt_sk(struct sock *sk) | ||
328 | { | ||
329 | return (struct packet_sock *)sk; | ||
330 | } | ||
331 | |||
332 | static void packet_sock_destruct(struct sock *sk) | 376 | static void packet_sock_destruct(struct sock *sk) |
333 | { | 377 | { |
334 | skb_queue_purge(&sk->sk_error_queue); | 378 | skb_queue_purge(&sk->sk_error_queue); |
@@ -1337,15 +1381,7 @@ static int packet_release(struct socket *sock) | |||
1337 | spin_unlock_bh(&net->packet.sklist_lock); | 1381 | spin_unlock_bh(&net->packet.sklist_lock); |
1338 | 1382 | ||
1339 | spin_lock(&po->bind_lock); | 1383 | spin_lock(&po->bind_lock); |
1340 | if (po->running) { | 1384 | unregister_prot_hook(sk, false); |
1341 | /* | ||
1342 | * Remove from protocol table | ||
1343 | */ | ||
1344 | po->running = 0; | ||
1345 | po->num = 0; | ||
1346 | __dev_remove_pack(&po->prot_hook); | ||
1347 | __sock_put(sk); | ||
1348 | } | ||
1349 | if (po->prot_hook.dev) { | 1385 | if (po->prot_hook.dev) { |
1350 | dev_put(po->prot_hook.dev); | 1386 | dev_put(po->prot_hook.dev); |
1351 | po->prot_hook.dev = NULL; | 1387 | po->prot_hook.dev = NULL; |
@@ -1392,15 +1428,7 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc | |||
1392 | lock_sock(sk); | 1428 | lock_sock(sk); |
1393 | 1429 | ||
1394 | spin_lock(&po->bind_lock); | 1430 | spin_lock(&po->bind_lock); |
1395 | if (po->running) { | 1431 | unregister_prot_hook(sk, true); |
1396 | __sock_put(sk); | ||
1397 | po->running = 0; | ||
1398 | po->num = 0; | ||
1399 | spin_unlock(&po->bind_lock); | ||
1400 | dev_remove_pack(&po->prot_hook); | ||
1401 | spin_lock(&po->bind_lock); | ||
1402 | } | ||
1403 | |||
1404 | po->num = protocol; | 1432 | po->num = protocol; |
1405 | po->prot_hook.type = protocol; | 1433 | po->prot_hook.type = protocol; |
1406 | if (po->prot_hook.dev) | 1434 | if (po->prot_hook.dev) |
@@ -1413,9 +1441,7 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc | |||
1413 | goto out_unlock; | 1441 | goto out_unlock; |
1414 | 1442 | ||
1415 | if (!dev || (dev->flags & IFF_UP)) { | 1443 | if (!dev || (dev->flags & IFF_UP)) { |
1416 | dev_add_pack(&po->prot_hook); | 1444 | register_prot_hook(sk); |
1417 | sock_hold(sk); | ||
1418 | po->running = 1; | ||
1419 | } else { | 1445 | } else { |
1420 | sk->sk_err = ENETDOWN; | 1446 | sk->sk_err = ENETDOWN; |
1421 | if (!sock_flag(sk, SOCK_DEAD)) | 1447 | if (!sock_flag(sk, SOCK_DEAD)) |
@@ -1542,9 +1568,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol, | |||
1542 | 1568 | ||
1543 | if (proto) { | 1569 | if (proto) { |
1544 | po->prot_hook.type = proto; | 1570 | po->prot_hook.type = proto; |
1545 | dev_add_pack(&po->prot_hook); | 1571 | register_prot_hook(sk); |
1546 | sock_hold(sk); | ||
1547 | po->running = 1; | ||
1548 | } | 1572 | } |
1549 | 1573 | ||
1550 | spin_lock_bh(&net->packet.sklist_lock); | 1574 | spin_lock_bh(&net->packet.sklist_lock); |
@@ -2240,9 +2264,7 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void | |||
2240 | if (dev->ifindex == po->ifindex) { | 2264 | if (dev->ifindex == po->ifindex) { |
2241 | spin_lock(&po->bind_lock); | 2265 | spin_lock(&po->bind_lock); |
2242 | if (po->running) { | 2266 | if (po->running) { |
2243 | __dev_remove_pack(&po->prot_hook); | 2267 | __unregister_prot_hook(sk, false); |
2244 | __sock_put(sk); | ||
2245 | po->running = 0; | ||
2246 | sk->sk_err = ENETDOWN; | 2268 | sk->sk_err = ENETDOWN; |
2247 | if (!sock_flag(sk, SOCK_DEAD)) | 2269 | if (!sock_flag(sk, SOCK_DEAD)) |
2248 | sk->sk_error_report(sk); | 2270 | sk->sk_error_report(sk); |
@@ -2259,11 +2281,8 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void | |||
2259 | case NETDEV_UP: | 2281 | case NETDEV_UP: |
2260 | if (dev->ifindex == po->ifindex) { | 2282 | if (dev->ifindex == po->ifindex) { |
2261 | spin_lock(&po->bind_lock); | 2283 | spin_lock(&po->bind_lock); |
2262 | if (po->num && !po->running) { | 2284 | if (po->num) |
2263 | dev_add_pack(&po->prot_hook); | 2285 | register_prot_hook(sk); |
2264 | sock_hold(sk); | ||
2265 | po->running = 1; | ||
2266 | } | ||
2267 | spin_unlock(&po->bind_lock); | 2286 | spin_unlock(&po->bind_lock); |
2268 | } | 2287 | } |
2269 | break; | 2288 | break; |
@@ -2530,10 +2549,8 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, | |||
2530 | was_running = po->running; | 2549 | was_running = po->running; |
2531 | num = po->num; | 2550 | num = po->num; |
2532 | if (was_running) { | 2551 | if (was_running) { |
2533 | __dev_remove_pack(&po->prot_hook); | ||
2534 | po->num = 0; | 2552 | po->num = 0; |
2535 | po->running = 0; | 2553 | __unregister_prot_hook(sk, false); |
2536 | __sock_put(sk); | ||
2537 | } | 2554 | } |
2538 | spin_unlock(&po->bind_lock); | 2555 | spin_unlock(&po->bind_lock); |
2539 | 2556 | ||
@@ -2564,11 +2581,9 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, | |||
2564 | mutex_unlock(&po->pg_vec_lock); | 2581 | mutex_unlock(&po->pg_vec_lock); |
2565 | 2582 | ||
2566 | spin_lock(&po->bind_lock); | 2583 | spin_lock(&po->bind_lock); |
2567 | if (was_running && !po->running) { | 2584 | if (was_running) { |
2568 | sock_hold(sk); | ||
2569 | po->running = 1; | ||
2570 | po->num = num; | 2585 | po->num = num; |
2571 | dev_add_pack(&po->prot_hook); | 2586 | register_prot_hook(sk); |
2572 | } | 2587 | } |
2573 | spin_unlock(&po->bind_lock); | 2588 | spin_unlock(&po->bind_lock); |
2574 | 2589 | ||