summaryrefslogtreecommitdiff
path: root/drivers/net/ppp/pppoe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ppp/pppoe.c')
-rw-r--r--drivers/net/ppp/pppoe.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index d2408a5e43a6..b62a5e3a1c65 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -380,6 +380,9 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
* can't change.
*/
+ if (skb->pkt_type == PACKET_OTHERHOST)
+ goto abort_kfree;
+
if (sk->sk_state & PPPOX_BOUND) {
ppp_input(&po->chan, skb);
} else if (sk->sk_state & PPPOX_RELAY) {
@@ -455,6 +458,22 @@ 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);
+ if (po->pppoe_dev) {
+ dev_put(po->pppoe_dev);
+ po->pppoe_dev = NULL;
+ }
+ pppox_unbind_sock(sk);
+ release_sock(sk);
+ sock_put(sk);
+}
+
/************************************************************************
*
* Receive a PPPoE Discovery frame.
@@ -500,7 +519,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 +633,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;
@@ -820,8 +842,8 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
return err;
}
-static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *m, size_t total_len)
+static int pppoe_sendmsg(struct socket *sock, struct msghdr *m,
+ size_t total_len)
{
struct sk_buff *skb;
struct sock *sk = sock->sk;
@@ -962,8 +984,8 @@ static const struct ppp_channel_ops pppoe_chan_ops = {
.start_xmit = pppoe_xmit,
};
-static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *m, size_t total_len, int flags)
+static int pppoe_recvmsg(struct socket *sock, struct msghdr *m,
+ size_t total_len, int flags)
{
struct sock *sk = sock->sk;
struct sk_buff *skb;