From 50f98aec98d066129b932e53bf33eef64896938f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 25 Apr 2011 04:38:19 +0200 Subject: Implemented tunnel list command --- quicktun.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 87 insertions(+), 8 deletions(-) (limited to 'quicktun.c') 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) -- cgit v1.2.3