return ioctl(sock_ioctl, cmd, &ifr);
}
+#ifdef IFLA_IPTUN_MAX
+static int system_add_ip6_tunnel(const char *name, const unsigned int link,
+ struct blob_attr **tb)
+{
+ struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
+ NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
+ struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
+ struct blob_attr *cur;
+ int ret = 0, ttl = 0;
+
+ if (!nlm)
+ return -1;
+
+ nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
+ nla_put_string(nlm, IFLA_IFNAME, name);
+
+ if (link)
+ nla_put_u32(nlm, IFLA_LINK, link);
+
+ struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
+ if (!linkinfo) {
+ ret = -ENOMEM;
+ goto failure;
+ }
+
+ nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
+ struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
+ if (!infodata) {
+ ret = -ENOMEM;
+ goto failure;
+ }
+
+ if (link)
+ nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
+
+ if ((cur = tb[TUNNEL_ATTR_TTL]))
+ ttl = blobmsg_get_u32(cur);
+
+ nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
+ nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
+ nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
+
+ struct in6_addr in6buf;
+ if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
+ if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
+ ret = -EINVAL;
+ goto failure;
+ }
+ nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
+ }
+
+ if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
+ if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
+ ret = -EINVAL;
+ goto failure;
+ }
+ nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
+ }
+
+#ifdef IFLA_IPTUN_FMR_MAX
+ if ((cur = tb[TUNNEL_ATTR_FMRS])) {
+ struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
+
+ struct blob_attr *fmr;
+ unsigned rem, fmrcnt = 0;
+ blobmsg_for_each_attr(fmr, cur, rem) {
+ if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
+ continue;
+
+ unsigned ip4len, ip6len, ealen, offset = 6;
+ char ip6buf[48];
+ char ip4buf[16];
+
+ if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
+ ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
+ ret = -EINVAL;
+ goto failure;
+ }
+
+ struct in6_addr ip6prefix;
+ struct in_addr ip4prefix;
+ if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
+ inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
+ ret = -EINVAL;
+ goto failure;
+ }
+
+ struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
+
+ nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
+ nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
+ nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
+ nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
+ nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
+ nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
+
+ nla_nest_end(nlm, rule);
+ }
+
+ nla_nest_end(nlm, fmrs);
+ }
+#endif
+
+ nla_nest_end(nlm, infodata);
+ nla_nest_end(nlm, linkinfo);
+
+ return system_rtnl_call(nlm);
+
+failure:
+ nlmsg_free(nlm);
+ return ret;
+}
+#endif
+
#ifdef IFLA_IPTUN_MAX
#define IP6_FLOWINFO_TCLASS htonl(0x0FF00000)
static int system_add_gre_tunnel(const char *name, const char *kind,
return system_add_sit_tunnel(name, link, tb);
#ifdef IFLA_IPTUN_MAX
else if (!strcmp(str, "ipip6")) {
- struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK,
- NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
- struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC };
- int ret = 0;
-
- if (!nlm)
- return -1;
-
- nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
- nla_put_string(nlm, IFLA_IFNAME, name);
-
- if (link)
- nla_put_u32(nlm, IFLA_LINK, link);
-
- struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
- if (!linkinfo) {
- ret = -ENOMEM;
- goto failure;
- }
- nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl");
- struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
- if (!infodata) {
- ret = -ENOMEM;
- goto failure;
- }
-
- if (link)
- nla_put_u32(nlm, IFLA_IPTUN_LINK, link);
-
- nla_put_u8(nlm, IFLA_IPTUN_PROTO, IPPROTO_IPIP);
- nla_put_u8(nlm, IFLA_IPTUN_TTL, (ttl) ? ttl : 64);
- nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, 4);
-
- struct in6_addr in6buf;
- if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
- if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
- ret = -EINVAL;
- goto failure;
- }
- nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf);
- }
-
- if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
- if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
- ret = -EINVAL;
- goto failure;
- }
- nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf);
- }
-
-#ifdef IFLA_IPTUN_FMR_MAX
- if ((cur = tb[TUNNEL_ATTR_FMRS])) {
- struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS);
-
- struct blob_attr *fmr;
- unsigned rem, fmrcnt = 0;
- blobmsg_for_each_attr(fmr, cur, rem) {
- if (blobmsg_type(fmr) != BLOBMSG_TYPE_STRING)
- continue;
-
- unsigned ip4len, ip6len, ealen, offset = 6;
- char ip6buf[48];
- char ip4buf[16];
-
- if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u",
- ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) {
- ret = -EINVAL;
- goto failure;
- }
-
- struct in6_addr ip6prefix;
- struct in_addr ip4prefix;
- if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 ||
- inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) {
- ret = -EINVAL;
- goto failure;
- }
-
- struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt);
-
- nla_put(nlm, IFLA_IPTUN_FMR_IP6_PREFIX, sizeof(ip6prefix), &ip6prefix);
- nla_put(nlm, IFLA_IPTUN_FMR_IP4_PREFIX, sizeof(ip4prefix), &ip4prefix);
- nla_put_u8(nlm, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6len);
- nla_put_u8(nlm, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4len);
- nla_put_u8(nlm, IFLA_IPTUN_FMR_EA_LEN, ealen);
- nla_put_u8(nlm, IFLA_IPTUN_FMR_OFFSET, offset);
-
- nla_nest_end(nlm, rule);
- }
-
- nla_nest_end(nlm, fmrs);
- }
-#endif
-
- nla_nest_end(nlm, infodata);
- nla_nest_end(nlm, linkinfo);
-
- return system_rtnl_call(nlm);
-failure:
- nlmsg_free(nlm);
- return ret;
+ return system_add_ip6_tunnel(name, link, tb);
} else if (!strcmp(str, "greip")) {
return system_add_gre_tunnel(name, "gre", link, tb, false);
} else if (!strcmp(str, "gretapip")) {