]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-netlink: introduce rtattr_read_nexthop()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 7 Oct 2020 04:00:45 +0000 (13:00 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 7 Oct 2020 17:51:23 +0000 (02:51 +0900)
src/libsystemd/sd-netlink/netlink-util.c
src/libsystemd/sd-netlink/netlink-util.h
src/network/networkd-route.h

index f045e794b6e7d8de2cf108f545dcc3da77a5afa8..f89340058078d270152ce40135b2f212cc3290ab 100644 (file)
@@ -368,3 +368,80 @@ int rtattr_append_attribute(struct rtattr **rta, unsigned short type, const void
 
         return 0;
 }
+
+int rtattr_read_nexthop(const struct rtnexthop *rtnh, size_t size, int family, OrderedSet **ret) {
+        _cleanup_ordered_set_free_free_ OrderedSet *set = NULL;
+        int r;
+
+        assert(rtnh);
+        assert(IN_SET(family, AF_INET, AF_INET6));
+
+        if (size < sizeof(struct rtnexthop))
+                return -EBADMSG;
+
+        for (; size >= sizeof(struct rtnexthop); ) {
+                _cleanup_free_ MultipathRoute *m = NULL;
+
+                if (NLMSG_ALIGN(rtnh->rtnh_len) > size)
+                        return -EBADMSG;
+
+                if (rtnh->rtnh_len < sizeof(struct rtnexthop))
+                        return -EBADMSG;
+
+                m = new(MultipathRoute, 1);
+                if (!m)
+                        return -ENOMEM;
+
+                *m = (MultipathRoute) {
+                        .ifindex = rtnh->rtnh_ifindex,
+                        .weight = rtnh->rtnh_hops == 0 ? 0 : rtnh->rtnh_hops + 1,
+                };
+
+                if (rtnh->rtnh_len > sizeof(struct rtnexthop)) {
+                        size_t len = rtnh->rtnh_len - sizeof(struct rtnexthop);
+
+                        for (struct rtattr *attr = RTNH_DATA(rtnh); RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) {
+                                if (attr->rta_type == RTA_GATEWAY) {
+                                        if (attr->rta_len != RTA_LENGTH(FAMILY_ADDRESS_SIZE(family)))
+                                                return -EBADMSG;
+
+                                        m->gateway.family = family;
+                                        memcpy(&m->gateway.address, RTA_DATA(attr), FAMILY_ADDRESS_SIZE(family));
+                                        break;
+                                } else if (attr->rta_type == RTA_VIA) {
+                                        uint16_t gw_family;
+
+                                        if (family != AF_INET)
+                                                return -EINVAL;
+
+                                        if (attr->rta_len < RTA_LENGTH(sizeof(uint16_t)))
+                                                return -EBADMSG;
+
+                                        gw_family = *(uint16_t *) RTA_DATA(attr);
+
+                                        if (gw_family != AF_INET6)
+                                                return -EBADMSG;
+
+                                        if (attr->rta_len != RTA_LENGTH(FAMILY_ADDRESS_SIZE(gw_family) + sizeof(gw_family)))
+                                                return -EBADMSG;
+
+                                        memcpy(&m->gateway, RTA_DATA(attr), FAMILY_ADDRESS_SIZE(gw_family) + sizeof(gw_family));
+                                        break;
+                                }
+                        }
+                }
+
+                r = ordered_set_ensure_put(&set, NULL, m);
+                if (r < 0)
+                        return r;
+
+                TAKE_PTR(m);
+
+                size -= NLMSG_ALIGN(rtnh->rtnh_len);
+                rtnh = RTNH_NEXT(rtnh);
+        }
+
+        if (ret)
+                *ret = TAKE_PTR(set);
+        return 0;
+}
index fa17e7dae7964ee6bc088cc07084a7c1f8b3ccda..2768d5fdc4db6302a7e34ebeb9f37aa60bcec588 100644 (file)
@@ -6,9 +6,22 @@
 #include "sd-netlink.h"
 
 #include "in-addr-util.h"
+#include "ordered-set.h"
 #include "socket-util.h"
 #include "util.h"
 
+/* See struct rtvia in rtnetlink.h */
+typedef struct RouteVia {
+        uint16_t family;
+        union in_addr_union address;
+} _packed_ RouteVia;
+
+typedef struct MultipathRoute {
+        RouteVia gateway;
+        int ifindex;
+        uint32_t weight;
+} MultipathRoute;
+
 int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret);
 uint32_t rtnl_message_get_serial(sd_netlink_message *m);
 void rtnl_message_seal(sd_netlink_message *m);
@@ -94,3 +107,5 @@ int netlink_message_read_in_addr_union(sd_netlink_message *m, unsigned short typ
 
 void rtattr_append_attribute_internal(struct rtattr *rta, unsigned short type, const void *data, size_t data_length);
 int rtattr_append_attribute(struct rtattr **rta, unsigned short type, const void *data, size_t data_length);
+
+int rtattr_read_nexthop(const struct rtnexthop *rtnh, size_t size, int family, OrderedSet **ret);
index 68d2d63574a9ced5b9f32a44212e018985147e72..ecc0aa4224dc81048dfb7cb4f071e8eb8bd8a447 100644 (file)
 typedef struct Manager Manager;
 typedef struct Network Network;
 
-/* See struct rtvia in rtnetlink.h */
-typedef struct RouteVia {
-        uint16_t family;
-        union in_addr_union address;
-} _packed_ RouteVia;
-
-typedef struct MultipathRoute {
-        RouteVia gateway;
-        int ifindex;
-        uint32_t weight;
-} MultipathRoute;
-
 typedef struct Route {
         Network *network;
         NetworkConfigSection *section;