summaryrefslogtreecommitdiffstats
path: root/quicktun.c
diff options
context:
space:
mode:
Diffstat (limited to 'quicktun.c')
-rw-r--r--quicktun.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/quicktun.c b/quicktun.c
index 3ecc0cc..6899a05 100644
--- a/quicktun.c
+++ b/quicktun.c
@@ -43,7 +43,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 err;
+ goto drop;
vec.iov_base = skb->data;
vec.iov_len = skb->len;
@@ -55,24 +55,31 @@ static netdev_tx_t quicktun_net_xmit(struct sk_buff *skb, struct net_device *dev
msg.msg_flags = MSG_DONTWAIT;
kernel_sendmsg(tun->sock, &msg, &vec, 1, skb->len);
+
+ tun->dev->stats.tx_packets++;
+ tun->dev->stats.tx_bytes += skb->len;
}
+ else
+ goto drop;
consume_skb(skb);
return NETDEV_TX_OK;
- err:
+ drop:
kfree_skb(skb);
+ tun->dev->stats.tx_dropped++;
return NETDEV_TX_OK;
}
static void quicktun_udp_data_ready(struct sock *sk, int bytes)
{
- int err;
struct sk_buff *skb;
+ unsigned int len;
struct quicktun_struct *tun = sk->sk_user_data;
- struct iphdr *iphdr;
+ int err;
+
skb = skb_recv_datagram(sk, 0, 1, &err);
if (!skb) {
@@ -86,27 +93,45 @@ static void quicktun_udp_data_ready(struct sock *sk, int bytes)
err = skb_linearize(skb);
if (err < 0)
- goto err;
+ goto drop;
__skb_pull(skb, sizeof(struct udphdr));
+ len = skb->len;
+
switch (tun->flags & QUICKTUN_MODE_MASK) {
case QUICKTUN_MODE_ETHERNET:
skb->protocol = eth_type_trans(skb, tun->dev);
break;
+
case QUICKTUN_MODE_IP:
__skb_tunnel_rx(skb, tun->dev);
skb_reset_network_header(skb);
- iphdr = (struct iphdr*)skb->data;
- skb->protocol = htons((iphdr->version == 6) ? ETH_P_IPV6 : ETH_P_IP);
+ switch (skb->data[0] & 0xf0) {
+ case 0x40:
+ skb->protocol = htons(ETH_P_IP);
+ break;
+ case 0x60:
+ skb->protocol = htons(ETH_P_IPV6);
+ break;
+ default:
+ goto drop;
+ }
break;
+
+ default:
+ goto drop;
}
netif_rx_ni(skb);
+
+ tun->dev->stats.rx_packets++;
+ tun->dev->stats.rx_bytes += len;
return;
- err:
+ drop:
+ tun->dev->stats.rx_dropped++;
kfree_skb(skb);
}