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 | |
| parent | f8bae99ee5030625a4e7f0d87784191882292f0e (diff) | |
packet: Add helpers to register/unregister ->prot_hook
Signed-off-by: David S. Miller <davem@davemloft.net>
| -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); |
