summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--qtctl.c4
-rw-r--r--quicktun.c67
-rw-r--r--quicktun.h6
3 files changed, 46 insertions, 31 deletions
diff --git a/qtctl.c b/qtctl.c
index e601ad9..7c3f2cf 100644
--- a/qtctl.c
+++ b/qtctl.c
@@ -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);
diff --git a/quicktun.c b/quicktun.c
index e745eb1..b0b1e32 100644
--- a/quicktun.c
+++ b/quicktun.c
@@ -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 },
diff --git a/quicktun.h b/quicktun.h
index a363491..3eb6b04 100644
--- a/quicktun.h
+++ b/quicktun.h
@@ -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,