X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=system-linux.c;h=c4d094d21daf47ddce8f4a7950245ce2b9369ab7;hp=0e6ce5ac686570dc15de99b6f6b46c43225d6d4c;hb=515a80251f14d4c033fd49918e9ecac308e135dd;hpb=87648299f8944a3268210e0315f6b5244d42fa4f diff --git a/system-linux.c b/system-linux.c index 0e6ce5a..c4d094d 100644 --- a/system-linux.c +++ b/system-linux.c @@ -1,3 +1,16 @@ +/* + * netifd - network interface daemon + * Copyright (C) 2012 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #define _GNU_SOURCE #include @@ -243,10 +256,15 @@ handle_hotplug_event(struct uloop_fd *u, unsigned int events) static int system_rtnl_call(struct nl_msg *msg) { - int s = -(nl_send_auto_complete(sock_rtnl, msg) - || nl_wait_for_ack(sock_rtnl)); + int ret; + + ret = nl_send_auto_complete(sock_rtnl, msg); nlmsg_free(msg); - return s; + + if (ret < 0) + return ret; + + return nl_wait_for_ack(sock_rtnl); } int system_bridge_delbr(struct device *bridge) @@ -751,6 +769,16 @@ static void system_add_link_modes(struct blob_buf *b, __u32 mask) } } +bool +system_if_force_external(const char *ifname) +{ + char buf[64]; + struct stat s; + + snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname); + return stat(buf, &s) == 0; +} + int system_if_dump_info(struct device *dev, struct blob_buf *b) { @@ -839,8 +867,12 @@ static int system_addr(struct device *dev, struct device_addr *addr, int cmd) nlmsg_append(msg, &ifa, sizeof(ifa), 0); nla_put(msg, IFA_LOCAL, alen, &addr->addr); - if (v4) - nla_put_u32(msg, IFA_BROADCAST, addr->broadcast); + if (v4) { + if (addr->broadcast) + nla_put_u32(msg, IFA_BROADCAST, addr->broadcast); + if (addr->point_to_point) + nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point); + } return system_rtnl_call(msg); } @@ -877,7 +909,7 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd) .rtm_family = (alen == 4) ? AF_INET : AF_INET6, .rtm_dst_len = route->mask, .rtm_table = RT_TABLE_MAIN, - .rtm_protocol = RTPROT_BOOT, + .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_BOOT, .rtm_scope = scope, .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST, }; @@ -901,8 +933,7 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd) if (have_gw) nla_put(msg, RTA_GATEWAY, alen, &route->nexthop); - if (route->flags & DEVADDR_DEVICE) - nla_put_u32(msg, RTA_OIF, ifindex); + nla_put_u32(msg, RTA_OIF, ifindex); return system_rtnl_call(msg); } @@ -995,7 +1026,7 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr) struct blob_attr *cur; struct ip_tunnel_parm p; const char *base, *str; - int cmd = SIOCADDTUNNEL; + bool is_sit; system_del_ip_tunnel(name); @@ -1004,12 +1035,12 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr) blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb, blob_data(attr), blob_len(attr)); - cur = tb[TUNNEL_ATTR_TYPE]; - if (!cur) + if (!(cur = tb[TUNNEL_ATTR_TYPE])) return -EINVAL; - str = blobmsg_data(cur); - if (!strcmp(str, "sit")) { + is_sit = !strcmp(str, "sit"); + + if (is_sit) { p.iph.protocol = IPPROTO_IPV6; base = "sit0"; } else @@ -1031,5 +1062,35 @@ int system_add_ip_tunnel(const char *name, struct blob_attr *attr) } strncpy(p.name, name, sizeof(p.name)); - return tunnel_ioctl(base, cmd, &p); + if (tunnel_ioctl(base, SIOCADDTUNNEL, &p) < 0) + return -1; + +#ifdef SIOCADD6RD + cur = tb[TUNNEL_ATTR_6RD_PREFIX]; + if (cur && is_sit) { + 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); + return -1; + } + } +#endif + + return 0; }