diff options
-rw-r--r-- | src/core/loopback-setup.c | 18 | ||||
-rw-r--r-- | src/libsystemd-rtnl/rtnl-message.c | 257 | ||||
-rw-r--r-- | src/libsystemd-rtnl/rtnl-util.c | 8 | ||||
-rw-r--r-- | src/libsystemd-rtnl/test-rtnl.c | 20 | ||||
-rw-r--r-- | src/network/networkd-address.c | 9 | ||||
-rw-r--r-- | src/network/networkd-bridge.c | 6 | ||||
-rw-r--r-- | src/network/networkd-route.c | 20 | ||||
-rw-r--r-- | src/systemd/sd-rtnl.h | 9 |
8 files changed, 258 insertions, 89 deletions
diff --git a/src/core/loopback-setup.c b/src/core/loopback-setup.c index 7bb20ecabe..1999959946 100644 --- a/src/core/loopback-setup.c +++ b/src/core/loopback-setup.c @@ -47,7 +47,7 @@ static int pipe_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { return r == -EEXIST ? 0 : r; } -static int add_adresses(sd_rtnl *rtnl, int if_loopback, uint32_t ipv4_address, int *counter) { +static int add_addresses(sd_rtnl *rtnl, int if_loopback, struct in_addr *ipv4_address, int *counter) { _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *ipv4 = NULL, *ipv6 = NULL; int r; @@ -55,7 +55,7 @@ static int add_adresses(sd_rtnl *rtnl, int if_loopback, uint32_t ipv4_address, i if (r < 0) return r; - r = sd_rtnl_message_append(ipv4, IFA_LOCAL, &ipv4_address); + r = sd_rtnl_message_append_in_addr(ipv4, IFA_LOCAL, ipv4_address); if (r < 0) return r; @@ -72,7 +72,7 @@ static int add_adresses(sd_rtnl *rtnl, int if_loopback, uint32_t ipv4_address, i if (r < 0) return r; - r = sd_rtnl_message_append(ipv6, IFA_LOCAL, &in6addr_loopback); + r = sd_rtnl_message_append_in6_addr(ipv6, IFA_LOCAL, &in6addr_loopback); if (r < 0) return r; @@ -85,7 +85,7 @@ static int add_adresses(sd_rtnl *rtnl, int if_loopback, uint32_t ipv4_address, i return 0; } -static int start_interface(sd_rtnl *rtnl, int if_loopback, uint32_t ipv4_address, int *counter) { +static int start_interface(sd_rtnl *rtnl, int if_loopback, struct in_addr *ipv4_address, int *counter) { _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL; int r; @@ -97,7 +97,7 @@ static int start_interface(sd_rtnl *rtnl, int if_loopback, uint32_t ipv4_address if (r < 0) return r; - r = sd_rtnl_message_append(req, IFA_LOCAL, &ipv4_address); + r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, ipv4_address); if (r < 0) return r; @@ -140,22 +140,24 @@ int loopback_setup(void) { _cleanup_sd_rtnl_unref_ sd_rtnl *rtnl = NULL; int r, if_loopback, counter = 0; bool eperm = false; - uint32_t ipv4_address = htonl(INADDR_LOOPBACK); + struct in_addr ipv4_address; errno = 0; if_loopback = (int) if_nametoindex("lo"); if (if_loopback <= 0) return errno ? -errno : -ENODEV; + ipv4_address.s_addr = htonl(INADDR_LOOPBACK); + r = sd_rtnl_open(0, &rtnl); if (r < 0) return r; - r = add_adresses(rtnl, if_loopback, ipv4_address, &counter); + r = add_addresses(rtnl, if_loopback, &ipv4_address, &counter); if (r < 0) return r; - r = start_interface(rtnl, if_loopback, ipv4_address, &counter); + r = start_interface(rtnl, if_loopback, &ipv4_address, &counter); if (r < 0) return r; diff --git a/src/libsystemd-rtnl/rtnl-message.c b/src/libsystemd-rtnl/rtnl-message.c index 8940d214ce..264cca004f 100644 --- a/src/libsystemd-rtnl/rtnl-message.c +++ b/src/libsystemd-rtnl/rtnl-message.c @@ -356,109 +356,256 @@ static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, return 0; } -int sd_rtnl_message_append(sd_rtnl_message *m, unsigned short type, const void *data) { +int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) { uint16_t rtm_type; - struct ifaddrmsg *ifa; - struct rtmsg *rtm; + int r; assert_return(m, -EINVAL); assert_return(data, -EINVAL); - sd_rtnl_message_get_type(m, &rtm_type); + r = sd_rtnl_message_get_type(m, &rtm_type); + if (r < 0) + return r; - if (m->current_container) { - switch (rtm_type) { - case RTM_NEWLINK: - case RTM_SETLINK: - case RTM_GETLINK: - case RTM_DELLINK: - switch (m->current_container->rta_type) { - case IFLA_LINKINFO: - switch (type) { - case IFLA_INFO_KIND: - return add_rtattr(m, type, data, strlen(data) + 1); - default: - return -ENOTSUP; - } + /* check that the type is correct */ + switch (rtm_type) { + case RTM_NEWLINK: + case RTM_SETLINK: + case RTM_GETLINK: + case RTM_DELLINK: + if (m->current_container) { + if (m->current_container->rta_type != IFLA_LINKINFO || + type != IFLA_INFO_KIND) + return -ENOTSUP; + } else { + switch (type) { + case IFLA_IFNAME: + case IFLA_IFALIAS: + case IFLA_QDISC: + break; default: return -ENOTSUP; } - default: + } + break; + case RTM_NEWADDR: + case RTM_GETADDR: + case RTM_DELADDR: + if (type != IFA_LABEL) return -ENOTSUP; - } + break; + default: + return -ENOTSUP; } + r = add_rtattr(m, type, data, strlen(data) + 1); + if (r < 0) + return r; + + return 0; +} + +int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) { + uint16_t rtm_type; + int r; + + assert_return(m, -EINVAL); + + r = sd_rtnl_message_get_type(m, &rtm_type); + if (r < 0) + return r; + + /* check that the type is correct */ switch (rtm_type) { case RTM_NEWLINK: case RTM_SETLINK: - case RTM_DELLINK: case RTM_GETLINK: + case RTM_DELLINK: switch (type) { - case IFLA_IFNAME: - case IFLA_IFALIAS: - case IFLA_QDISC: - return add_rtattr(m, type, data, strlen(data) + 1); case IFLA_MASTER: case IFLA_MTU: case IFLA_LINK: - return add_rtattr(m, type, data, sizeof(uint32_t)); - case IFLA_STATS: - return add_rtattr(m, type, data, sizeof(struct rtnl_link_stats)); - case IFLA_ADDRESS: - case IFLA_BROADCAST: - return add_rtattr(m, type, data, ETH_ALEN); + break; default: return -ENOTSUP; } + break; + case RTM_NEWROUTE: + case RTM_GETROUTE: + case RTM_DELROUTE: + switch (type) { + case RTA_TABLE: + case RTA_PRIORITY: + case RTA_IIF: + case RTA_OIF: + break; + default: + return -ENOTSUP; + } + break; + default: + return -ENOTSUP; + } + + r = add_rtattr(m, type, &data, sizeof(&data)); + if (r < 0) + return r; + + return 0; +} + +int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) { + struct ifaddrmsg *ifa; + struct rtmsg *rtm; + uint16_t rtm_type; + int r; + + assert_return(m, -EINVAL); + assert_return(data, -EINVAL); + + r = sd_rtnl_message_get_type(m, &rtm_type); + if (r < 0) + return r; + + /* check that the type is correct */ + switch (rtm_type) { case RTM_NEWADDR: - case RTM_DELADDR: case RTM_GETADDR: + case RTM_DELADDR: switch (type) { - case IFA_LABEL: - return add_rtattr(m, type, data, strlen(data) + 1); case IFA_ADDRESS: case IFA_LOCAL: case IFA_BROADCAST: case IFA_ANYCAST: ifa = NLMSG_DATA(m->hdr); - switch (ifa->ifa_family) { - case AF_INET: - return add_rtattr(m, type, data, sizeof(struct in_addr)); - case AF_INET6: - return add_rtattr(m, type, data, sizeof(struct in6_addr)); - default: - return -EINVAL; - } + + if (ifa->ifa_family != AF_INET) + return -EINVAL; + + break; default: return -ENOTSUP; } + break; case RTM_NEWROUTE: + case RTM_GETROUTE: case RTM_DELROUTE: + switch (type) { + case RTA_DST: + case RTA_SRC: + case RTA_GATEWAY: + rtm = NLMSG_DATA(m->hdr); + + if (rtm->rtm_family != AF_INET) + return -EINVAL; + + break; + default: + return -ENOTSUP; + } + break; + default: + return -ENOTSUP; + } + + r = add_rtattr(m, type, data, sizeof(data)); + if (r < 0) + return r; + + return 0; +} + +int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) { + struct ifaddrmsg *ifa; + struct rtmsg *rtm; + uint16_t rtm_type; + int r; + + assert_return(m, -EINVAL); + assert_return(data, -EINVAL); + + r = sd_rtnl_message_get_type(m, &rtm_type); + if (r < 0) + return r; + + /* check that the type is correct */ + switch (rtm_type) { + case RTM_NEWADDR: + case RTM_GETADDR: + case RTM_DELADDR: + switch (type) { + case IFA_ADDRESS: + case IFA_LOCAL: + case IFA_BROADCAST: + case IFA_ANYCAST: + ifa = NLMSG_DATA(m->hdr); + + if (ifa->ifa_family != AF_INET6) + return -EINVAL; + + break; + default: + return -ENOTSUP; + } + break; + case RTM_NEWROUTE: case RTM_GETROUTE: + case RTM_DELROUTE: switch (type) { case RTA_DST: case RTA_SRC: case RTA_GATEWAY: rtm = NLMSG_DATA(m->hdr); - switch (rtm->rtm_family) { - case AF_INET: - return add_rtattr(m, type, data, sizeof(struct in_addr)); - case AF_INET6: - return add_rtattr(m, type, data, sizeof(struct in6_addr)); - default: - return -EINVAL; - } - case RTA_TABLE: - case RTA_PRIORITY: - case RTA_IIF: - case RTA_OIF: - return add_rtattr(m, type, data, sizeof(uint32_t)); + + if (rtm->rtm_family != AF_INET6) + return -EINVAL; + + break; default: return -ENOTSUP; } default: return -ENOTSUP; } + + r = add_rtattr(m, type, data, sizeof(data)); + if (r < 0) + return r; + + return 0; +} + +int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) { + uint16_t rtm_type; + int r; + + assert_return(m, -EINVAL); + assert_return(data, -EINVAL); + + sd_rtnl_message_get_type(m, &rtm_type); + + switch (rtm_type) { + case RTM_NEWLINK: + case RTM_SETLINK: + case RTM_DELLINK: + case RTM_GETLINK: + switch (type) { + case IFLA_ADDRESS: + case IFLA_BROADCAST: + break; + default: + return -ENOTSUP; + } + break; + default: + return -ENOTSUP; + } + + r = add_rtattr(m, type, data, sizeof(data)); + if (r < 0) + return r; + + return 0; } int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) { diff --git a/src/libsystemd-rtnl/rtnl-util.c b/src/libsystemd-rtnl/rtnl-util.c index 264b72ec37..dfc0050def 100644 --- a/src/libsystemd-rtnl/rtnl-util.c +++ b/src/libsystemd-rtnl/rtnl-util.c @@ -38,7 +38,7 @@ int rtnl_set_link_name(sd_rtnl *rtnl, int ifindex, const char *name) { if (r < 0) return r; - r = sd_rtnl_message_append(message, IFLA_IFNAME, name); + r = sd_rtnl_message_append_string(message, IFLA_IFNAME, name); if (r < 0) return r; @@ -66,7 +66,7 @@ int rtnl_set_link_properties(sd_rtnl *rtnl, int ifindex, const char *alias, return r; if (alias) { - r = sd_rtnl_message_append(message, IFLA_IFALIAS, alias); + r = sd_rtnl_message_append_string(message, IFLA_IFALIAS, alias); if (r < 0) return r; @@ -75,7 +75,7 @@ int rtnl_set_link_properties(sd_rtnl *rtnl, int ifindex, const char *alias, } if (mac) { - r = sd_rtnl_message_append(message, IFLA_ADDRESS, mac); + r = sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, mac); if (r < 0) return r; @@ -83,7 +83,7 @@ int rtnl_set_link_properties(sd_rtnl *rtnl, int ifindex, const char *alias, } if (mtu > 0) { - r = sd_rtnl_message_append(message, IFLA_MTU, &mtu); + r = sd_rtnl_message_append_u32(message, IFLA_MTU, mtu); if (r < 0) return r; diff --git a/src/libsystemd-rtnl/test-rtnl.c b/src/libsystemd-rtnl/test-rtnl.c index d7a243a97e..58654e990a 100644 --- a/src/libsystemd-rtnl/test-rtnl.c +++ b/src/libsystemd-rtnl/test-rtnl.c @@ -38,9 +38,9 @@ static void test_link_configure(sd_rtnl *rtnl, int ifindex) { /* we'd really like to test NEWLINK, but let's not mess with the running kernel */ assert(sd_rtnl_message_link_new(RTM_GETLINK, ifindex, &message) >= 0); - assert(sd_rtnl_message_append(message, IFLA_IFNAME, name) >= 0); - assert(sd_rtnl_message_append(message, IFLA_ADDRESS, ether_aton(mac)) >= 0); - assert(sd_rtnl_message_append(message, IFLA_MTU, &mtu) >= 0); + assert(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0); + assert(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0); + assert(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0); assert(sd_rtnl_message_read(message, &type, &data) > 0); assert(type == IFLA_IFNAME); @@ -59,7 +59,7 @@ static void test_link_configure(sd_rtnl *rtnl, int ifindex) { static void test_route(void) { _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req; - uint32_t addr = htonl(INADDR_LOOPBACK); + struct in_addr addr; uint32_t index = 2; uint16_t type; void *data; @@ -71,13 +71,15 @@ static void test_route(void) { return; } - r = sd_rtnl_message_append(req, RTA_GATEWAY, &addr); + addr.s_addr = htonl(INADDR_LOOPBACK); + + r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr); if (r < 0) { log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r)); return; } - r = sd_rtnl_message_append(req, RTA_OIF, &index); + r = sd_rtnl_message_append_u32(req, RTA_OIF, index); if (r < 0) { log_error("Could not append RTA_OIF attribute: %s", strerror(-r)); return; @@ -85,7 +87,7 @@ static void test_route(void) { assert(sd_rtnl_message_read(req, &type, &data) > 0); assert(type == RTA_GATEWAY); - assert(*(uint32_t *) data == addr); + assert(((struct in_addr *)data)->s_addr == addr.s_addr); assert(sd_rtnl_message_read(req, &type, &data) > 0); assert(type == RTA_OIF); @@ -213,7 +215,7 @@ static void test_container(void) { assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0); assert(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -EINVAL); - assert(sd_rtnl_message_append(m, IFLA_INFO_KIND, "kind") >= 0); + assert(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0); assert(sd_rtnl_message_close_container(m) >= 0); assert(sd_rtnl_message_close_container(m) == -EINVAL); @@ -295,7 +297,7 @@ int main(void) { assert(sd_rtnl_message_link_new(RTM_GETLINK, if_loopback, &m) >= 0); assert(m); - assert(sd_rtnl_message_append(m, IFLA_MTU, &mtu) >= 0); + assert(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0); assert(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1); assert(type == IFLA_MTU); diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 8f16a8c6c1..63ba33ea24 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -95,7 +95,10 @@ int address_configure(Address *address, Link *link, return r; } - r = sd_rtnl_message_append(req, IFA_LOCAL, &address->in_addr); + if (address->family == AF_INET) + r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in); + else if (address->family == AF_INET6) + r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6); if (r < 0) { log_error("Could not append IFA_LOCAL attribute: %s", strerror(-r)); @@ -107,7 +110,7 @@ int address_configure(Address *address, Link *link, broadcast.s_addr = address->in_addr.in.s_addr | address->netmask.s_addr; - r = sd_rtnl_message_append(req, IFA_BROADCAST, &broadcast); + r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &broadcast); if (r < 0) { log_error("Could not append IFA_BROADCAST attribute: %s", strerror(-r)); @@ -116,7 +119,7 @@ int address_configure(Address *address, Link *link, } if (address->label) { - r = sd_rtnl_message_append(req, IFA_LABEL, address->label); + r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label); if (r < 0) { log_error("Could not append IFA_LABEL attribute: %s", strerror(-r)); diff --git a/src/network/networkd-bridge.c b/src/network/networkd-bridge.c index b764b7d593..2c541463ec 100644 --- a/src/network/networkd-bridge.c +++ b/src/network/networkd-bridge.c @@ -91,7 +91,7 @@ static int bridge_join_ready(Bridge *bridge, Link* link, sd_rtnl_message_handler return r; } - r = sd_rtnl_message_append(req, IFLA_MASTER, &bridge->link->ifindex); + r = sd_rtnl_message_append_u32(req, IFLA_MASTER, bridge->link->ifindex); if (r < 0) { log_error("Could not append IFLA_MASTER attribute: %s", strerror(-r)); @@ -162,7 +162,7 @@ static int bridge_create(Bridge *bridge) { return r; } - r = sd_rtnl_message_append(req, IFLA_IFNAME, bridge->name); + r = sd_rtnl_message_append_string(req, IFLA_IFNAME, bridge->name); if (r < 0) { log_error("Could not append IFLA_IFNAME attribute: %s", strerror(-r)); @@ -176,7 +176,7 @@ static int bridge_create(Bridge *bridge) { return r; } - r = sd_rtnl_message_append(req, IFLA_INFO_KIND, "bridge"); + r = sd_rtnl_message_append_string(req, IFLA_INFO_KIND, "bridge"); if (r < 0) { log_error("Could not append IFLA_INFO_KIND attribute: %s", strerror(-r)); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index f8580e93c8..22604b3afb 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -92,16 +92,24 @@ int route_configure(Route *route, Link *link, return r; } - r = sd_rtnl_message_append(req, RTA_GATEWAY, &route->in_addr); + if (route->family == AF_INET) + r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &route->in_addr.in); + else if (route->family == AF_INET6) + r = sd_rtnl_message_append_in6_addr(req, RTA_GATEWAY, &route->in_addr.in6); if (r < 0) { log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r)); return r; } - r = sd_rtnl_message_append(req, RTA_DST, &route->dst_addr); - if (r < 0) { - log_error("Could not append RTA_DST attribute: %s", strerror(-r)); - return r; + if (route->dst_prefixlen) { + if (route->family == AF_INET) + r = sd_rtnl_message_append_in_addr(req, RTA_DST, &route->dst_addr.in); + else if (route->family == AF_INET6) + r = sd_rtnl_message_append_in6_addr(req, RTA_DST, &route->dst_addr.in6); + if (r < 0) { + log_error("Could not append RTA_DST attribute: %s", strerror(-r)); + return r; + } } r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen); @@ -110,7 +118,7 @@ int route_configure(Route *route, Link *link, return r; } - r = sd_rtnl_message_append(req, RTA_OIF, &link->ifindex); + r = sd_rtnl_message_append_u32(req, RTA_OIF, link->ifindex); if (r < 0) { log_error("Could not append RTA_OIF attribute: %s", strerror(-r)); return r; diff --git a/src/systemd/sd-rtnl.h b/src/systemd/sd-rtnl.h index fcd09a0963..7d626b8403 100644 --- a/src/systemd/sd-rtnl.h +++ b/src/systemd/sd-rtnl.h @@ -23,6 +23,8 @@ ***/ #include <inttypes.h> +#include <netinet/in.h> +#include <netinet/ether.h> #include "sd-event.h" #include "_sd-common.h" @@ -89,7 +91,12 @@ int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags); int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen); -int sd_rtnl_message_append(sd_rtnl_message *m, unsigned short type, const void *data); +int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data); +int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data); +int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data); +int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data); +int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data); + int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type); int sd_rtnl_message_close_container(sd_rtnl_message *m); |