[systemd-commits] 8 commits - src/libsystemd src/network src/shared src/systemd

Tom Gundersen tomegun at kemper.freedesktop.org
Tue Dec 2 01:50:22 PST 2014


 src/libsystemd/sd-rtnl/rtnl-message.c |  122 ++++++++++++++--
 src/libsystemd/sd-rtnl/rtnl-types.c   |   22 ++
 src/libsystemd/sd-rtnl/rtnl-util.c    |   11 +
 src/libsystemd/sd-rtnl/rtnl-util.h    |    1 
 src/network/networkctl.c              |  253 +++++++++++++++++++++++++++++++++-
 src/shared/udev-util.h                |    2 
 src/systemd/sd-rtnl.h                 |    6 
 7 files changed, 403 insertions(+), 14 deletions(-)

New commits:
commit c09da72900b03fcddade06643f24c6357f3e0482
Author: Tom Gundersen <teg at jklm.no>
Date:   Tue Dec 2 01:05:52 2014 +0100

    networkctl: print the Gateway in the status output
    
    This is the IP address of the default route on the link, if present. A
    description is printed when available (the manufacturer of the gateway NIC based
    on its MAC address).
    
    In the future we should prefer LLDP information over MAC info.

diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 5351663..91eb635 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -247,6 +247,251 @@ static int list_links(char **args, unsigned n) {
         return 0;
 }
 
