X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=system-linux.c;h=0ac4ae626c10307bc728a5019be9bd1b0b5d60db;hb=7573880ac042c6e5c8d48b1ad83d357b5e02743b;hp=88880477e0816736c5a9c10961b9d04822905dbf;hpb=91810ecc13239f3b18c8299de265b4f3531c0017;p=project%2Fnetifd.git diff --git a/system-linux.c b/system-linux.c index 8888047..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]; @@ -1896,7 +1899,8 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd) rtm.rtm_type == RTN_ANYCAST) { rtm.rtm_scope = RT_SCOPE_LINK; } else if (rtm.rtm_type == RTN_BLACKHOLE || rtm.rtm_type == RTN_UNREACHABLE || - rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY) { + rtm.rtm_type == RTN_PROHIBIT || rtm.rtm_type == RTN_FAILED_POLICY || + rtm.rtm_type == RTN_THROW) { rtm.rtm_scope = RT_SCOPE_UNIVERSE; dev = NULL; } @@ -1987,8 +1991,8 @@ bool system_resolve_rt_proto(const char *type, unsigned int *id) FILE *f; char *e, buf[128]; unsigned int n, proto = 256; - - if ((n = strtoul(type, &e, 0)) >= 0 && !*e && e != type) + n = strtoul(type, &e, 0); + if (!*e && e != type) proto = n; else if (!strcmp(type, "unspec")) proto = RTPROT_UNSPEC; @@ -2316,31 +2320,41 @@ static int system_add_gre_tunnel(const char *name, const char *kind, } } - if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) { - uint8_t icsum, ocsum, iseqno, oseqno; - if (sscanf(blobmsg_get_string(cur), "%u,%u,%hhu,%hhu,%hhu,%hhu", - &ikey, &okey, &icsum, &ocsum, &iseqno, &oseqno) < 6) { - ret = -EINVAL; - goto failure; - } + if ((cur = tb[TUNNEL_ATTR_DATA])) { + struct blob_attr *tb_data[__GRE_DATA_ATTR_MAX]; + + blobmsg_parse(gre_data_attr_list.params, __GRE_DATA_ATTR_MAX, tb_data, + blobmsg_data(cur), blobmsg_len(cur)); - if (ikey) - iflags |= GRE_KEY; + if ((cur = tb_data[GRE_DATA_IKEY])) { + if ((ikey = blobmsg_get_u32(cur))) + iflags |= GRE_KEY; + } - if (okey) - oflags |= GRE_KEY; + if ((cur = tb_data[GRE_DATA_OKEY])) { + if ((okey = blobmsg_get_u32(cur))) + oflags |= GRE_KEY; + } - if (icsum) - iflags |= GRE_CSUM; + if ((cur = tb_data[GRE_DATA_ICSUM])) { + if (blobmsg_get_bool(cur)) + iflags |= GRE_CSUM; + } - if (ocsum) - oflags |= GRE_CSUM; + if ((cur = tb_data[GRE_DATA_OCSUM])) { + if (blobmsg_get_bool(cur)) + oflags |= GRE_CSUM; + } - if (iseqno) - iflags |= GRE_SEQ; + if ((cur = tb_data[GRE_DATA_ISEQNO])) { + if (blobmsg_get_bool(cur)) + iflags |= GRE_SEQ; + } - if (oseqno) - oflags |= GRE_SEQ; + if ((cur = tb[GRE_DATA_OSEQNO])) { + if (blobmsg_get_bool(cur)) + oflags |= GRE_SEQ; + } } if (v6) { @@ -2452,7 +2466,6 @@ static int system_add_vti_tunnel(const char *name, const char *kind, struct nl_msg *nlm; struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, }; struct blob_attr *cur; - uint32_t ikey = 0, okey = 0; int ret = 0; nlm = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE); @@ -2478,14 +2491,6 @@ static int system_add_vti_tunnel(const char *name, const char *kind, if (link) nla_put_u32(nlm, IFLA_VTI_LINK, link); - if ((cur = tb[TUNNEL_ATTR_INFO]) && (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)) { - if (sscanf(blobmsg_get_string(cur), "%u,%u", - &ikey, &okey) < 2) { - ret = -EINVAL; - goto failure; - } - } - if (v6) { struct in6_addr in6buf; if ((cur = tb[TUNNEL_ATTR_LOCAL])) { @@ -2525,11 +2530,23 @@ static int system_add_vti_tunnel(const char *name, const char *kind, } - if (okey) - nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey)); + if ((cur = tb[TUNNEL_ATTR_DATA])) { + struct blob_attr *tb_data[__VTI_DATA_ATTR_MAX]; + uint32_t ikey = 0, okey = 0; - if (ikey) - nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey)); + blobmsg_parse(vti_data_attr_list.params, __VTI_DATA_ATTR_MAX, tb_data, + blobmsg_data(cur), blobmsg_len(cur)); + + if ((cur = tb_data[VTI_DATA_IKEY])) { + if ((ikey = blobmsg_get_u32(cur))) + nla_put_u32(nlm, IFLA_VTI_IKEY, htonl(ikey)); + } + + if ((cur = tb_data[VTI_DATA_OKEY])) { + if ((okey = blobmsg_get_u32(cur))) + nla_put_u32(nlm, IFLA_VTI_OKEY, htonl(okey)); + } + } nla_nest_end(nlm, infodata); nla_nest_end(nlm, linkinfo); @@ -2691,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; @@ -2839,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 };