summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--system-linux.c40
-rw-r--r--system.c2
-rw-r--r--system.h2
3 files changed, 38 insertions, 6 deletions
diff --git a/system-linux.c b/system-linux.c
index ceb5ac5..aaa8230 100644
--- a/system-linux.c
+++ b/system-linux.c
@@ -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;
}
diff --git a/system.c b/system.c
index c85d0e4..1096ad2 100644
--- 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 = {
diff --git a/system.h b/system.h
index 73ceb41..5e275ca 100644
--- 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
};