summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--system-linux.c61
-rw-r--r--system.c9
-rw-r--r--system.h6
3 files changed, 76 insertions, 0 deletions
diff --git a/system-linux.c b/system-linux.c
index 2f5bbe1..c63d8d8 100644
--- a/system-linux.c
+++ b/system-linux.c
@@ -2877,6 +2877,63 @@ failure:
}
#endif
+#ifdef IFLA_XFRM_MAX
+static int system_add_xfrm_tunnel(const char *name, const char *kind,
+ const unsigned int link, struct blob_attr **tb)
+{
+ struct nl_msg *nlm;
+ struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
+ struct blob_attr *cur;
+ int ret = 0;
+
+ nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL);
+ if (!nlm)
+ return -1;
+
+ nlmsg_append(nlm, &ifi, sizeof(ifi), 0);
+ nla_put_string(nlm, IFLA_IFNAME, name);
+
+ struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO);
+ if (!linkinfo) {
+ ret = -ENOMEM;
+ goto failure;
+ }
+
+ nla_put_string(nlm, IFLA_INFO_KIND, kind);
+ struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA);
+ if (!infodata) {
+ ret = -ENOMEM;
+ goto failure;
+ }
+
+ if (link)
+ nla_put_u32(nlm, IFLA_XFRM_LINK, link);
+
+ if ((cur = tb[TUNNEL_ATTR_DATA])) {
+ struct blob_attr *tb_data[__XFRM_DATA_ATTR_MAX];
+ uint32_t if_id = 0;
+
+ blobmsg_parse(xfrm_data_attr_list.params, __XFRM_DATA_ATTR_MAX, tb_data,
+ blobmsg_data(cur), blobmsg_len(cur));
+
+ if ((cur = tb_data[XFRM_DATA_IF_ID])) {
+ if ((if_id = blobmsg_get_u32(cur)))
+ nla_put_u32(nlm, IFLA_XFRM_IF_ID, if_id);
+ }
+
+ }
+
+ nla_nest_end(nlm, infodata);
+ nla_nest_end(nlm, linkinfo);
+
+ return system_rtnl_call(nlm);
+
+failure:
+ nlmsg_free(nlm);
+ return ret;
+}
+#endif
+
#ifdef IFLA_VXLAN_MAX
static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
{
@@ -3259,6 +3316,10 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
} else if (!strcmp(str, "vtiip6")) {
return system_add_vti_tunnel(name, "vti6", link, tb, true);
#endif
+#ifdef IFLA_XFRM_MAX
+ } else if (!strcmp(str, "xfrm")) {
+ return system_add_xfrm_tunnel(name, "xfrm", link, tb);
+#endif
#ifdef IFLA_VXLAN_MAX
} else if(!strcmp(str, "vxlan")) {
return system_add_vxlan(name, link, tb, false);
diff --git a/system.c b/system.c
index dd9ab50..bbdfef7 100644
--- a/system.c
+++ b/system.c
@@ -70,6 +70,15 @@ const struct uci_blob_param_list vti_data_attr_list = {
.params = vti_data_attrs,
};
+static const struct blobmsg_policy xfrm_data_attrs[__XFRM_DATA_ATTR_MAX] = {
+ [XFRM_DATA_IF_ID] = { .name = "ifid", .type = BLOBMSG_TYPE_INT32 },
+};
+
+const struct uci_blob_param_list xfrm_data_attr_list = {
+ .n_params = __XFRM_DATA_ATTR_MAX,
+ .params = xfrm_data_attrs,
+};
+
static const struct blobmsg_policy sixrd_data_attrs[__SIXRD_DATA_ATTR_MAX] = {
[SIXRD_DATA_PREFIX] = { .name = "prefix", .type = BLOBMSG_TYPE_STRING },
[SIXRD_DATA_RELAY_PREFIX] = { .name = "relay-prefix", .type = BLOBMSG_TYPE_STRING },
diff --git a/system.h b/system.h
index 9fefcae..61c4046 100644
--- a/system.h
+++ b/system.h
@@ -63,6 +63,11 @@ enum vti_data {
__VTI_DATA_ATTR_MAX
};
+enum xfrm_data {
+ XFRM_DATA_IF_ID,
+ __XFRM_DATA_ATTR_MAX
+};
+
enum sixrd_data {
SIXRD_DATA_PREFIX,
SIXRD_DATA_RELAY_PREFIX,
@@ -86,6 +91,7 @@ enum fmr_data {
extern const struct uci_blob_param_list vxlan_data_attr_list;
extern const struct uci_blob_param_list gre_data_attr_list;
extern const struct uci_blob_param_list vti_data_attr_list;
+extern const struct uci_blob_param_list xfrm_data_attr_list;
extern const struct uci_blob_param_list sixrd_data_attr_list;
extern const struct uci_blob_param_list ipip6_data_attr_list;
extern const struct uci_blob_param_list fmr_data_attr_list;