X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=system-linux.c;h=4463a2a8282a1151cb99734d65dd57689a7fad52;hb=HEAD;hp=8efb020e78d22ef4054961b00766915f20a2821e;hpb=eee02ccca8c8ba2540108e6a5cff10888bb337c9;p=project%2Fnetifd.git diff --git a/system-linux.c b/system-linux.c index 8efb020..4463a2a 100644 --- a/system-linux.c +++ b/system-linux.c @@ -169,19 +169,14 @@ static void handler_nl_event(struct uloop_fd *u, unsigned int events) { struct event_socket *ev = container_of(u, struct event_socket, uloop); - int err; - socklen_t errlen = sizeof(err); + int ret; - if (!u->error) { - nl_recvmsgs_default(ev->sock); + ret = nl_recvmsgs_default(ev->sock); + if (ret >= 0) return; - } - - if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen)) - goto abort; - switch(err) { - case ENOBUFS: + switch (-ret) { + case NLE_NOMEM: /* Increase rx buffer size on netlink socket */ ev->bufsize *= 2; if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0)) @@ -195,7 +190,6 @@ handler_nl_event(struct uloop_fd *u, unsigned int events) default: goto abort; } - u->error = false; return; abort: @@ -203,6 +197,14 @@ abort: return; } +static void +nl_udebug_cb(void *priv, struct nl_msg *msg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + + udebug_netlink_msg(priv, nlmsg_get_proto(msg), nlh, nlh->nlmsg_len); +} + static struct nl_sock * create_socket(int protocol, int groups) { @@ -220,6 +222,9 @@ create_socket(int protocol, int groups) return NULL; } + nl_socket_set_tx_debug_cb(sock, nl_udebug_cb, &udb_nl); + nl_socket_set_rx_debug_cb(sock, nl_udebug_cb, &udb_nl); + return sock; } @@ -700,12 +705,10 @@ static void system_device_update_state(struct device *dev, unsigned int flags, unsigned int ifindex) { if (dev->type == &simple_device_type) { - bool present = ifindex > 0; - if (dev->external) - present = present && (flags & IFF_UP); + device_set_disabled(dev, !(flags & IFF_UP)); - device_set_present(dev, present); + device_set_present(dev, ifindex > 0); } device_set_link(dev, flags & IFF_LOWER_UP ? true : false); } @@ -788,24 +791,19 @@ handle_hotplug_event(struct uloop_fd *u, unsigned int events) struct sockaddr_nl nla; unsigned char *buf = NULL; int size; - int err; - socklen_t errlen = sizeof(err); - if (!u->error) { - while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) { - if (nla.nl_pid == 0) - handle_hotplug_msg((char *) buf, size); + while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) { + if (nla.nl_pid == 0) + handle_hotplug_msg((char *) buf, size); - free(buf); - } - return; + free(buf); } - if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen)) - goto abort; + switch (-size) { + case 0: + return; - switch(err) { - case ENOBUFS: + case NLE_NOMEM: /* Increase rx buffer size on netlink socket */ ev->bufsize *= 2; if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0)) @@ -815,7 +813,6 @@ handle_hotplug_event(struct uloop_fd *u, unsigned int events) default: goto abort; } - u->error = false; return; abort: @@ -950,16 +947,19 @@ int system_bridge_addif(struct device *bridge, struct device *dev) int tries = 0; int ret; -retry: - ret = 0; - oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf)); - if (!oldbr || strcmp(oldbr, bridge->ifname) != 0) { + + for (tries = 0; tries < 3; tries++) { + ret = 0; + oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf)); + if (oldbr && !strcmp(oldbr, bridge->ifname)) + break; + ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL); - tries++; - D(SYSTEM, "Failed to add device '%s' to bridge '%s' (tries=%d): %s\n", + if (!ret) + break; + + D(SYSTEM, "Failed to add device '%s' to bridge '%s' (tries=%d): %s", dev->ifname, bridge->ifname, tries, strerror(errno)); - if (tries <= 3) - goto retry; } if (dev->wireless) @@ -1238,9 +1238,9 @@ static int cb_clear_event(struct nl_msg *msg, void *arg) return NL_SKIP; if (type == RTM_DELRULE) - D(SYSTEM, "Remove a rule\n"); + D(SYSTEM, "Remove a rule"); else - D(SYSTEM, "Remove %s from device %s\n", + D(SYSTEM, "Remove %s from device %s", type == RTM_DELADDR ? "an address" : "a route", clr->dev->ifname); @@ -1253,9 +1253,9 @@ static int cb_clear_event(struct nl_msg *msg, void *arg) ret = nl_send_auto_complete(sock_rtnl, clr->msg); if (ret < 0) { if (type == RTM_DELRULE) - D(SYSTEM, "Error deleting a rule: %d\n", ret); + D(SYSTEM, "Error deleting a rule: %d", ret); else - D(SYSTEM, "Error deleting %s from device '%s': %d\n", + D(SYSTEM, "Error deleting %s from device '%s': %d", type == RTM_DELADDR ? "an address" : "a route", clr->dev->ifname, ret); } @@ -1348,14 +1348,14 @@ void system_if_clear_state(struct device *dev) system_if_flags(dev->ifname, 0, IFF_UP); if (system_is_bridge(dev->ifname)) { - D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname); + D(SYSTEM, "Delete existing bridge named '%s'", dev->ifname); system_bridge_delbr(dev); return; } bridge = system_get_bridge(dev->ifname, buf, sizeof(buf)); if (bridge) { - D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge); + D(SYSTEM, "Remove device '%s' from bridge '%s'", dev->ifname, bridge); system_bridge_if(bridge, dev, SIOCBRDELIF, NULL); } @@ -1448,7 +1448,7 @@ int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg) rv = system_rtnl_call(msg); if (rv) - D(SYSTEM, "Error adding bridge '%s': %d\n", bridge->ifname, rv); + D(SYSTEM, "Error adding bridge '%s': %d", bridge->ifname, rv); return rv; @@ -1504,7 +1504,7 @@ int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvla rv = system_rtnl_call(msg); if (rv) - D(SYSTEM, "Error adding macvlan '%s' over '%s': %d\n", macvlan->ifname, dev->ifname, rv); + D(SYSTEM, "Error adding macvlan '%s' over '%s': %d", macvlan->ifname, dev->ifname, rv); return rv; @@ -1592,9 +1592,9 @@ int system_veth_add(struct device *veth, struct veth_config *cfg) rv = system_rtnl_call(msg); if (rv) { if (cfg->flags & VETH_OPT_PEER_NAME) - D(SYSTEM, "Error adding veth '%s' with peer '%s': %d\n", veth->ifname, cfg->peer_name, rv); + D(SYSTEM, "Error adding veth '%s' with peer '%s': %d", veth->ifname, cfg->peer_name, rv); else - D(SYSTEM, "Error adding veth '%s': %d\n", veth->ifname, rv); + D(SYSTEM, "Error adding veth '%s': %d", veth->ifname, rv); } return rv; @@ -1700,7 +1700,7 @@ int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlande rv = system_rtnl_call(msg); if (rv) - D(SYSTEM, "Error adding vlandev '%s' over '%s': %d\n", vlandev->ifname, dev->ifname, rv); + D(SYSTEM, "Error adding vlandev '%s' over '%s': %d", vlandev->ifname, dev->ifname, rv); return rv; @@ -1844,6 +1844,17 @@ out: return ret; } +static void system_refresh_orig_macaddr(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) - 1); + + if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) + memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr)); +} + static void system_set_master(struct device *dev, int master_ifindex) { struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, }; @@ -2236,6 +2247,16 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, uint64_t apply_mask &= s->flags; + if (apply_mask & DEV_OPT_MASTER) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0) + system_set_master(dev, s->master_ifindex); + if (!(apply_mask & (DEV_OPT_MACADDR | DEV_OPT_DEFAULT_MACADDR)) || dev->external) + system_refresh_orig_macaddr(dev, &dev->orig_settings); +#else + netifd_log_message(L_WARNING, "%s Your kernel is older than linux 6.1.0, changing DSA port conduit is not supported!", dev->ifname); +#endif + } + memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1); if (apply_mask & DEV_OPT_MTU) { @@ -2324,12 +2345,6 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, uint64_t system_set_drop_unsolicited_na(dev, s->drop_unsolicited_na ? "1" : "0"); if (apply_mask & DEV_OPT_ARP_ACCEPT) system_set_arp_accept(dev, s->arp_accept ? "1" : "0"); - if (apply_mask & DEV_OPT_MASTER) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0) - system_set_master(dev, s->master_ifindex); -#else - netifd_log_message(L_WARNING, "%s Your kernel is older than linux 6.1.0, changing DSA port conduit is not supported!", dev->ifname); -#endif system_set_ethtool_settings(dev, s); } @@ -4384,7 +4399,7 @@ static int system_add_vxlan(const char *name, const unsigned int link, struct bl ret = system_rtnl_call(msg); if (ret) - D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret); + D(SYSTEM, "Error adding vxlan '%s': %d", name, ret); return ret;