+/* IEEE Organizationally Unique Identifier vendor string */
+static int ieee_oui(struct udev_hwdb *hwdb, struct ether_addr *mac, char **ret) {
+        struct udev_list_entry *entry;
+        char *description;
+        char str[32];
+
+        /* skip commonly misused 00:00:00 (Xerox) prefix */
+        if (memcmp(mac, "\0\0\0", 3) == 0)
+                return -EINVAL;
+
+        snprintf(str, sizeof(str), "OUI:%02X%02X%02X%02X%02X%02X", mac->ether_addr_octet[0], mac->ether_addr_octet[1], mac->ether_addr_octet[2],
+                                                                   mac->ether_addr_octet[3], mac->ether_addr_octet[4], mac->ether_addr_octet[5]);
+
+        udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, str, 0))
+                if (strcmp(udev_list_entry_get_name(entry), "ID_OUI_FROM_DATABASE") == 0) {
+                        description = strdup(udev_list_entry_get_value(entry));
+                        if (!description)
+                                return -ENOMEM;
+
+                        *ret = description;
+                        return 0;
+                }
+
+        return -ENODATA;
+}
+
+static int get_gateway_description(sd_rtnl *rtnl, struct udev_hwdb *hwdb, int ifindex, int family,
+                                   union in_addr_union *gateway, char **gateway_description) {
+        _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
+        sd_rtnl_message *m;
+        int r;
+
+        assert(rtnl);
+        assert(ifindex >= 0);
+        assert(family == AF_INET || family == AF_INET6);
+        assert(gateway);
+        assert(gateway_description);
+
+        r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_GETNEIGH, ifindex, family);
+        if (r < 0)
+                return r;
+
+        r = sd_rtnl_message_request_dump(req, true);
+        if (r < 0)
+                return r;
+
+        r = sd_rtnl_call(rtnl, req, 0, &reply);
+        if (r < 0)
+                return r;
+
+        for (m = reply; m; m = sd_rtnl_message_next(m)) {
+                union in_addr_union gw = {};
+                struct ether_addr mac = {};
+                uint16_t type;
+                int ifi, fam;
+
+                r = sd_rtnl_message_get_errno(m);
+                if (r < 0) {
+                        log_error_errno(r, "got error: %m");
+                        continue;
+                }
+
+                r = sd_rtnl_message_get_type(m, &type);
+                if (r < 0) {
+                        log_error_errno(r, "could not get type: %m");
+                        continue;
+                }
+
+                if (type != RTM_NEWNEIGH) {
+                        log_error("type is not RTM_NEWNEIGH");
+                        continue;
+                }
+
+                r = sd_rtnl_message_neigh_get_family(m, &fam);
+                if (r < 0) {
+                        log_error_errno(r, "could not get family: %m");
+                        continue;
+                }
+
+                if (fam != family) {
+                        log_error("family is not correct");
+                        continue;
+                }
+
+                r = sd_rtnl_message_neigh_get_ifindex(m, &ifi);
+                if (r < 0) {
+                        log_error_errno(r, "colud not get ifindex: %m");
+                        continue;
+                }
+
+                if (ifindex > 0 && ifi != ifindex)
+                        continue;
+
+                switch (fam) {
+                case AF_INET:
+                        r = sd_rtnl_message_read_in_addr(m, NDA_DST, &gw.in);
+                        if (r < 0)
+                                continue;
+
+                        break;
+                case AF_INET6:
+                        r = sd_rtnl_message_read_in6_addr(m, NDA_DST, &gw.in6);
+                        if (r < 0)
+                                continue;
+
+                        break;
+                default:
+                        continue;
+                }
+
+                if (!in_addr_equal(fam, &gw, gateway))
+                        continue;
+
+                r = sd_rtnl_message_read_ether_addr(m, NDA_LLADDR, &mac);
+                if (r < 0)
+                        continue;
+
+                r = ieee_oui(hwdb, &mac, gateway_description);
+                if (r < 0)
+                        continue;
+
+                return 0;
+        }
+
+        return -ENODATA;
+}
+
+static int dump_gateways(sd_rtnl *rtnl, struct udev_hwdb *hwdb, const char *prefix, int ifindex) {
+        _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
+        sd_rtnl_message *m;
+        bool first = true;
+        int r;
+
+        assert(rtnl);
+        assert(ifindex >= 0);
+
+        r = sd_rtnl_message_new_route(rtnl, &req, RTM_GETROUTE, AF_UNSPEC, RTPROT_UNSPEC);
+        if (r < 0)
+                return r;
+
+        r = sd_rtnl_message_request_dump(req, true);
+        if (r < 0)
+                return r;
+
+        r = sd_rtnl_call(rtnl, req, 0, &reply);
+        if (r < 0)
+                return r;
+
+        for (m = reply; m; m = sd_rtnl_message_next(m)) {
+                _cleanup_free_ char *gateway = NULL, *gateway_description = NULL;
+                union in_addr_union gw = {};
+                uint16_t type;
+                uint32_t ifi;
+                int family;
+
+                r = sd_rtnl_message_get_errno(m);
+                if (r < 0) {
+                        log_error_errno(r, "got error: %m");
+                        continue;
+                }
+
+                r = sd_rtnl_message_get_type(m, &type);
+                if (r < 0) {
+                        log_error_errno(r, "could not get type: %m");
+                        continue;
+                }
+
+                if (type != RTM_NEWROUTE) {
+                        log_error("type is not RTM_NEWROUTE");
+                        continue;
+                }
+
+                r = sd_rtnl_message_route_get_family(m, &family);
+                if (r < 0) {
+                        log_error_errno(r, "could not get family: %m");
+                        continue;
+                }
+
+                r = sd_rtnl_message_read_u32(m, RTA_OIF, &ifi);
+                if (r < 0) {
+                        log_error_errno(r, "colud not get RTA_OIF: %m");
+                        continue;
+                }
+
+                if (ifindex > 0 && ifi != (unsigned) ifindex)
+                        continue;
+
+                switch (family) {
+                case AF_INET:
+                        r = sd_rtnl_message_read_in_addr(m, RTA_GATEWAY, &gw.in);
+                        if (r < 0)
+                                continue;
+
+                        r = sd_rtnl_message_read_in_addr(m, RTA_DST, NULL);
+                        if (r >= 0)
+                                continue;
+
+                        r = sd_rtnl_message_read_in_addr(m, RTA_SRC, NULL);
+                        if (r >= 0)
+                                continue;
+
+                        break;
+                case AF_INET6:
+                        r = sd_rtnl_message_read_in6_addr(m, RTA_GATEWAY, &gw.in6);
+                        if (r < 0)
+                                continue;
+
+                        r = sd_rtnl_message_read_in6_addr(m, RTA_DST, NULL);
+                        if (r >= 0)
+                                continue;
+
+                        r = sd_rtnl_message_read_in6_addr(m, RTA_SRC, NULL);
+                        if (r >= 0)
+                                continue;
+
+                        break;
+                default:
+                        continue;
+                }
+
+                r = in_addr_to_string(family, &gw, &gateway);
+                if (r < 0)
+                        continue;
+
+                r = get_gateway_description(rtnl, hwdb, ifi, family, &gw, &gateway_description);
+                if (r < 0)
+                        log_debug("could not get description of gateway: %s", strerror(-r));
+
+                if (gateway_description)
+                        printf("%*s%s (%s)\n",
+                               (int) strlen(prefix),
+                               first ? prefix : "",
+                               gateway, gateway_description);
+                else
+                        printf("%*s%s\n",
+                               (int) strlen(prefix),
+                               first ? prefix : "",
+                               gateway);
+
+                first = false;
+        }
+
+        return 0;
+}
+
 static int dump_addresses(sd_rtnl *rtnl, const char *prefix, int ifindex) {
         _cleanup_free_ struct local_address *local = NULL;
         int r, n, i;
@@ -284,9 +529,11 @@ static void dump_list(const char *prefix, char **l) {
 
 static int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
         _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
-        _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
+        _cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *gateway = NULL, *gateway_description = NULL,
+                            *gateway6 = NULL, *gateway6_description = NULL;
         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+        _cleanup_udev_hwdb_unref_ struct udev_hwdb *hwdb = NULL;
         char devid[2 + DECIMAL_STR_MAX(int)];
         _cleanup_free_ char *t = NULL, *network = NULL;
         const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL;
@@ -420,6 +667,10 @@ static int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) {
         if (mtu > 0)
                 printf("         MTU: %u\n", mtu);
 
+        hwdb = udev_hwdb_new(udev);
+
+        dump_gateways(rtnl, hwdb, "     Gateway: ", ifindex);
+
         dump_addresses(rtnl, "     Address: ", ifindex);
 
         if (!strv_isempty(dns))

commit 722f7cc95cdc0532f3226aae796ef446d2eea722
Author: Tom Gundersen <teg at jklm.no>
Date:   Tue Dec 2 10:46:14 2014 +0100

    sd-rtnl: route - allow GETROUTE with AF_UNSPEC

diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index 84ebf65..7ec6143 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -150,7 +150,8 @@ int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
         int r;
 
         assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
-        assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
+        assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) ||
+                      rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
         assert_return(ret, -EINVAL);
 
         r = message_new(rtnl, ret, nlmsg_type);

commit 1e30c94f745814d495c0dc3f91c4f52d27e2a3e0
Author: Tom Gundersen <teg at jklm.no>
Date:   Tue Dec 2 10:19:14 2014 +0100

    shared: udev-util - add hwdb cleanup macro

diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h
index 5f09ce1..5e0e1a9 100644
--- a/src/shared/udev-util.h
+++ b/src/shared/udev-util.h
@@ -27,6 +27,7 @@
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev*, udev_unref);
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_device*, udev_device_unref);
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_enumerate*, udev_enumerate_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_hwdb*, udev_hwdb_unref);
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_event*, udev_event_unref);
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_rules*, udev_rules_unref);
 DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl*, udev_ctrl_unref);
