From 7573880ac042c6e5c8d48b1ad83d357b5e02743b Mon Sep 17 00:00:00 2001 From: Hans Dedecker Date: Fri, 19 May 2017 12:05:55 +0200 Subject: system-linux: parse 6rd specific settings as nested json data object Parse 6rd specific settings prefix, relay-prefix as nested json data objects. At the same time improve 6rd error handling. Signed-off-by: Hans Dedecker --- system-linux.c | 89 ++++++++++++++++++++++++++++++++++++++-------------------- system.c | 12 ++++++-- system.h | 7 +++++ 3 files changed, 76 insertions(+), 32 deletions(-) diff --git a/system-linux.c b/system-linux.c index ddc31d8..0ac4ae6 100644 --- a/system-linux.c +++ b/system-linux.c @@ -81,6 +81,9 @@ static struct nl_sock *sock_rtnl = NULL; static int cb_rtnl_event(struct nl_msg *msg, void *arg); static void handle_hotplug_event(struct uloop_fd *u, unsigned int events); +static int system_add_proto_tunnel(const char *name, const uint8_t proto, + const unsigned int link, struct blob_attr **tb); +static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb); static char dev_buf[256]; @@ -2705,6 +2708,59 @@ failure: } #endif +static int system_add_sit_tunnel(const char *name, const unsigned int link, struct blob_attr **tb) +{ + struct blob_attr *cur; + int ret = 0; + + if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0) + return -1; + +#ifdef SIOCADD6RD + if ((cur = tb[TUNNEL_ATTR_DATA])) { + struct blob_attr *tb_data[__SIXRD_DATA_ATTR_MAX]; + unsigned int mask; + struct ip_tunnel_6rd p6; + + blobmsg_parse(sixrd_data_attr_list.params, __SIXRD_DATA_ATTR_MAX, tb_data, + blobmsg_data(cur), blobmsg_len(cur)); + + memset(&p6, 0, sizeof(p6)); + + if ((cur = tb_data[SIXRD_DATA_PREFIX])) { + if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur), + &p6.prefix, &mask) || mask > 128) { + ret = -EINVAL; + goto failure; + } + + p6.prefixlen = mask; + } + + if ((cur = tb[SIXRD_DATA_RELAY_PREFIX])) { + if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur), + &p6.relay_prefix, &mask) || mask > 32) { + ret = -EINVAL; + goto failure; + } + + p6.relay_prefixlen = mask; + } + + if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) { + ret = -1; + goto failure; + } + } +#endif + + return ret; + +failure: + __system_del_ip_tunnel(name, tb); + return ret; +} + static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb) { struct blob_attr *cur; @@ -2853,37 +2909,10 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr) link = iface->l3_dev.dev->ifindex; } - if (!strcmp(str, "sit")) { - if (system_add_proto_tunnel(name, IPPROTO_IPV6, link, tb) < 0) - return -1; - -#ifdef SIOCADD6RD - if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) { - 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, tb); - return -1; - } - } -#endif + if (!strcmp(str, "sit")) + return system_add_sit_tunnel(name, link, tb); #ifdef IFLA_IPTUN_MAX - } else if (!strcmp(str, "ipip6")) { + 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 }; diff --git a/system.c b/system.c index 3d4a979..bf3fd77 100644 --- a/system.c +++ b/system.c @@ -23,8 +23,6 @@ static const struct blobmsg_policy tunnel_attrs[__TUNNEL_ATTR_MAX] = { [TUNNEL_ATTR_DF] = { .name = "df", .type = BLOBMSG_TYPE_BOOL }, [TUNNEL_ATTR_TTL] = { .name = "ttl", .type = BLOBMSG_TYPE_INT32 }, [TUNNEL_ATTR_TOS] = { .name = "tos", .type = BLOBMSG_TYPE_STRING }, - [TUNNEL_ATTR_6RD_PREFIX] = {.name = "6rd-prefix", .type = BLOBMSG_TYPE_STRING }, - [TUNNEL_ATTR_6RD_RELAY_PREFIX] = { .name = "6rd-relay-prefix", .type = BLOBMSG_TYPE_STRING }, [TUNNEL_ATTR_LINK] = { .name = "link", .type = BLOBMSG_TYPE_STRING }, [TUNNEL_ATTR_FMRS] = { .name = "fmrs", .type = BLOBMSG_TYPE_ARRAY }, [TUNNEL_ATTR_DATA] = { .name = "data", .type = BLOBMSG_TYPE_TABLE }, @@ -70,6 +68,16 @@ const struct uci_blob_param_list vti_data_attr_list = { .params = vti_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 }, +}; + +const struct uci_blob_param_list sixrd_data_attr_list = { + .n_params = __SIXRD_DATA_ATTR_MAX, + .params = sixrd_data_attrs, +}; + void system_fd_set_cloexec(int fd) { #ifdef FD_CLOEXEC diff --git a/system.h b/system.h index 9995fa9..c8ddbad 100644 --- a/system.h +++ b/system.h @@ -63,9 +63,16 @@ enum vti_data { __VTI_DATA_ATTR_MAX }; +enum sixrd_data { + SIXRD_DATA_PREFIX, + SIXRD_DATA_RELAY_PREFIX, + __SIXRD_DATA_ATTR_MAX +}; + 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; enum bridge_opt { /* stp and forward delay always set */ -- cgit v1.2.3