From 87648299f8944a3268210e0315f6b5244d42fa4f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 15 Mar 2012 00:09:20 +0100 Subject: [PATCH] system-linux: add functions for adding/removing ip tunnels (currently only sit supported) --- CMakeLists.txt | 2 +- system-dummy.c | 10 +++++++ system-linux.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- system.c | 14 +++++++++ system.h | 13 ++++++++ 5 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 system.c diff --git a/CMakeLists.txt b/CMakeLists.txt index adb2c07..2062d3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ IF(APPLE) ENDIF() SET(SOURCES - main.c utils.c + main.c utils.c system.c interface.c interface-ip.c interface-event.c proto.c proto-static.c proto-shell.c config.c device.c bridge.c vlan.c ubus.c) diff --git a/system-dummy.c b/system-dummy.c index 71dad0e..401a1a9 100644 --- a/system-dummy.c +++ b/system-dummy.c @@ -206,3 +206,13 @@ time_t system_get_rtime(void) return 0; } + +int system_del_ip_tunnel(const char *name) +{ + return 0; +} + +int system_add_ip_tunnel(const char *name, struct blob_attr *attr) +{ + return 0; +} diff --git a/system-linux.c b/system-linux.c index 4a8c03d..0e6ce5a 100644 --- a/system-linux.c +++ b/system-linux.c @@ -5,12 +5,19 @@ #include #include +#include +#include + +#include +#include + #include #include +#include #include #include +#include #include -#include #include #include @@ -942,3 +949,87 @@ time_t system_get_rtime(void) return 0; } + +#ifndef IP_DF +#define IP_DF 0x4000 +#endif + +static void tunnel_parm_init(struct ip_tunnel_parm *p) +{ + memset(p, 0, sizeof(*p)); + p->iph.version = 4; + p->iph.ihl = 5; + p->iph.frag_off = htons(IP_DF); +} + +static int tunnel_ioctl(const char *name, int cmd, void *p) +{ + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + ifr.ifr_ifru.ifru_data = p; + return ioctl(sock_ioctl, cmd, &ifr); +} + +int system_del_ip_tunnel(const char *name) +{ + struct ip_tunnel_parm p; + + tunnel_parm_init(&p); + return tunnel_ioctl(name, SIOCDELTUNNEL, &p); +} + +static int parse_ipaddr(struct blob_attr *attr, __be32 *addr) +{ + if (!attr) + return 1; + + return inet_pton(AF_INET, blobmsg_data(attr), (void *) addr); +} + + +int system_add_ip_tunnel(const char *name, struct blob_attr *attr) +{ + struct blob_attr *tb[__TUNNEL_ATTR_MAX]; + struct blob_attr *cur; + struct ip_tunnel_parm p; + const char *base, *str; + int cmd = SIOCADDTUNNEL; + + system_del_ip_tunnel(name); + + tunnel_parm_init(&p); + + blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb, + blob_data(attr), blob_len(attr)); + + cur = tb[TUNNEL_ATTR_TYPE]; + if (!cur) + return -EINVAL; + + str = blobmsg_data(cur); + if (!strcmp(str, "sit")) { + p.iph.protocol = IPPROTO_IPV6; + base = "sit0"; + } else + return -EINVAL; + + if (!parse_ipaddr(tb[TUNNEL_ATTR_LOCAL], &p.iph.saddr)) + return -EINVAL; + + if (!parse_ipaddr(tb[TUNNEL_ATTR_REMOTE], &p.iph.daddr)) + return -EINVAL; + + if ((cur = tb[TUNNEL_ATTR_TTL])) { + unsigned int val = blobmsg_get_u32(cur); + + if (val > 255) + return -EINVAL; + + p.iph.ttl = val; + } + + strncpy(p.name, name, sizeof(p.name)); + return tunnel_ioctl(base, cmd, &p); +} diff --git a/system.c b/system.c new file mode 100644 index 0000000..d85f7eb --- /dev/null +++ b/system.c @@ -0,0 +1,14 @@ +#include "netifd.h" +#include "system.h" + +static const struct blobmsg_policy tunnel_attrs[__TUNNEL_ATTR_MAX] = { + [TUNNEL_ATTR_TYPE] = { "mode", BLOBMSG_TYPE_STRING }, + [TUNNEL_ATTR_LOCAL] = { "local", BLOBMSG_TYPE_STRING }, + [TUNNEL_ATTR_REMOTE] = { "remote", BLOBMSG_TYPE_STRING }, + [TUNNEL_ATTR_TTL] = { "ttl", BLOBMSG_TYPE_INT32 }, +}; + +const struct config_param_list tunnel_attr_list = { + .n_params = __TUNNEL_ATTR_MAX, + .params = tunnel_attrs, +}; diff --git a/system.h b/system.h index 6de6b08..05fbcae 100644 --- a/system.h +++ b/system.h @@ -6,6 +6,16 @@ #include "device.h" #include "interface-ip.h" +enum tunnel_param { + TUNNEL_ATTR_TYPE, + TUNNEL_ATTR_REMOTE, + TUNNEL_ATTR_LOCAL, + TUNNEL_ATTR_TTL, + __TUNNEL_ATTR_MAX +}; + +const struct config_param_list tunnel_attr_list; + enum bridge_opt { /* stp and forward delay always set */ BRIDGE_OPT_AGEING_TIME = (1 << 0), @@ -49,6 +59,9 @@ int system_add_route(struct device *dev, struct device_route *route); int system_del_route(struct device *dev, struct device_route *route); int system_flush_routes(void); +int system_del_ip_tunnel(const char *name); +int system_add_ip_tunnel(const char *name, struct blob_attr *attr); + time_t system_get_rtime(void); #endif -- 2.11.0