X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=system-linux.c;h=0308e6f3e6ed5b08af95a0a0845d05a2edda977a;hp=e313cbc97934bf37f410e180419fe66bef039f99;hb=e19e9800b93dbaec566c43d752b9cf1a3c7c913b;hpb=beecba5195b2f1180f0bdfb6f61f0dbd3dff0eba diff --git a/system-linux.c b/system-linux.c index e313cbc..0308e6f 100644 --- a/system-linux.c +++ b/system-linux.c @@ -24,67 +24,79 @@ #include "device.h" #include "system.h" +struct event_socket { + struct uloop_fd uloop; + struct nl_sock *sock; + struct nl_cb *cb; +}; + static int sock_ioctl = -1; static struct nl_sock *sock_rtnl = NULL; -static struct nl_sock *sock_rtnl_event = NULL; -static void handler_rtnl_event(struct uloop_fd *u, unsigned int events); static int cb_rtnl_event(struct nl_msg *msg, void *arg); -static struct uloop_fd rtnl_event = {.cb = handler_rtnl_event}; -static struct nl_cb *nl_cb_rtnl_event; -int system_init(void) +static void +handler_nl_event(struct uloop_fd *u, unsigned int events) { - sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0); - fcntl(sock_ioctl, F_SETFD, fcntl(sock_ioctl, F_GETFD) | FD_CLOEXEC); + struct event_socket *ev = container_of(u, struct event_socket, uloop); + nl_recvmsgs(ev->sock, ev->cb); +} - // Prepare socket for routing / address control - sock_rtnl = nl_socket_alloc(); - if (!sock_rtnl) - return -1; +static struct nl_sock * +create_socket(int protocol) +{ + struct nl_sock *sock; + + sock = nl_socket_alloc(); + if (!sock) + return NULL; + + if (nl_connect(sock, protocol)) + return NULL; - if (nl_connect(sock_rtnl, NETLINK_ROUTE)) - goto error_free_sock; + return sock; +} +static bool +create_event_socket(struct event_socket *ev, int protocol, + int (*cb)(struct nl_msg *msg, void *arg)) +{ // Prepare socket for link events - nl_cb_rtnl_event = nl_cb_alloc(NL_CB_DEFAULT); - if (!nl_cb_rtnl_event) - goto error_free_sock; + ev->cb = nl_cb_alloc(NL_CB_DEFAULT); + if (!ev->cb) + return false; - nl_cb_set(nl_cb_rtnl_event, NL_CB_VALID, NL_CB_CUSTOM, - cb_rtnl_event, NULL); + nl_cb_set(ev->cb, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL); - sock_rtnl_event = nl_socket_alloc(); - if (!sock_rtnl_event) - goto error_free_cb; + ev->sock = create_socket(protocol); + if (!ev->sock) + return false; - if (nl_connect(sock_rtnl_event, NETLINK_ROUTE)) - goto error_free_event; + ev->uloop.fd = nl_socket_get_fd(ev->sock); + ev->uloop.cb = handler_nl_event; + uloop_fd_add(&ev->uloop, ULOOP_READ | ULOOP_EDGE_TRIGGER); + return true; +} - // Receive network link events form kernel - nl_socket_add_membership(sock_rtnl_event, RTNLGRP_LINK); +int system_init(void) +{ + static struct event_socket rtnl_event; - rtnl_event.fd = nl_socket_get_fd(sock_rtnl_event); - uloop_fd_add(&rtnl_event, ULOOP_READ | ULOOP_EDGE_TRIGGER); + sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0); + fcntl(sock_ioctl, F_SETFD, fcntl(sock_ioctl, F_GETFD) | FD_CLOEXEC); - return 0; + // Prepare socket for routing / address control + sock_rtnl = create_socket(NETLINK_ROUTE); + if (!sock_rtnl) + return -1; -error_free_event: - nl_socket_free(sock_rtnl_event); - sock_rtnl_event = NULL; -error_free_cb: - nl_cb_put(nl_cb_rtnl_event); - nl_cb_rtnl_event = NULL; -error_free_sock: - nl_socket_free(sock_rtnl); - sock_rtnl = NULL; - return -1; -} + if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event)) + return -1; -// If socket is ready for reading parse netlink events -static void handler_rtnl_event(struct uloop_fd *u, unsigned int events) -{ - nl_recvmsgs(sock_rtnl_event, nl_cb_rtnl_event); + // Receive network link events form kernel + nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK); + + return 0; } static void system_set_sysctl(const char *path, const char *val) @@ -101,7 +113,7 @@ 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) { - char buf[256]; + static char buf[256]; snprintf(buf, sizeof(buf), path, val); system_set_sysctl(buf, val); @@ -367,9 +379,12 @@ out: */ void system_if_clear_state(struct device *dev) { - char buf[256]; + static char buf[256]; char *bridge; + if (dev->external) + return; + dev->ifindex = system_if_resolve(dev); if (!dev->ifindex) return; @@ -562,7 +577,17 @@ static int system_addr(struct device *dev, struct device_addr *addr, int cmd) .ifa_index = dev->ifindex, }; - struct nl_msg *msg = nlmsg_alloc_simple(cmd, 0); + 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; @@ -586,6 +611,7 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd) int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16; bool have_gw; unsigned int flags = 0; + int ifindex = dev->ifindex; if (alen == 4) have_gw = !!route->nexthop.in.s_addr; @@ -606,11 +632,20 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd) .rtm_scope = scope, .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST, }; + struct nl_msg *msg; if (cmd == RTM_NEWROUTE) flags |= NLM_F_CREATE | NLM_F_REPLACE; - struct nl_msg *msg = nlmsg_alloc_simple(cmd, flags); + dev = route->device; + if (dev) { + if (!dev->ifindex) + return -1; + + ifindex = dev->ifindex; + } + + msg = nlmsg_alloc_simple(cmd, flags); if (!msg) return -1; @@ -623,7 +658,7 @@ static int system_rt(struct device *dev, struct device_route *route, int cmd) nla_put(msg, RTA_GATEWAY, alen, &route->nexthop); if (route->flags & DEVADDR_DEVICE) - nla_put_u32(msg, RTA_OIF, dev->ifindex); + nla_put_u32(msg, RTA_OIF, ifindex); return system_rtnl_call(msg); }