From 45f7bf0ddba8e1b81db65fab30eca50da83e6be5 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 14 Apr 2011 22:50:55 +0200 Subject: Implement interface configuration and deletion --- qtctl.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- quicktun.c | 60 +++++++++++++++++++---- quicktun.h | 4 +- 3 files changed, 207 insertions(+), 19 deletions(-) diff --git a/qtctl.c b/qtctl.c index 7c3f2cf..2468846 100644 --- a/qtctl.c +++ b/qtctl.c @@ -1,3 +1,6 @@ +#include +#include + #include #include #include @@ -7,21 +10,101 @@ #include "quicktun.h" -int main() +void usage() +{ + fputs("Usage: qtctl add [ dev NAME ] [ mode { ethernet | ip } ]\n" + " [ local_address ADDRESS ] [ local_port PORT ]\n" + " [ remote_address ADDRESS ] [ remote_port PORT ]\n" + " [ remote_float ]\n" + " qtctl del dev NAME\n", stderr); + + exit(2); +} + +void add(int argc, char *argv[], struct nl_handle *sock, int family) { - struct nl_handle *sock; struct nl_msg *msg; struct nl_cb *cb; - int family; - sock = nl_handle_alloc(); - genl_connect(sock); - family = genl_ctrl_resolve(sock, "quicktun"); + int p = 1; + uint16_t mode = QUICKTUN_MODE_ETHERNET; + + char *tmp_charp; + struct in_addr tmp_addr; + unsigned long tmp_ul; + 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_MODE, QUICKTUN_MODE_IP); - nla_put_u32(msg, QUICKTUN_A_REMOTE_ADDRESS, inet_addr("192.168.0.2")); + + while ((++p) < argc) { + if (!strcmp(argv[p], "dev")) { + if ((++p) >= argc) + usage(); + + tmp_charp = strndup(argv[p], IFNAMSIZ - 1); + nla_put_string(msg, QUICKTUN_A_IFNAME, tmp_charp); + free(tmp_charp); + } + else if (!strcmp(argv[p], "mode")) { + if ((++p) >= argc) + usage(); + + if (!strcmp(argv[p], "ethernet")) + mode = QUICKTUN_MODE_ETHERNET; + else if (!strcmp(argv[p], "ip")) + mode = QUICKTUN_MODE_IP; + else + usage(); + } + else if (!strcmp(argv[p], "local_address")) { + if ((++p) >= argc) + usage(); + + if (!(inet_aton(argv[p], &tmp_addr))) + usage(); + + nla_put_u32(msg, QUICKTUN_A_LOCAL_ADDRESS, tmp_addr.s_addr); + } + else if (!strcmp(argv[p], "local_port")) { + if ((++p) >= argc) + usage(); + + tmp_ul = strtoul(argv[p], &tmp_charp, 10); + + if (*tmp_charp) + usage(); + + nla_put_u16(msg, QUICKTUN_A_LOCAL_PORT, htons((short)tmp_ul)); + } + else if (!strcmp(argv[p], "remote_address")) { + if ((++p) >= argc) + usage(); + + if (!(inet_aton(argv[p], &tmp_addr))) + usage(); + + nla_put_u32(msg, QUICKTUN_A_REMOTE_ADDRESS, tmp_addr.s_addr); + } + else if (!strcmp(argv[p], "remote_port")) { + if ((++p) >= argc) + usage(); + + tmp_ul = strtoul(argv[p], &tmp_charp, 10); + + if (*tmp_charp) + usage(); + + nla_put_u16(msg, QUICKTUN_A_REMOTE_PORT, htons((short)tmp_ul)); + } + else if (!strcmp(argv[p], "remote_float")) { + nla_put_flag(msg, QUICKTUN_A_REMOTE_FLOAT); + } + else + usage(); + } + + nla_put_u16(msg, QUICKTUN_A_MODE, mode); nl_send_auto_complete(sock, msg); @@ -31,6 +114,69 @@ int main() nl_cb_err(cb, NL_CB_DEBUG, NULL, NULL); nl_recvmsgs(sock, cb); +} + +void del(int argc, char *argv[], struct nl_handle *sock, int family) +{ + struct nl_msg *msg; + struct nl_cb *cb; + + int p = 1; + char *tmp_charp; + + int has_dev = 0; + + + msg = nlmsg_alloc(); + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO, QUICKTUN_CMD_DELETE_DEVICE, 1); + + while ((++p) < argc) { + if (!strcmp(argv[p], "dev")) { + if ((++p) >= argc) + usage(); + + if (has_dev) + usage(); + + tmp_charp = strndup(argv[p], IFNAMSIZ - 1); + nla_put_string(msg, QUICKTUN_A_IFNAME, tmp_charp); + free(tmp_charp); + + has_dev = 1; + } + } + + if (!has_dev) + usage(); + + nl_send_auto_complete(sock, msg); + + nlmsg_free(msg); + + cb = nl_cb_alloc(NL_CB_DEFAULT); + nl_cb_err(cb, NL_CB_DEBUG, NULL, NULL); + + nl_recvmsgs(sock, cb); +} + +int main(int argc, char *argv[]) +{ + struct nl_handle *sock; + int family; + + sock = nl_handle_alloc(); + genl_connect(sock); + family = genl_ctrl_resolve(sock, "quicktun"); + + if (argc < 2) + usage(); + + if (!strcmp(argv[1], "add")) + add(argc, argv, sock, family); + else if (!strcmp(argv[1], "del")) + del(argc, argv, sock, family); + else + usage(); return 0; } diff --git a/quicktun.c b/quicktun.c index b0b1e32..d16a62f 100644 --- a/quicktun.c +++ b/quicktun.c @@ -35,6 +35,7 @@ struct quicktun_struct { static void quicktun_net_uninit(struct net_device *dev) { + pr_info("quicktun_net_uninit"); } static netdev_tx_t quicktun_net_xmit(struct sk_buff *skb, struct net_device *dev) @@ -106,18 +107,18 @@ quicktun_net_change_mtu(struct net_device *dev, int new_mtu) } -static const struct net_device_ops quicktun_tun_netdev_ops = { +static const struct net_device_ops quicktun_ethernet_netdev_ops = { .ndo_uninit = quicktun_net_uninit, .ndo_start_xmit = quicktun_net_xmit, .ndo_change_mtu = quicktun_net_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, }; -static const struct net_device_ops quicktun_tap_netdev_ops = { +static const struct net_device_ops quicktun_ip_netdev_ops = { .ndo_uninit = quicktun_net_uninit, .ndo_start_xmit = quicktun_net_xmit, .ndo_change_mtu = quicktun_net_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, }; @@ -153,6 +154,7 @@ static const struct ethtool_ops quicktun_ethtool_ops = { static void quicktun_free_netdev(struct net_device *dev) { + pr_info("Quicktun: free_netdev"); } static void quicktun_setup(struct net_device *dev) @@ -176,7 +178,7 @@ static void quicktun_net_init(struct net_device *dev) switch (tun->flags & QUICKTUN_MODE_MASK) { case QUICKTUN_MODE_ETHERNET: - dev->netdev_ops = &quicktun_tap_netdev_ops; + dev->netdev_ops = &quicktun_ethernet_netdev_ops; ether_setup(dev); @@ -184,7 +186,7 @@ static void quicktun_net_init(struct net_device *dev) break; case QUICKTUN_MODE_IP: - dev->netdev_ops = &quicktun_tun_netdev_ops; + dev->netdev_ops = &quicktun_ip_netdev_ops; dev->hard_header_len = 0; dev->addr_len = 0; @@ -309,9 +311,49 @@ static int quicktun_cmd_create_device(struct sk_buff *skb, struct genl_info *inf return err; } -static int quicktun_cmd_destroy_device(struct sk_buff *skb, struct genl_info *info) +static int quicktun_cmd_delete_device(struct sk_buff *skb, struct genl_info *info) { + int err; + struct net *net = genl_info_net(info); + struct net_device *dev; + struct quicktun_struct *tun; + struct socket *sock; + char *name; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (!info->attrs[QUICKTUN_A_IFNAME]) + return -EINVAL; + + name = nla_data(info->attrs[QUICKTUN_A_IFNAME]); + + dev = dev_get_by_name(net, name); + if (!dev) + return -EINVAL; + + if (dev->netdev_ops != &quicktun_ethernet_netdev_ops && dev->netdev_ops != &quicktun_ip_netdev_ops) { + err = -EINVAL; + goto err; + } + + tun = netdev_priv(dev); + sock = tun->sock; + + rtnl_lock(); + dev_put(dev); + unregister_netdevice(dev); + rtnl_unlock(); + + pr_info("quicktun: release sock"); + sock_release(sock); + return 0; + +err: + dev_put(dev); + + return err; } @@ -341,8 +383,8 @@ static struct genl_ops quicktun_nl_ops[] = { .policy = quicktun_nl_policy, }, { - .cmd = QUICKTUN_CMD_DESTROY_DEVICE, - .doit = quicktun_cmd_destroy_device, + .cmd = QUICKTUN_CMD_DELETE_DEVICE, + .doit = quicktun_cmd_delete_device, .policy = quicktun_nl_policy, }, }; diff --git a/quicktun.h b/quicktun.h index 3eb6b04..b002050 100644 --- a/quicktun.h +++ b/quicktun.h @@ -7,8 +7,8 @@ enum { QUICKTUN_CMD_UNSPEC, QUICKTUN_CMD_CREATE_DEVICE, - QUICKTUN_CMD_MODIFY_DEVICE, - QUICKTUN_CMD_DESTROY_DEVICE, + QUICKTUN_CMD_CHANGE_DEVICE, + QUICKTUN_CMD_DELETE_DEVICE, QUICKTUN_CMD_GET_DEVICE, __QUICKTUN_CMD_MAX }; -- cgit v1.2.3