aboutsummaryrefslogtreecommitdiffstats
path: root/net/packet/af_packet.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-07-04 04:44:29 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-06 01:34:52 -0400
commitce06b03e60fc19c680d1bf873e779bf11c2fc518 (patch)
tree7028330a054a0d614a85c315de01a297f0daf4f0 /net/packet/af_packet.c
parentf8bae99ee5030625a4e7f0d87784191882292f0e (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.c103
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
225static 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 */
234static 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 */
251static 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
266static 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
225static inline __pure struct page *pgv_to_page(void *addr) 274static 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
327static inline struct packet_sock *pkt_sk(struct sock *sk)
328{
329 return (struct packet_sock *)sk;
330}
331
332static void packet_sock_destruct(struct sock *sk) 376static 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