summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--qtctl.c162
-rw-r--r--quicktun.c60
-rw-r--r--quicktun.h4
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 <stdio.h>
+#include <string.h>
+
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
@@ -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
};