X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=system-linux.c;h=6345b7f22bc80c232a689a5a7547116fba84ccff;hp=0ff2b3b344d742c0beb457a4bbd11c1e6ae53974;hb=680e846cd931223df74cdc12c8b6ce08f233a4f4;hpb=91fa29a0d17b40963f67f08e740ca0a07365db90 diff --git a/system-linux.c b/system-linux.c index 0ff2b3b..6345b7f 100644 --- a/system-linux.c +++ b/system-linux.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,8 @@ 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 char dev_buf[256]; + static void handler_nl_event(struct uloop_fd *u, unsigned int events) { @@ -131,10 +134,8 @@ static void system_set_sysctl(const char *path, const char *val) static void system_set_dev_sysctl(const char *path, const char *device, const char *val) { - static char buf[256]; - - snprintf(buf, sizeof(buf), path, val); - system_set_sysctl(buf, val); + snprintf(dev_buf, sizeof(dev_buf), path, val); + system_set_sysctl(dev_buf, val); } static void system_set_disable_ipv6(struct device *dev, const char *val) @@ -257,18 +258,6 @@ static int system_bridge_if(const char *bridge, struct device *dev, int cmd, voi return ioctl(sock_ioctl, cmd, &ifr); } -int system_bridge_addif(struct device *bridge, struct device *dev) -{ - system_set_disable_ipv6(dev, "1"); - return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL); -} - -int system_bridge_delif(struct device *bridge, struct device *dev) -{ - system_set_disable_ipv6(dev, "0"); - return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL); -} - static bool system_is_bridge(const char *name, char *buf, int buflen) { struct stat st; @@ -305,6 +294,24 @@ static char *system_get_bridge(const char *name, char *buf, int buflen) return path + 1; } +int system_bridge_addif(struct device *bridge, struct device *dev) +{ + char *oldbr; + + system_set_disable_ipv6(dev, "1"); + oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf)); + if (oldbr && !strcmp(oldbr, bridge->ifname)) + return 0; + + return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL); +} + +int system_bridge_delif(struct device *bridge, struct device *dev) +{ + system_set_disable_ipv6(dev, "0"); + return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL); +} + static int system_if_resolve(struct device *dev) { struct ifreq ifr; @@ -570,6 +577,30 @@ int system_vlan_del(struct device *dev) } static void +system_if_get_settings(struct device *dev, struct device_settings *s) +{ + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name)); + + if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) { + s->mtu = ifr.ifr_mtu; + s->flags |= DEV_OPT_MTU; + } + + if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) { + s->txqueuelen = ifr.ifr_qlen; + s->flags |= DEV_OPT_TXQUEUELEN; + } + + if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) { + memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr)); + s->flags |= DEV_OPT_MACADDR; + } +} + +static void system_if_apply_settings(struct device *dev, struct device_settings *s) { struct ifreq ifr; @@ -578,20 +609,25 @@ system_if_apply_settings(struct device *dev, struct device_settings *s) strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name)); if (s->flags & DEV_OPT_MTU) { ifr.ifr_mtu = s->mtu; - ioctl(sock_ioctl, SIOCSIFMTU, &ifr); + if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0) + s->flags &= ~DEV_OPT_MTU; } if (s->flags & DEV_OPT_TXQUEUELEN) { ifr.ifr_qlen = s->txqueuelen; - ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr); + if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0) + s->flags &= ~DEV_OPT_TXQUEUELEN; } if (s->flags & DEV_OPT_MACADDR) { - memcpy(&ifr.ifr_hwaddr, s->macaddr, sizeof(s->macaddr)); - ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr); + ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; + memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr)); + if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0) + s->flags &= ~DEV_OPT_MACADDR; } } int system_if_up(struct device *dev) { + system_if_get_settings(dev, &dev->orig_settings); system_if_apply_settings(dev, &dev->settings); dev->ifindex = system_if_resolve(dev); return system_if_flags(dev->ifname, IFF_UP, 0); @@ -599,7 +635,10 @@ int system_if_up(struct device *dev) int system_if_down(struct device *dev) { - return system_if_flags(dev->ifname, 0, IFF_UP); + int ret = system_if_flags(dev->ifname, 0, IFF_UP); + dev->orig_settings.flags &= dev->settings.flags; + system_if_apply_settings(dev, &dev->orig_settings); + return ret; } int system_if_check(struct device *dev) @@ -719,8 +758,6 @@ system_if_dump_info(struct device *dev, struct blob_buf *b) if (read_int_file(dir_fd, "carrier", &val)) blobmsg_add_u8(b, "link", !!val); - if (read_string_file(dir_fd, "address", buf, sizeof(buf))) - blobmsg_add_string(b, "macaddr", buf); memset(&ecmd, 0, sizeof(ecmd)); memset(&ifr, 0, sizeof(ifr)); @@ -779,7 +816,8 @@ system_if_dump_stats(struct device *dev, struct blob_buf *b) static int system_addr(struct device *dev, struct device_addr *addr, int cmd) { - int alen = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16; + bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4); + int alen = v4 ? 4 : 16; struct ifaddrmsg ifa = { .ifa_family = (alen == 4) ? AF_INET : AF_INET6, .ifa_prefixlen = addr->mask, @@ -788,20 +826,15 @@ static int system_addr(struct device *dev, struct device_addr *addr, int cmd) struct nl_msg *msg; - dev = addr->device; - if (dev) { - if (!dev->ifindex) - return -1; - - ifa.ifa_index = dev->ifindex; - } - msg = nlmsg_alloc_simple(cmd, 0); if (!msg) return -1; 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); + return system_rtnl_call(msg); } @@ -846,14 +879,6 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd) if (cmd == RTM_NEWROUTE) flags |= NLM_F_CREATE | NLM_F_REPLACE; - dev = route->device; - if (dev) { - if (!dev->ifindex) - return -1; - - ifindex = dev->ifindex; - } - msg = nlmsg_alloc_simple(cmd, flags); if (!msg) return -1; @@ -863,6 +888,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->metric >= 0) + nla_put_u32(msg, RTA_PRIORITY, route->metric); + if (have_gw) nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);