summaryrefslogtreecommitdiffstats
path: root/quicktun.c
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2011-04-25 04:38:19 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2011-04-25 04:38:19 +0200
commit50f98aec98d066129b932e53bf33eef64896938f (patch)
treed4dcf5577ad982b08a65a9c9f3115a2cb0342e1a /quicktun.c
parent814e3c10474fd28840d5fcbbb9224b396807cbb2 (diff)
downloadmodquicktun-50f98aec98d066129b932e53bf33eef64896938f.tar
modquicktun-50f98aec98d066129b932e53bf33eef64896938f.zip
Implemented tunnel list command
Diffstat (limited to 'quicktun.c')
-rw-r--r--quicktun.c95
1 files changed, 87 insertions, 8 deletions
diff --git a/quicktun.c b/quicktun.c
index 4bc7557..46d973a 100644
--- a/quicktun.c
+++ b/quicktun.c
@@ -143,7 +143,7 @@ static void quicktun_udp_data_ready(struct sock *sk, int bytes)
read_unlock(&sk->sk_callback_lock);
- netif_rx_ni(skb);
+ netif_rx(skb);
tun->dev->stats.rx_packets++;
tun->dev->stats.rx_bytes += len;
@@ -271,6 +271,16 @@ error:
return err;
}
+
+static struct genl_family quicktun_nl_family = {
+ .id = GENL_ID_GENERATE,
+ .name = DRV_NAME,
+ .version = 1,
+ .hdrsize = 0,
+ .maxattr = QUICKTUN_A_MAX,
+};
+
+
static int quicktun_cmd_create_device(struct sk_buff *skb, struct genl_info *info)
{
unsigned long flags = 0;
@@ -416,17 +426,81 @@ err_unlock:
return err;
}
+static void __put_tunnel_spec(struct sk_buff *skb, struct quicktun_struct *tun)
+{
+ struct nlattr *nested = nla_nest_start(skb, QUICKTUN_A_TUNNEL_SPEC);
-static struct genl_family quicktun_nl_family = {
- .id = GENL_ID_GENERATE,
- .name = DRV_NAME,
- .version = 1,
- .hdrsize = 0,
- .maxattr = QUICKTUN_A_MAX,
-};
+ nla_put_string(skb, QUICKTUN_A_IFNAME, tun->dev->name);
+ nla_put_u16(skb, QUICKTUN_A_MODE, tun->flags & QUICKTUN_MODE_MASK);
+ nla_put_u32(skb, QUICKTUN_A_LOCAL_ADDRESS, tun->local_address.sin_addr.s_addr);
+ nla_put_u16(skb, QUICKTUN_A_LOCAL_PORT, tun->local_address.sin_port);
+ nla_put_u32(skb, QUICKTUN_A_REMOTE_ADDRESS, tun->remote_address.sin_addr.s_addr);
+ nla_put_u16(skb, QUICKTUN_A_REMOTE_PORT, tun->remote_address.sin_port);
+
+ if (tun->flags & QUICKTUN_FLAG_REMOTE_FLOAT)
+ nla_put_flag(skb, QUICKTUN_A_REMOTE_FLOAT);
+
+ nla_nest_end(skb, nested);
+}
+
+static int quicktun_cmd_get_device(struct sk_buff *skb, struct genl_info *info)
+{
+ struct sk_buff *ret;
+ void *skb_head;
+ int err;
+ char *name = NULL;
+
+ ret = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (ret == NULL)
+ return -ENOMEM;
+
+ skb_head = genlmsg_put(ret, 0, info->snd_seq, &quicktun_nl_family, 0, QUICKTUN_CMD_GET_DEVICE);
+
+ if (skb_head == NULL)
+ return -ENOMEM;
+
+ if (info->attrs[QUICKTUN_A_IFNAME])
+ name = nla_data(info->attrs[QUICKTUN_A_IFNAME]);
+
+ rtnl_lock();
+
+ if (name) {
+ struct net_device *dev;
+
+ dev = __dev_get_by_name(genl_info_net(info), name);
+ if (!dev) {
+ err = -EINVAL;
+ goto err_unlock;
+ }
+
+ __put_tunnel_spec(ret, netdev_priv(dev));
+ }
+ else {
+ struct quicktun_struct *entry, *next;
+
+ list_for_each_entry_safe(entry, next, &quicktun_list, list)
+ __put_tunnel_spec(ret, entry);
+ }
+
+ rtnl_unlock();
+
+ genlmsg_end(ret, skb_head);
+
+ err = genlmsg_unicast(genl_info_net(info), ret, info->snd_pid);
+ if (err)
+ return err;
+
+ return 0;
+
+err_unlock:
+ rtnl_unlock();
+
+ return err;
+}
static struct nla_policy quicktun_nl_policy[__QUICKTUN_A_MAX] = {
+ [QUICKTUN_A_TUNNEL_SPEC] = { .type = NLA_NESTED },
[QUICKTUN_A_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
[QUICKTUN_A_MODE] = { .type = NLA_U16 },
[QUICKTUN_A_LOCAL_ADDRESS] = { .type = NLA_U32 },
@@ -447,6 +521,11 @@ static struct genl_ops quicktun_nl_ops[] = {
.doit = quicktun_cmd_delete_device,
.policy = quicktun_nl_policy,
},
+ {
+ .cmd = QUICKTUN_CMD_GET_DEVICE,
+ .doit = quicktun_cmd_get_device,
+ .policy = quicktun_nl_policy,
+ },
};
static int __init quicktun_init(void)