diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2011-04-14 17:07:51 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2011-04-14 17:07:51 +0200 |
commit | b476556d447c07244e71ff15d832efb19109ae29 (patch) | |
tree | df51e7bd081e9b83a7b09aa4bb680cfa3fa7f6f6 | |
parent | 888629be2dd5a0b7d2d6707efc8315c96dfb8867 (diff) | |
download | modquicktun-b476556d447c07244e71ff15d832efb19109ae29.tar modquicktun-b476556d447c07244e71ff15d832efb19109ae29.zip |
Handle packets correctly in IP mode
-rw-r--r-- | qtctl.c | 4 | ||||
-rw-r--r-- | quicktun.c | 67 | ||||
-rw-r--r-- | quicktun.h | 6 |
3 files changed, 46 insertions, 31 deletions
@@ -20,8 +20,8 @@ int main() msg = nlmsg_alloc(); genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO, QUICKTUN_CMD_CREATE_DEVICE, 1); - nla_put_u16(msg, QUICKTUN_A_TYPE, QUICKTUN_TAP_DEV); - nla_put_u32(msg, QUICKTUN_A_REMOTE_ADDRESS, ntohl(inet_addr("192.168.0.2"))); + nla_put_u16(msg, QUICKTUN_A_MODE, QUICKTUN_MODE_IP); + nla_put_u32(msg, QUICKTUN_A_REMOTE_ADDRESS, inet_addr("192.168.0.2")); nl_send_auto_complete(sock, msg); @@ -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 }, @@ -1,8 +1,8 @@ #ifndef __QUICKTUN_H #define __QUICKTUN_H -#define QUICKTUN_TUN_DEV 0x0001 -#define QUICKTUN_TAP_DEV 0x0002 +#define QUICKTUN_MODE_ETHERNET 0x0001 +#define QUICKTUN_MODE_IP 0x0002 enum { QUICKTUN_CMD_UNSPEC, @@ -16,7 +16,7 @@ enum { enum { QUICKTUN_A_UNSPEC, QUICKTUN_A_IFNAME, - QUICKTUN_A_TYPE, + QUICKTUN_A_MODE, QUICKTUN_A_LOCAL_ADDRESS, QUICKTUN_A_LOCAL_PORT, QUICKTUN_A_REMOTE_ADDRESS, |