From a580028dae5b7bebcc14c240fe7dac31cbd89355 Mon Sep 17 00:00:00 2001 From: Hans Dedecker Date: Tue, 29 May 2018 22:40:00 +0200 Subject: system-linux: make encaplimit configurable for ip6 tunnels (FS#1501) Make encapsulation limit of IP6 tunnels configurable for the ds-lite/map proto shell handlers as not all ISPs support the destination option header containing the tunnel encapsulation limit value as reported in FS#1501. The IP6 tunnel specific setting encaplimit is parsed as a nested json data object; setting it to ignore disables the insertion of the destination option header while a value from 0 till 255 sets the tunnel encapsulation limit accordingly in the destination option header. Signed-off-by: Hans Dedecker --- system-linux.c | 51 +++++++++++++++++++++++++++++++++------------------ system.c | 10 ++++++++++ system.h | 7 +++++++ 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/system-linux.c b/system-linux.c index 2a108e2..0127b01 100644 --- a/system-linux.c +++ b/system-linux.c @@ -2300,7 +2300,6 @@ static int system_add_ip6_tunnel(const char *name, const unsigned int 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])) { @@ -2319,26 +2318,41 @@ static int system_add_ip6_tunnel(const char *name, const unsigned int link, nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf); } -#ifdef IFLA_IPTUN_FMR_MAX if ((cur = tb[TUNNEL_ATTR_DATA])) { - struct blob_attr *dcur; - unsigned drem, fmrcnt = 0; - struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS); + struct blob_attr *tb_data[__IPIP6_DATA_ATTR_MAX]; - if (!fmrs) { - ret = -ENOMEM; - goto failure; - } + blobmsg_parse(ipip6_data_attr_list.params, __IPIP6_DATA_ATTR_MAX, tb_data, + blobmsg_data(cur), blobmsg_len(cur)); - blobmsg_for_each_attr(dcur, cur, drem) { - if (blobmsg_type(dcur) != BLOBMSG_TYPE_ARRAY || - strcmp(blobmsg_name(dcur), "fmrs") || - blobmsg_check_array(dcur, BLOBMSG_TYPE_UNSPEC) <= 0) - continue; + if ((cur = tb_data[IPIP6_DATA_ENCAPLIMIT])) { + char *str = blobmsg_get_string(cur); + + if (strcmp(str, "ignore")) { + char *e; + unsigned encap_limit = strtoul(str, &e, 0); + + if (e == str || *e || encap_limit > 255) { + ret = -EINVAL; + goto failure; + } + nla_put_u8(nlm, IFLA_IPTUN_ENCAP_LIMIT, encap_limit); + } else + nla_put_u32(nlm, IFLA_IPTUN_FLAGS, IP6_TNL_F_IGN_ENCAP_LIMIT); + } + +#ifdef IFLA_IPTUN_FMR_MAX + if ((cur = tb_data[IPIP6_DATA_FMRS])) { struct blob_attr *rcur; - unsigned rrem; - blobmsg_for_each_attr(rcur, dcur, rrem) { + unsigned rrem, fmrcnt = 0; + struct nlattr *fmrs = nla_nest_start(nlm, IFLA_IPTUN_FMRS); + + if (!fmrs) { + ret = -ENOMEM; + goto failure; + } + + blobmsg_for_each_attr(rcur, cur, rrem) { struct blob_attr *tb_fmr[__FMR_DATA_ATTR_MAX], *tb_cur; struct in6_addr ip6prefix; struct in_addr ip4prefix; @@ -2390,10 +2404,11 @@ static int system_add_ip6_tunnel(const char *name, const unsigned int link, nla_nest_end(nlm, rule); } + + nla_nest_end(nlm, fmrs); } - nla_nest_end(nlm, fmrs); - } #endif + } nla_nest_end(nlm, infodata); nla_nest_end(nlm, linkinfo); diff --git a/system.c b/system.c index e236e96..f96708d 100644 --- a/system.c +++ b/system.c @@ -79,6 +79,16 @@ const struct uci_blob_param_list sixrd_data_attr_list = { .params = sixrd_data_attrs, }; +static const struct blobmsg_policy ipip6_data_attrs[__SIXRD_DATA_ATTR_MAX] = { + [IPIP6_DATA_ENCAPLIMIT] = { .name = "encaplimit", .type = BLOBMSG_TYPE_STRING }, + [IPIP6_DATA_FMRS] = { .name = "fmrs", .type = BLOBMSG_TYPE_ARRAY }, +}; + +const struct uci_blob_param_list ipip6_data_attr_list = { + .n_params = __IPIP6_DATA_ATTR_MAX, + .params = ipip6_data_attrs, +}; + static const struct blobmsg_policy fmr_data_attrs[__FMR_DATA_ATTR_MAX] = { [FMR_DATA_PREFIX6] = { .name = "prefix6", .type = BLOBMSG_TYPE_STRING }, [FMR_DATA_PREFIX4] = { .name = "prefix4", .type = BLOBMSG_TYPE_STRING }, diff --git a/system.h b/system.h index 371a524..683dc18 100644 --- a/system.h +++ b/system.h @@ -68,6 +68,12 @@ enum sixrd_data { __SIXRD_DATA_ATTR_MAX }; +enum ipip6_data { + IPIP6_DATA_ENCAPLIMIT, + IPIP6_DATA_FMRS, + __IPIP6_DATA_ATTR_MAX +}; + enum fmr_data { FMR_DATA_PREFIX6, FMR_DATA_PREFIX4, @@ -80,6 +86,7 @@ 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 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; enum bridge_opt { -- cgit v1.2.3