X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=system-linux.c;h=cbcc5bd44a45c199112ac4c3172c3e5d50ba4b00;hp=c6d81e60459f08165cd05ebfdec35d0250be68b3;hb=e3dc49a34fdd0dd900271cdfe6bb1c05babe5ee6;hpb=b19c14ca2ea5594d37bd3492ad147047eed4703f diff --git a/system-linux.c b/system-linux.c index c6d81e6..cbcc5bd 100644 --- a/system-linux.c +++ b/system-linux.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +37,10 @@ #include #include -#include +#ifndef RTN_FAILED_POLICY +#define RTN_FAILED_POLICY 12 +#endif + #include #include #include @@ -152,7 +156,7 @@ static void system_set_sysctl(const char *path, const char *val) if (fd < 0) return; - write(fd, val, strlen(val)); + if (write(fd, val, strlen(val))) {} close(fd); } @@ -452,8 +456,9 @@ static int cb_clear_event(struct nl_msg *msg, void *arg) hdr->nlmsg_type = type; hdr->nlmsg_flags = NLM_F_REQUEST; - if (!nl_send_auto_complete(sock_rtnl, clr->msg)) - nl_wait_for_ack(sock_rtnl); + nl_socket_disable_auto_ack(sock_rtnl); + nl_send_auto_complete(sock_rtnl, clr->msg); + nl_socket_enable_auto_ack(sock_rtnl); return NL_SKIP; } @@ -607,6 +612,93 @@ int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg) return 0; } +int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg) +{ + struct nl_msg *msg; + struct nlattr *linkinfo, *data; + struct ifinfomsg iim = { .ifi_family = AF_INET }; + int ifindex = system_if_resolve(dev); + int i, rv; + static const struct { + const char *name; + enum macvlan_mode val; + } modes[] = { + { "private", MACVLAN_MODE_PRIVATE }, + { "vepa", MACVLAN_MODE_VEPA }, + { "bridge", MACVLAN_MODE_BRIDGE }, + { "passthru", MACVLAN_MODE_PASSTHRU }, + }; + + if (ifindex == 0) + return -ENOENT; + + msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); + + if (!msg) + return -1; + + nlmsg_append(msg, &iim, sizeof(iim), 0); + + if (cfg->flags & MACVLAN_OPT_MACADDR) + nla_put(msg, IFLA_ADDRESS, sizeof(cfg->macaddr), cfg->macaddr); + nla_put(msg, IFLA_IFNAME, IFNAMSIZ, macvlan->ifname); + nla_put_u32(msg, IFLA_LINK, ifindex); + + if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) + goto nla_put_failure; + + nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan"); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (cfg->mode) { + for (i = 0; i < ARRAY_SIZE(modes); i++) { + if (strcmp(cfg->mode, modes[i].name) != 0) + continue; + + nla_put_u32(msg, IFLA_MACVLAN_MODE, modes[i].val); + break; + } + } + + nla_nest_end(msg, data); + nla_nest_end(msg, linkinfo); + + rv = system_rtnl_call(msg); + if (rv) + D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv); + + return rv; + +nla_put_failure: + nlmsg_free(msg); + return -ENOMEM; +} + +int system_macvlan_del(struct device *macvlan) +{ + struct nl_msg *msg; + struct ifinfomsg iim; + + iim.ifi_family = AF_INET; + iim.ifi_index = 0; + + msg = nlmsg_alloc_simple(RTM_DELLINK, 0); + + if (!msg) + return -1; + + nlmsg_append(msg, &iim, sizeof(iim), 0); + + nla_put(msg, IFLA_INFO_KIND, strlen("macvlan"), "macvlan"); + nla_put(msg, IFLA_IFNAME, sizeof(macvlan->ifname), macvlan->ifname); + + system_rtnl_call(msg); + + return 0; +} + static int system_vlan(struct device *dev, int id) { struct vlan_ioctl_args ifr = { @@ -976,6 +1068,7 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd) struct rtmsg rtm = { .rtm_family = (alen == 4) ? AF_INET : AF_INET6, .rtm_dst_len = route->mask, + .rtm_src_len = route->sourcemask, .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC, .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC, .rtm_scope = scope, @@ -1001,6 +1094,9 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd) if (route->mask) nla_put(msg, RTA_DST, alen, &route->addr); + if (route->sourcemask) + nla_put(msg, RTA_SRC, alen, &route->source); + if (route->metric > 0) nla_put_u32(msg, RTA_PRIORITY, route->metric); @@ -1039,7 +1135,7 @@ int system_flush_routes(void) if (fd < 0) continue; - write(fd, "-1", 2); + if (write(fd, "-1", 2)) {} close(fd); } return 0; @@ -1255,6 +1351,8 @@ bool system_resolve_iprule_action(const char *action, unsigned int *id) n = RTN_UNICAST; else if (!strcmp(action, "throw")) n = RTN_THROW; + else if (!strcmp(action, "failed_policy")) + n = RTN_FAILED_POLICY; else { n = strtoul(action, &e, 0); if (!e || *e || e == action || n > 255) @@ -1325,11 +1423,11 @@ out: return ret; } - int system_add_ip_tunnel(const char *name, struct blob_attr *attr) { struct blob_attr *tb[__TUNNEL_ATTR_MAX]; struct blob_attr *cur; + bool set_df = true; const char *str; system_del_ip_tunnel(name); @@ -1341,9 +1439,15 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr) return -EINVAL; str = blobmsg_data(cur); + if ((cur = tb[TUNNEL_ATTR_DF])) + set_df = blobmsg_get_bool(cur); + unsigned int ttl = 0; - if ((cur = tb[TUNNEL_ATTR_TTL]) && (ttl = blobmsg_get_u32(cur)) > 255) - return -EINVAL; + if ((cur = tb[TUNNEL_ATTR_TTL])) { + ttl = blobmsg_get_u32(cur); + if (ttl > 255 || (!set_df && ttl)) + return -EINVAL; + } unsigned int link = 0; if ((cur = tb[TUNNEL_ATTR_LINK])) { @@ -1355,14 +1459,13 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr) link = iface->l3_dev.dev->ifindex; } - if (!strcmp(str, "sit")) { struct ip_tunnel_parm p = { .link = link, .iph = { .version = 4, .ihl = 5, - .frag_off = htons(IP_DF), + .frag_off = set_df ? htons(IP_DF) : 0, .protocol = IPPROTO_IPV6, .ttl = ttl }