@@ -35,6 +36,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_monitor*, udev_monitor_unref);
 #define _cleanup_udev_unref_ _cleanup_(udev_unrefp)
 #define _cleanup_udev_device_unref_ _cleanup_(udev_device_unrefp)
 #define _cleanup_udev_enumerate_unref_ _cleanup_(udev_enumerate_unrefp)
+#define _cleanup_udev_hwdb_unref_ _cleanup_(udev_hwdb_unrefp)
 #define _cleanup_udev_event_unref_ _cleanup_(udev_event_unrefp)
 #define _cleanup_udev_rules_unref_ _cleanup_(udev_rules_unrefp)
 #define _cleanup_udev_ctrl_unref_ _cleanup_(udev_ctrl_unrefp)

commit 20dff6c4ff4f6e1b88c841e523ce9cff0e150fdf
Author: Tom Gundersen <teg at jklm.no>
Date:   Tue Dec 2 01:35:11 2014 +0100

    sd-rtnl: add sd_rtnl_message_{new_neigh,neigh_get_{family,ifindex}}

diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index e5c72e7..84ebf65 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -171,6 +171,59 @@ int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
         return 0;
 }
 
+int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) {
+        struct ndmsg *ndm;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->hdr, -EINVAL);
+        assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
+        assert_return(family, -EINVAL);
+
+        ndm = NLMSG_DATA(m->hdr);
+
+        *family = ndm->ndm_family;
+
+        return 0;
+}
+
+int sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *index) {
+        struct ndmsg *ndm;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->hdr, -EINVAL);
+        assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
+        assert_return(index, -EINVAL);
+
+        ndm = NLMSG_DATA(m->hdr);
+
+        *index = ndm->ndm_ifindex;
+
+        return 0;
+}
+
+int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
+        struct ndmsg *ndm;
+        int r;
+
+        assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
+        assert_return(ndm_family == AF_INET || ndm_family == AF_INET6, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        r = message_new(rtnl, ret, nlmsg_type);
+        if (r < 0)
+                return r;
+
+        if (nlmsg_type == RTM_NEWNEIGH)
+                (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
+
+        ndm = NLMSG_DATA((*ret)->hdr);
+
+        ndm->ndm_family = ndm_family;
+        ndm->ndm_ifindex = index;
+
+        return 0;
+}
+
 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
         struct ifinfomsg *ifi;
 
@@ -242,9 +295,10 @@ int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
         assert_return(m, -EINVAL);
         assert_return(m->hdr, -EINVAL);
-        assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
-                      m->hdr->nlmsg_type == RTM_GETADDR ||
-                      m->hdr->nlmsg_type == RTM_GETROUTE,
+        assert_return(m->hdr->nlmsg_type == RTM_GETLINK  ||
+                      m->hdr->nlmsg_type == RTM_GETADDR  ||
+                      m->hdr->nlmsg_type == RTM_GETROUTE ||
+                      m->hdr->nlmsg_type == RTM_GETNEIGH,
                       -EINVAL);
 
         if (dump)
diff --git a/src/libsystemd/sd-rtnl/rtnl-util.c b/src/libsystemd/sd-rtnl/rtnl-util.c
index 4521742..194a267 100644
--- a/src/libsystemd/sd-rtnl/rtnl-util.c
+++ b/src/libsystemd/sd-rtnl/rtnl-util.c
@@ -122,6 +122,17 @@ int rtnl_message_new_synthetic_error(int error, uint32_t serial, sd_rtnl_message
         return 0;
 }
 
+bool rtnl_message_type_is_neigh(uint16_t type) {
+        switch (type) {
+                case RTM_NEWNEIGH:
+                case RTM_GETNEIGH:
+                case RTM_DELNEIGH:
+                        return true;
+                default:
+                        return false;
+        }
+}
+
 bool rtnl_message_type_is_route(uint16_t type) {
         switch (type) {
                 case RTM_NEWROUTE:
diff --git a/src/libsystemd/sd-rtnl/rtnl-util.h b/src/libsystemd/sd-rtnl/rtnl-util.h
index fa3592d..ca9fbd4 100644
--- a/src/libsystemd/sd-rtnl/rtnl-util.h
+++ b/src/libsystemd/sd-rtnl/rtnl-util.h
@@ -33,6 +33,7 @@ void rtnl_message_seal(sd_rtnl_message *m);
 bool rtnl_message_type_is_link(uint16_t type);
 bool rtnl_message_type_is_addr(uint16_t type);
 bool rtnl_message_type_is_route(uint16_t type);
+bool rtnl_message_type_is_neigh(uint16_t type);
 
 int rtnl_set_link_name(sd_rtnl **rtnl, int ifindex, const char *name);
 int rtnl_set_link_properties(sd_rtnl **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, unsigned mtu);
diff --git a/src/systemd/sd-rtnl.h b/src/systemd/sd-rtnl.h
index 14eb9b8..15eaa26 100644
--- a/src/systemd/sd-rtnl.h
+++ b/src/systemd/sd-rtnl.h
@@ -75,6 +75,7 @@ int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t msg_
                              int family);
 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type,
                               int rtm_family, unsigned char rtm_protocol);
+int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t msg_type, int index, int nda_family);
 
 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m);
 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m);
