diff options
Diffstat (limited to 'quicktun.c')
-rw-r--r-- | quicktun.c | 67 |
1 files changed, 41 insertions, 26 deletions
@@ -4,6 +4,7 @@ #include <linux/ip.h> #include <linux/netdevice.h> #include <linux/udp.h> +#include <net/dst.h> #include <net/genetlink.h> #include <net/sock.h> @@ -14,7 +15,7 @@ #define DRV_VERSION "0.1" #define DRV_DESCRIPTION "Quicktun tunnel driver" -#define QUICKTUN_TYPE_MASK 0x000f +#define QUICKTUN_MODE_MASK 0x000f #define QUICKTUN_FLAG_REMOTE_FLOAT 0x0010 #define MIN_MTU 68 @@ -65,6 +66,7 @@ static void quicktun_udp_data_ready(struct sock *sk, int bytes) int err; struct sk_buff *skb; struct quicktun_struct *tun = sk->sk_user_data; + struct iphdr *iphdr; skb = skb_recv_datagram(sk, 0, 1, &err); if (!skb) { @@ -77,7 +79,20 @@ static void quicktun_udp_data_ready(struct sock *sk, int bytes) skb_orphan(skb); skb_pull(skb, sizeof(struct udphdr)); - skb->protocol = eth_type_trans(skb, tun->dev); + + 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); + break; + } + netif_rx_ni(skb); } @@ -114,12 +129,12 @@ static void quicktun_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo strcpy(info->version, DRV_VERSION); strcpy(info->fw_version, "N/A"); - switch (tun->flags & QUICKTUN_TYPE_MASK) { - case QUICKTUN_TUN_DEV: - strcpy(info->bus_info, "tun"); + switch (tun->flags & QUICKTUN_MODE_MASK) { + case QUICKTUN_MODE_ETHERNET: + strcpy(info->bus_info, "ethernet"); break; - case QUICKTUN_TAP_DEV: - strcpy(info->bus_info, "tap"); + case QUICKTUN_MODE_IP: + strcpy(info->bus_info, "ip"); break; } } @@ -159,8 +174,16 @@ static void quicktun_net_init(struct net_device *dev) { struct quicktun_struct *tun = netdev_priv(dev); - switch (tun->flags & QUICKTUN_TYPE_MASK) { - case QUICKTUN_TUN_DEV: + switch (tun->flags & QUICKTUN_MODE_MASK) { + case QUICKTUN_MODE_ETHERNET: + dev->netdev_ops = &quicktun_tap_netdev_ops; + + ether_setup(dev); + + random_ether_addr(dev->dev_addr); + break; + + case QUICKTUN_MODE_IP: dev->netdev_ops = &quicktun_tun_netdev_ops; dev->hard_header_len = 0; @@ -170,14 +193,6 @@ static void quicktun_net_init(struct net_device *dev) dev->type = ARPHRD_NONE; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; break; - - case QUICKTUN_TAP_DEV: - dev->netdev_ops = &quicktun_tap_netdev_ops; - - ether_setup(dev); - - random_ether_addr(dev->dev_addr); - break; } } @@ -217,12 +232,12 @@ static int quicktun_cmd_create_device(struct sk_buff *skb, struct genl_info *inf if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (info->attrs[QUICKTUN_A_TYPE]) - type = nla_get_u16(info->attrs[QUICKTUN_A_TYPE]); + if (info->attrs[QUICKTUN_A_MODE]) + type = nla_get_u16(info->attrs[QUICKTUN_A_MODE]); switch (type) { - case QUICKTUN_TUN_DEV: - case QUICKTUN_TAP_DEV: + case QUICKTUN_MODE_ETHERNET: + case QUICKTUN_MODE_IP: flags |= type; break; default: @@ -246,17 +261,17 @@ static int quicktun_cmd_create_device(struct sk_buff *skb, struct genl_info *inf quicktun_net_init(dev); if (info->attrs[QUICKTUN_A_LOCAL_ADDRESS]) - tun->local_address.sin_addr.s_addr = htonl(nla_get_u32(info->attrs[QUICKTUN_A_LOCAL_ADDRESS])); + tun->local_address.sin_addr.s_addr = nla_get_be32(info->attrs[QUICKTUN_A_LOCAL_ADDRESS]); /* Set remote port to local port by default */ if (info->attrs[QUICKTUN_A_LOCAL_PORT]) - tun->remote_address.sin_port = tun->local_address.sin_port = htons(nla_get_u16(info->attrs[QUICKTUN_A_LOCAL_PORT])); + tun->remote_address.sin_port = tun->local_address.sin_port = nla_get_be16(info->attrs[QUICKTUN_A_LOCAL_PORT]); if (info->attrs[QUICKTUN_A_REMOTE_ADDRESS]) - tun->remote_address.sin_addr.s_addr = htonl(nla_get_u32(info->attrs[QUICKTUN_A_REMOTE_ADDRESS])); + tun->remote_address.sin_addr.s_addr = nla_get_be32(info->attrs[QUICKTUN_A_REMOTE_ADDRESS]); if (info->attrs[QUICKTUN_A_REMOTE_PORT]) - tun->remote_address.sin_port = htons(nla_get_u16(info->attrs[QUICKTUN_A_REMOTE_PORT])); + tun->remote_address.sin_port = nla_get_be16(info->attrs[QUICKTUN_A_REMOTE_PORT]); if (info->attrs[QUICKTUN_A_REMOTE_FLOAT]) { if(nla_get_flag(info->attrs[QUICKTUN_A_REMOTE_FLOAT])) @@ -311,7 +326,7 @@ static struct genl_family quicktun_nl_family = { static struct nla_policy quicktun_nl_policy[__QUICKTUN_A_MAX] = { [QUICKTUN_A_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 }, - [QUICKTUN_A_TYPE] = { .type = NLA_U16 }, + [QUICKTUN_A_MODE] = { .type = NLA_U16 }, [QUICKTUN_A_LOCAL_ADDRESS] = { .type = NLA_U32 }, [QUICKTUN_A_LOCAL_PORT] = { .type = NLA_U16 }, [QUICKTUN_A_REMOTE_ADDRESS] = { .type = NLA_U32 }, |