Add 6rd options to tunnel spec.
authorStéphan Kochen <stephan@kochen.nl>
Sun, 17 Jun 2012 15:26:35 +0000 (17:26 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Mon, 18 Jun 2012 21:03:31 +0000 (23:03 +0200)
This patch adds support for setting the 6rd tunnel options. These are the same
options normally specified with `ip tunnel 6rd ...`.

Signed-off-by: Stéphan Kochen <stephan@kochen.nl>
system-linux.c
system.c
system.h

index ceb5ac5..aaa8230 100644 (file)
@@ -1026,7 +1026,7 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
        struct blob_attr *cur;
        struct ip_tunnel_parm p;
        const char *base, *str;
-       int cmd = SIOCADDTUNNEL;
+       bool is_sit;
 
        system_del_ip_tunnel(name);
 
@@ -1035,12 +1035,12 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
        blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
                blob_data(attr), blob_len(attr));
 
-       cur = tb[TUNNEL_ATTR_TYPE];
-       if (!cur)
+       if (!(cur = tb[TUNNEL_ATTR_TYPE]))
                return -EINVAL;
-
        str = blobmsg_data(cur);
-       if (!strcmp(str, "sit")) {
+       is_sit = !strcmp(str, "sit");
+
+       if (is_sit) {
                p.iph.protocol = IPPROTO_IPV6;
                base = "sit0";
        } else
@@ -1062,5 +1062,33 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
        }
 
        strncpy(p.name, name, sizeof(p.name));
-       return tunnel_ioctl(base, cmd, &p);
+       if (tunnel_ioctl(base, SIOCADDTUNNEL, &p) < 0)
+               return -1;
+
+       cur = tb[TUNNEL_ATTR_6RD_PREFIX];
+       if (cur && is_sit) {
+               unsigned int mask;
+               struct ip_tunnel_6rd p6;
+
+               memset(&p6, 0, sizeof(p6));
+
+               if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
+                                       &p6.prefix, &mask) || mask > 128)
+                       return -EINVAL;
+               p6.prefixlen = mask;
+
+               if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
+                       if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
+                                               &p6.relay_prefix, &mask) || mask > 32)
+                               return -EINVAL;
+                       p6.relay_prefixlen = mask;
+               }
+
+               if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
+                       system_del_ip_tunnel(name);
+                       return -1;
+               }
+       }
+
+       return 0;
 }
index c85d0e4..1096ad2 100644 (file)
--- a/system.c
+++ b/system.c
@@ -19,6 +19,8 @@ static const struct blobmsg_policy tunnel_attrs[__TUNNEL_ATTR_MAX] = {
        [TUNNEL_ATTR_LOCAL] = { "local", BLOBMSG_TYPE_STRING },
        [TUNNEL_ATTR_REMOTE] = { "remote", BLOBMSG_TYPE_STRING },
        [TUNNEL_ATTR_TTL] = { "ttl", BLOBMSG_TYPE_INT32 },
+       [TUNNEL_ATTR_6RD_PREFIX] = { "6rd-prefix", BLOBMSG_TYPE_STRING },
+       [TUNNEL_ATTR_6RD_RELAY_PREFIX] = { "6rd-relay-prefix", BLOBMSG_TYPE_STRING },
 };
 
 const struct config_param_list tunnel_attr_list = {
index 73ceb41..5e275ca 100644 (file)
--- a/system.h
+++ b/system.h
@@ -24,6 +24,8 @@ enum tunnel_param {
        TUNNEL_ATTR_REMOTE,
        TUNNEL_ATTR_LOCAL,
        TUNNEL_ATTR_TTL,
+       TUNNEL_ATTR_6RD_PREFIX,
+       TUNNEL_ATTR_6RD_RELAY_PREFIX,
        __TUNNEL_ATTR_MAX
 };