@@ -104,6 +105,9 @@ int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char pr
 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope);
 int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family);
 
+int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family);
+int sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *family);
+
 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data);
 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data);
 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data);

commit e559b38493e6e0bc0214af2bce5aa940a8a15006
Author: Tom Gundersen <teg at jklm.no>
Date:   Tue Dec 2 01:23:47 2014 +0100

    sd-rtnl: add typesystem for RTM_*NEIGH

diff --git a/src/libsystemd/sd-rtnl/rtnl-types.c b/src/libsystemd/sd-rtnl/rtnl-types.c
index b6c483c..a1db2ab 100644
--- a/src/libsystemd/sd-rtnl/rtnl-types.c
+++ b/src/libsystemd/sd-rtnl/rtnl-types.c
@@ -329,6 +329,25 @@ static const NLTypeSystem rtnl_route_type_system = {
         .types = rtnl_route_types,
 };
 
+static const NLType rtnl_neigh_types[NDA_MAX + 1] = {
+        [NDA_DST]               = { .type = NLA_IN_ADDR },
+        [NDA_LLADDR]            = { .type = NLA_ETHER_ADDR },
+/*
+        NDA_CACHEINFO,
+        NDA_PROBES,
+        NDA_VLAN,
+        NDA_PORT
+        NDA_VNI
+        NDA_IFINDEX
+        NDA_MASTER
+*/
+};
+
+static const NLTypeSystem rtnl_neigh_type_system = {
+        .max = ELEMENTSOF(rtnl_neigh_types) - 1,
+        .types = rtnl_neigh_types,
+};
+
 static const NLType rtnl_types[RTM_MAX + 1] = {
         [NLMSG_ERROR]  = { .type = NLA_META, .size = sizeof(struct nlmsgerr) },
         [RTM_NEWLINK]  = { .type = NLA_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
@@ -341,6 +360,9 @@ static const NLType rtnl_types[RTM_MAX + 1] = {
         [RTM_NEWROUTE] = { .type = NLA_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
         [RTM_DELROUTE] = { .type = NLA_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
         [RTM_GETROUTE] = { .type = NLA_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
+        [RTM_NEWNEIGH] = { .type = NLA_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
+        [RTM_DELNEIGH] = { .type = NLA_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
+        [RTM_GETNEIGH] = { .type = NLA_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
 };
 
 const NLTypeSystem rtnl_type_system = {
diff --git a/src/systemd/sd-rtnl.h b/src/systemd/sd-rtnl.h
index 0d17b16..14eb9b8 100644
--- a/src/systemd/sd-rtnl.h
+++ b/src/systemd/sd-rtnl.h
@@ -26,6 +26,7 @@
 #include <netinet/in.h>
 #include <netinet/ether.h>
 #include <linux/rtnetlink.h>
+#include <linux/neighbour.h>
 
 #include "sd-event.h"
 #include "_sd-common.h"

commit 64918838d566058b7cec72d13f4524de0a64a8e3
Author: Tom Gundersen <teg at jklm.no>
Date:   Tue Dec 2 00:59:34 2014 +0100

    sd-rtnl: add a bit more debugging in case a message is dropped

diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index e7238d5..e5c72e7 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -1306,8 +1306,10 @@ int socket_read_message(sd_rtnl *rtnl) {
                 }
 
                 /* check that the size matches the message type */
-                if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
+                if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) {
+                        log_debug("sd-rtnl: message larger than expected, dropping");
                         continue;
+                }
 
                 r = message_new_empty(rtnl, &m);
                 if (r < 0)

commit 73ae2b7dade339c8a258dcf4fa2b302e238117e1
Author: Tom Gundersen <teg at jklm.no>
Date:   Tue Dec 2 00:59:02 2014 +0100

    sd-rtnl: message - allow checking for attributes without reading out their contents

diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index 22ee4c5..e7238d5 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -830,6 +830,8 @@ int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const c
         int r;
         void *attr_data;
 
+        assert_return(m, -EINVAL);
+
         r = message_attribute_has_type(m, type, NLA_STRING);
         if (r < 0)
                 return r;
@@ -840,7 +842,8 @@ int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const c
         else if (strnlen(attr_data, r) >= (size_t) r)
                 return -EIO;
 
-        *data = (const char *) attr_data;
+        if (data)
+                *data = (const char *) attr_data;
 
         return 0;
 }
@@ -849,6 +852,8 @@ int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *da
         int r;
         void *attr_data;
 
+        assert_return(m, -EINVAL);
+
         r = message_attribute_has_type(m, type, NLA_U8);
         if (r < 0)
                 return r;
@@ -859,7 +864,8 @@ int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *da
         else if ((size_t) r < sizeof(uint8_t))
                 return -EIO;
 
-        *data = *(uint8_t *) attr_data;
+        if (data)
+                *data = *(uint8_t *) attr_data;
 
         return 0;
 }
@@ -868,6 +874,8 @@ int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *
         int r;
         void *attr_data;
 
+        assert_return(m, -EINVAL);
+
         r = message_attribute_has_type(m, type, NLA_U16);
         if (r < 0)
                 return r;
@@ -878,7 +886,8 @@ int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *
         else if ((size_t) r < sizeof(uint16_t))
                 return -EIO;
 
-        *data = *(uint16_t *) attr_data;
+        if (data)
+                *data = *(uint16_t *) attr_data;
 
         return 0;
 }
@@ -887,6 +896,8 @@ int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *
         int r;
         void *attr_data;
 
+        assert_return(m, -EINVAL);
+
         r = message_attribute_has_type(m, type, NLA_U32);
         if (r < 0)
                 return r;
@@ -897,7 +908,8 @@ int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *
         else if ((size_t)r < sizeof(uint32_t))
                 return -EIO;
 
-        *data = *(uint32_t *) attr_data;
+        if (data)
+                *data = *(uint32_t *) attr_data;
 
         return 0;
 }
@@ -906,6 +918,8 @@ int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, str
         int r;
         void *attr_data;
 
+        assert_return(m, -EINVAL);
+
         r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
         if (r < 0)
                 return r;
@@ -916,7 +930,8 @@ int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, str
         else if ((size_t)r < sizeof(struct ether_addr))
                 return -EIO;
 
-        memcpy(data, attr_data, sizeof(struct ether_addr));
+        if (data)
+                memcpy(data, attr_data, sizeof(struct ether_addr));
 
         return 0;
 }
@@ -925,6 +940,8 @@ int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, str
         int r;
         void *attr_data;
 
+        assert_return(m, -EINVAL);
+
         r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
         if (r < 0)
                 return r;
@@ -935,7 +952,8 @@ int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, str
         else if ((size_t)r < sizeof(struct ifa_cacheinfo))
                 return -EIO;
 
-        memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
+        if (info)
+                memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
 
         return 0;
 }
@@ -944,6 +962,8 @@ int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct
         int r;
         void *attr_data;
 
+        assert_return(m, -EINVAL);
+
         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
         if (r < 0)
                 return r;
@@ -954,7 +974,8 @@ int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct
         else if ((size_t)r < sizeof(struct in_addr))
                 return -EIO;
 
-        memcpy(data, attr_data, sizeof(struct in_addr));
+        if (data)
+                memcpy(data, attr_data, sizeof(struct in_addr));
 
         return 0;
 }
@@ -963,6 +984,8 @@ int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struc
         int r;
         void *attr_data;
 
+        assert_return(m, -EINVAL);
+
         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
         if (r < 0)
                 return r;
@@ -973,7 +996,8 @@ int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struc
         else if ((size_t)r < sizeof(struct in6_addr))
                 return -EIO;
 
-        memcpy(data, attr_data, sizeof(struct in6_addr));
+        if (data)
+                memcpy(data, attr_data, sizeof(struct in6_addr));
 
         return 0;
 }

