|
@@ -455,6 +455,18 @@ out:
|
|
|
return NET_RX_DROP;
|
|
|
}
|
|
|
|
|
|
+static void pppoe_unbind_sock_work(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct pppox_sock *po = container_of(work, struct pppox_sock,
|
|
|
+ proto.pppoe.padt_work);
|
|
|
+ struct sock *sk = sk_pppox(po);
|
|
|
+
|
|
|
+ lock_sock(sk);
|
|
|
+ pppox_unbind_sock(sk);
|
|
|
+ release_sock(sk);
|
|
|
+ sock_put(sk);
|
|
|
+}
|
|
|
+
|
|
|
/************************************************************************
|
|
|
*
|
|
|
* Receive a PPPoE Discovery frame.
|
|
@@ -500,7 +512,8 @@ static int pppoe_disc_rcv(struct sk_buff *skb, struct net_device *dev,
|
|
|
}
|
|
|
|
|
|
bh_unlock_sock(sk);
|
|
|
- sock_put(sk);
|
|
|
+ if (!schedule_work(&po->proto.pppoe.padt_work))
|
|
|
+ sock_put(sk);
|
|
|
}
|
|
|
|
|
|
abort:
|
|
@@ -613,6 +626,8 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
|
|
|
|
|
|
lock_sock(sk);
|
|
|
|
|
|
+ INIT_WORK(&po->proto.pppoe.padt_work, pppoe_unbind_sock_work);
|
|
|
+
|
|
|
error = -EINVAL;
|
|
|
if (sp->sa_protocol != PX_PROTO_OE)
|
|
|
goto end;
|