Skip to content

Commit ce06b03

Browse files
committed
packet: Add helpers to register/unregister ->prot_hook
Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent f8bae99 commit ce06b03

File tree

1 file changed

+59
-44
lines changed

1 file changed

+59
-44
lines changed

net/packet/af_packet.c

Lines changed: 59 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,55 @@ struct packet_skb_cb {
222222

223223
#define PACKET_SKB_CB(__skb) ((struct packet_skb_cb *)((__skb)->cb))
224224

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+
225274
static inline __pure struct page *pgv_to_page(void *addr)
226275
{
227276
if (is_vmalloc_addr(addr))
@@ -324,11 +373,6 @@ static inline void packet_increment_head(struct packet_ring_buffer *buff)
324373
buff->head = buff->head != buff->frame_max ? buff->head+1 : 0;
325374
}
326375

327-
static inline struct packet_sock *pkt_sk(struct sock *sk)
328-
{
329-
return (struct packet_sock *)sk;
330-
}
331-
332376
static void packet_sock_destruct(struct sock *sk)
333377
{
334378
skb_queue_purge(&sk->sk_error_queue);
@@ -1337,15 +1381,7 @@ static int packet_release(struct socket *sock)
13371381
spin_unlock_bh(&net->packet.sklist_lock);
13381382

13391383
spin_lock(&po->bind_lock);
1340-
if (po->running) {
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-
}
1384+
unregister_prot_hook(sk, false);
13491385
if (po->prot_hook.dev) {
13501386
dev_put(po->prot_hook.dev);
13511387
po->prot_hook.dev = NULL;
@@ -1392,15 +1428,7 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc
13921428
lock_sock(sk);
13931429

13941430
spin_lock(&po->bind_lock);
1395-
if (po->running) {
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-
1431+
unregister_prot_hook(sk, true);
14041432
po->num = protocol;
14051433
po->prot_hook.type = protocol;
14061434
if (po->prot_hook.dev)
@@ -1413,9 +1441,7 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc
14131441
goto out_unlock;
14141442

14151443
if (!dev || (dev->flags & IFF_UP)) {
1416-
dev_add_pack(&po->prot_hook);
1417-
sock_hold(sk);
1418-
po->running = 1;
1444+
register_prot_hook(sk);
14191445
} else {
14201446
sk->sk_err = ENETDOWN;
14211447
if (!sock_flag(sk, SOCK_DEAD))
@@ -1542,9 +1568,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
15421568

15431569
if (proto) {
15441570
po->prot_hook.type = proto;
1545-
dev_add_pack(&po->prot_hook);
1546-
sock_hold(sk);
1547-
po->running = 1;
1571+
register_prot_hook(sk);
15481572
}
15491573

15501574
spin_lock_bh(&net->packet.sklist_lock);
@@ -2240,9 +2264,7 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void
22402264
if (dev->ifindex == po->ifindex) {
22412265
spin_lock(&po->bind_lock);
22422266
if (po->running) {
2243-
__dev_remove_pack(&po->prot_hook);
2244-
__sock_put(sk);
2245-
po->running = 0;
2267+
__unregister_prot_hook(sk, false);
22462268
sk->sk_err = ENETDOWN;
22472269
if (!sock_flag(sk, SOCK_DEAD))
22482270
sk->sk_error_report(sk);
@@ -2259,11 +2281,8 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void
22592281
case NETDEV_UP:
22602282
if (dev->ifindex == po->ifindex) {
22612283
spin_lock(&po->bind_lock);
2262-
if (po->num && !po->running) {
2263-
dev_add_pack(&po->prot_hook);
2264-
sock_hold(sk);
2265-
po->running = 1;
2266-
}
2284+
if (po->num)
2285+
register_prot_hook(sk);
22672286
spin_unlock(&po->bind_lock);
22682287
}
22692288
break;
@@ -2530,10 +2549,8 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req,
25302549
was_running = po->running;
25312550
num = po->num;
25322551
if (was_running) {
2533-
__dev_remove_pack(&po->prot_hook);
25342552
po->num = 0;
2535-
po->running = 0;
2536-
__sock_put(sk);
2553+
__unregister_prot_hook(sk, false);
25372554
}
25382555
spin_unlock(&po->bind_lock);
25392556

@@ -2564,11 +2581,9 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req,
25642581
mutex_unlock(&po->pg_vec_lock);
25652582

25662583
spin_lock(&po->bind_lock);
2567-
if (was_running && !po->running) {
2568-
sock_hold(sk);
2569-
po->running = 1;
2584+
if (was_running) {
25702585
po->num = num;
2571-
dev_add_pack(&po->prot_hook);
2586+
register_prot_hook(sk);
25722587
}
25732588
spin_unlock(&po->bind_lock);
25742589

0 commit comments

Comments
 (0)