commit dae4de9d42debf448bf667e0e4fd4606dfcfae0c
Author: Tom Gundersen <teg at jklm.no>
Date:   Tue Dec 2 00:58:17 2014 +0100

    sd-rtnl: add sd_rtnl_message_route_get_family

diff --git a/src/libsystemd/sd-rtnl/rtnl-message.c b/src/libsystemd/sd-rtnl/rtnl-message.c
index 44ad303..22ee4c5 100644
--- a/src/libsystemd/sd-rtnl/rtnl-message.c
+++ b/src/libsystemd/sd-rtnl/rtnl-message.c
@@ -128,6 +128,21 @@ int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
         return 0;
 }
 
+int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family) {
+        struct rtmsg *rtm;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->hdr, -EINVAL);
+        assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
+        assert_return(family, -EINVAL);
+
+        rtm = NLMSG_DATA(m->hdr);
+
+        *family = rtm->rtm_family;
+
+        return 0;
+}
+
 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
                               uint16_t nlmsg_type, int rtm_family,
                               unsigned char rtm_protocol) {
diff --git a/src/systemd/sd-rtnl.h b/src/systemd/sd-rtnl.h
index 95bdb1d..0d17b16 100644
--- a/src/systemd/sd-rtnl.h
+++ b/src/systemd/sd-rtnl.h
@@ -101,6 +101,7 @@ int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type);
 
 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen);
 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope);
+int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family);
 
 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data);
 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data);



More information about the systemd-commits mailing list