X-Git-Url: https://git.archive.openwrt.org/?a=blobdiff_plain;ds=sidebyside;f=system-linux.c;h=c6f17e99c8015ca7f414231c6a77139c7a522e2e;hb=61e627ed78ed47e40cc63a24ff8fb2f5fb2c418f;hp=744742279efc719a2f1e666947b08153de0f89da;hpb=8f0c8e8e91945a3e5c3fa7111b2a3494b731b32c;p=project%2Fnetifd.git diff --git a/system-linux.c b/system-linux.c index 7447422..c6f17e9 100644 --- a/system-linux.c +++ b/system-linux.c @@ -3,6 +3,7 @@ * Copyright (C) 2012 Felix Fietkau * Copyright (C) 2013 Jo-Philipp Wich * Copyright (C) 2013 Steven Barth + * Copyright (C) 2014 Gioacchino Mazzurco * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -36,6 +37,7 @@ #include #include #include +#include #ifndef RTN_FAILED_POLICY #define RTN_FAILED_POLICY 12 @@ -162,6 +164,46 @@ create_event_socket(struct event_socket *ev, int protocol, return true; } +static bool +system_rtn_aton(const char *src, unsigned int *dst) +{ + char *e; + unsigned int n; + + if (!strcmp(src, "local")) + n = RTN_LOCAL; + else if (!strcmp(src, "nat")) + n = RTN_NAT; + else if (!strcmp(src, "broadcast")) + n = RTN_BROADCAST; + else if (!strcmp(src, "anycast")) + n = RTN_ANYCAST; + else if (!strcmp(src, "multicast")) + n = RTN_MULTICAST; + else if (!strcmp(src, "prohibit")) + n = RTN_PROHIBIT; + else if (!strcmp(src, "unreachable")) + n = RTN_UNREACHABLE; + else if (!strcmp(src, "blackhole")) + n = RTN_BLACKHOLE; + else if (!strcmp(src, "xresolve")) + n = RTN_XRESOLVE; + else if (!strcmp(src, "unicast")) + n = RTN_UNICAST; + else if (!strcmp(src, "throw")) + n = RTN_THROW; + else if (!strcmp(src, "failed_policy")) + n = RTN_FAILED_POLICY; + else { + n = strtoul(src, &e, 0); + if (!e || *e || e == src || n > 255) + return false; + } + + *dst = n; + return true; +} + int system_init(void) { static struct event_socket rtnl_event; @@ -689,7 +731,7 @@ int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvla { struct nl_msg *msg; struct nlattr *linkinfo, *data; - struct ifinfomsg iim = { .ifi_family = AF_INET }; + struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, }; int ifindex = system_if_resolve(dev); int i, rv; static const struct { @@ -714,13 +756,13 @@ int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvla 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_string(msg, IFLA_IFNAME, 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"); + nla_put_string(msg, IFLA_INFO_KIND, "macvlan"); if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) goto nla_put_failure; @@ -749,27 +791,27 @@ nla_put_failure: return -ENOMEM; } -int system_macvlan_del(struct device *macvlan) +static int system_link_del(struct device *dev) { struct nl_msg *msg; - struct ifinfomsg iim; - - iim.ifi_family = AF_INET; - iim.ifi_index = 0; + struct ifinfomsg iim = { + .ifi_family = AF_UNSPEC, + .ifi_index = 0, + }; - msg = nlmsg_alloc_simple(RTM_DELLINK, 0); + msg = nlmsg_alloc_simple(RTM_DELLINK, NLM_F_REQUEST); if (!msg) return -1; nlmsg_append(msg, &iim, sizeof(iim), 0); + nla_put_string(msg, IFLA_IFNAME, dev->ifname); + return system_rtnl_call(msg); +} - 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; +int system_macvlan_del(struct device *macvlan) +{ + return system_link_del(macvlan); } static int system_vlan(struct device *dev, int id) @@ -802,6 +844,62 @@ int system_vlan_del(struct device *dev) return system_vlan(dev, -1); } +int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg) +{ + struct nl_msg *msg; + struct nlattr *linkinfo, *data; + struct ifinfomsg iim = { .ifi_family = AF_UNSPEC }; + int ifindex = system_if_resolve(dev); + int rv; + + 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); + nla_put_string(msg, IFLA_IFNAME, vlandev->ifname); + nla_put_u32(msg, IFLA_LINK, ifindex); + + if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) + goto nla_put_failure; + + nla_put_string(msg, IFLA_INFO_KIND, "vlan"); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + nla_put_u16(msg, IFLA_VLAN_ID, cfg->vid); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + nla_put_u16(msg, IFLA_VLAN_PROTOCOL, htons(cfg->proto)); +#else + if(cfg->proto == VLAN_PROTO_8021AD) + netifd_log_message(L_WARNING, "%s Your kernel is older than linux 3.10.0, 802.1ad is not supported defaulting to 802.1q", vlandev->type->name); +#endif + + nla_nest_end(msg, data); + nla_nest_end(msg, linkinfo); + + rv = system_rtnl_call(msg); + if (rv) + D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv); + + return rv; + +nla_put_failure: + nlmsg_free(msg); + return -ENOMEM; +} + +int system_vlandev_del(struct device *vlandev) +{ + return system_link_del(vlandev); +} + static void system_if_get_settings(struct device *dev, struct device_settings *s) { @@ -1207,9 +1305,6 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd) route->nexthop.in6.s6_addr32[2] || route->nexthop.in6.s6_addr32[3]; - unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE : - (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK; - unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE)) ? route->table : RT_TABLE_MAIN; @@ -1219,7 +1314,7 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd) .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, + .rtm_scope = RT_SCOPE_NOWHERE, .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST, .rtm_flags = (route->flags & DEVROUTE_ONLINK) ? RTNH_F_ONLINK : 0, }; @@ -1232,6 +1327,23 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd) rtm.rtm_scope = RT_SCOPE_UNIVERSE; rtm.rtm_type = RTN_UNREACHABLE; } + else + rtm.rtm_scope = (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK; + } + + if (route->flags & DEVROUTE_TYPE) { + rtm.rtm_type = route->type; + if (!(route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))) { + if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_BROADCAST || + rtm.rtm_type == RTN_NAT || rtm.rtm_type == RTN_ANYCAST) + rtm.rtm_table = RT_TABLE_LOCAL; + } + + if (rtm.rtm_type == RTN_LOCAL || rtm.rtm_type == RTN_NAT) + rtm.rtm_scope = RT_SCOPE_HOST; + else if (rtm.rtm_type == RTN_BROADCAST || rtm.rtm_type == RTN_MULTICAST || + rtm.rtm_type == RTN_ANYCAST) + rtm.rtm_scope = RT_SCOPE_LINK; } msg = nlmsg_alloc_simple(cmd, flags); @@ -1305,6 +1417,11 @@ int system_flush_routes(void) return 0; } +bool system_resolve_rt_type(const char *type, unsigned int *id) +{ + return system_rtn_aton(type, id); +} + bool system_resolve_rt_table(const char *name, unsigned int *id) { FILE *f; @@ -1347,14 +1464,15 @@ bool system_resolve_rt_table(const char *name, unsigned int *id) if (table == RT_TABLE_UNSPEC) return false; - /* do not consider main table special */ - if (table == RT_TABLE_MAIN) - table = RT_TABLE_UNSPEC; - *id = table; return true; } +bool system_is_default_rt_table(unsigned int id) +{ + return (id == RT_TABLE_MAIN); +} + static int system_iprule(struct iprule *rule, int cmd) { int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16; @@ -1490,41 +1608,7 @@ int system_flush_iprules(void) bool system_resolve_iprule_action(const char *action, unsigned int *id) { - char *e; - unsigned int n; - - if (!strcmp(action, "local")) - n = RTN_LOCAL; - else if (!strcmp(action, "nat")) - n = RTN_NAT; - else if (!strcmp(action, "broadcast")) - n = RTN_BROADCAST; - else if (!strcmp(action, "anycast")) - n = RTN_ANYCAST; - else if (!strcmp(action, "multicast")) - n = RTN_MULTICAST; - else if (!strcmp(action, "prohibit")) - n = RTN_PROHIBIT; - else if (!strcmp(action, "unreachable")) - n = RTN_UNREACHABLE; - else if (!strcmp(action, "blackhole")) - n = RTN_BLACKHOLE; - else if (!strcmp(action, "xresolve")) - n = RTN_XRESOLVE; - else if (!strcmp(action, "unicast")) - 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) - return false; - } - - *id = n; - return true; + return system_rtn_aton(action, id); } time_t system_get_rtime(void) @@ -1675,8 +1759,12 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr) } 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 }; + int ret = 0; + + if (!nlm) + return -1; + nlmsg_append(nlm, &ifi, sizeof(ifi), 0); nla_put_string(nlm, IFLA_IFNAME, name); @@ -1684,8 +1772,16 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr) nla_put_u32(nlm, IFLA_LINK, link); struct nlattr *linkinfo = nla_nest_start(nlm, IFLA_LINKINFO); + if (!linkinfo) { + ret = -ENOMEM; + goto failure; + } nla_put_string(nlm, IFLA_INFO_KIND, "ip6tnl"); struct nlattr *infodata = nla_nest_start(nlm, IFLA_INFO_DATA); + if (!infodata) { + ret = -ENOMEM; + goto failure; + } if (link) nla_put_u32(nlm, IFLA_IPTUN_LINK, link); @@ -1696,14 +1792,18 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr) struct in6_addr in6buf; if ((cur = tb[TUNNEL_ATTR_LOCAL])) { - if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) - return -EINVAL; + if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) { + ret = -EINVAL; + goto failure; + } nla_put(nlm, IFLA_IPTUN_LOCAL, sizeof(in6buf), &in6buf); } if ((cur = tb[TUNNEL_ATTR_REMOTE])) { - if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) - return -EINVAL; + if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) { + ret = -EINVAL; + goto failure; + } nla_put(nlm, IFLA_IPTUN_REMOTE, sizeof(in6buf), &in6buf); } @@ -1722,14 +1822,18 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr) char ip4buf[16]; if (sscanf(blobmsg_get_string(fmr), "%47[^/]/%u,%15[^/]/%u,%u,%u", - ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) - return -EINVAL; + ip6buf, &ip6len, ip4buf, &ip4len, &ealen, &offset) < 5) { + ret = -EINVAL; + goto failure; + } struct in6_addr ip6prefix; struct in_addr ip4prefix; if (inet_pton(AF_INET6, ip6buf, &ip6prefix) != 1 || - inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) - return -EINVAL; + inet_pton(AF_INET, ip4buf, &ip4prefix) != 1) { + ret = -EINVAL; + goto failure; + } struct nlattr *rule = nla_nest_start(nlm, ++fmrcnt); @@ -1751,7 +1855,11 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr) nla_nest_end(nlm, linkinfo); return system_rtnl_call(nlm); - } else +failure: + nlmsg_free(nlm); + return ret; + } + else return -EINVAL; return 0;