summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2011-04-18 03:54:45 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2011-04-18 03:54:45 +0200
commit814e3c10474fd28840d5fcbbb9224b396807cbb2 (patch)
tree5d355c93fa8ecfd176701d9ffc1dac5d6f255df5
parent5491a35bf8783cda3ada729bfc81426439a21452 (diff)
downloadmodquicktun-814e3c10474fd28840d5fcbbb9224b396807cbb2.tar
modquicktun-814e3c10474fd28840d5fcbbb9224b396807cbb2.zip
Shut down the socket before unregistering the device
-rw-r--r--quicktun.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/quicktun.c b/quicktun.c
index f24e25d..4bc7557 100644
--- a/quicktun.c
+++ b/quicktun.c
@@ -50,7 +50,7 @@ static netdev_tx_t quicktun_net_xmit(struct sk_buff *skb, struct net_device *dev
if (tun->remote_address.sin_addr.s_addr) {
err = skb_linearize(skb);
if (err < 0)
- goto drop;
+ goto error;
vec.iov_base = skb->data;
vec.iov_len = skb->len;
@@ -67,16 +67,16 @@ static netdev_tx_t quicktun_net_xmit(struct sk_buff *skb, struct net_device *dev
tun->dev->stats.tx_bytes += skb->len;
}
else
- goto drop;
+ goto error;
consume_skb(skb);
return NETDEV_TX_OK;
- drop:
+error:
kfree_skb(skb);
- tun->dev->stats.tx_dropped++;
+ tun->dev->stats.tx_errors++;
return NETDEV_TX_OK;
}
@@ -88,8 +88,11 @@ static void quicktun_udp_data_ready(struct sock *sk, int bytes)
int err;
+ read_lock(&sk->sk_callback_lock);
+
skb = skb_recv_datagram(sk, 0, 1, &err);
if (!skb) {
+ read_unlock(&sk->sk_callback_lock);
if (err == -EAGAIN)
return;
pr_info("Quicktun: UDP socket error %d", err);
@@ -138,13 +141,17 @@ static void quicktun_udp_data_ready(struct sock *sk, int bytes)
goto drop;
}
+ read_unlock(&sk->sk_callback_lock);
+
netif_rx_ni(skb);
tun->dev->stats.rx_packets++;
tun->dev->stats.rx_bytes += len;
return;
- drop:
+drop:
+ read_unlock(&sk->sk_callback_lock);
+
tun->dev->stats.rx_dropped++;
kfree_skb(skb);
}
@@ -259,7 +266,7 @@ static int quicktun_socket_init(struct net_device *dev)
goto error;
return 0;
- error:
+error:
sock_release(tun->sock);
return err;
}
@@ -347,11 +354,11 @@ static int quicktun_cmd_create_device(struct sk_buff *skb, struct genl_info *inf
return 0;
- err_free_sk:
+err_free_sk:
rtnl_unlock();
sock_release(tun->sock);
- err_free_dev:
+err_free_dev:
free_netdev(dev);
return err;
}
@@ -361,6 +368,8 @@ static void __quicktun_delete_device(struct net_device *dev) {
struct quicktun_struct *tun = netdev_priv(dev);
struct socket *sock = tun->sock;
+ kernel_sock_shutdown(sock, SHUT_RD);
+
list_del(&tun->list);
unregister_netdevice(dev);
@@ -401,7 +410,7 @@ static int quicktun_cmd_delete_device(struct sk_buff *skb, struct genl_info *inf
return 0;
- err_unlock:
+err_unlock:
rtnl_unlock();
return err;