]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-netlink: allow configuration of flags parameter when creating message object
authorLennart Poettering <lennart@poettering.net>
Tue, 8 Apr 2025 10:13:12 +0000 (12:13 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 13 May 2025 12:42:33 +0000 (14:42 +0200)
We soon want to add for sock_diag(7) netlink sockets. Those reuse the
same message type codes for request and response but with different
message formats. Hence we need to look at NLM_F_REQUEST to determine
which message policy to apply. Hence it is essential to know the flags
parameters right away when creating a message, since we cannot do early
validation otherwise.

This only adds support for setting the flags value right at the moment
of creation of the message object, it does not otherwise add
sock_diag(7) support, that is added in a later message.

This also corrects the flag for synthetic NLMSG_ERROR messages which
should not have the NLM_F_REQUEST flag set (since they are responses,
not requests).

src/libsystemd/sd-netlink/netlink-genl.c
src/libsystemd/sd-netlink/netlink-internal.h
src/libsystemd/sd-netlink/netlink-message-nfnl.c
src/libsystemd/sd-netlink/netlink-message-rtnl.c
src/libsystemd/sd-netlink/netlink-message.c
src/libsystemd/sd-netlink/netlink-socket.c
src/libsystemd/sd-netlink/netlink-types.c
src/libsystemd/sd-netlink/netlink-types.h

index 8d2269b54d58edd24b687ac7bf49ea653a634d25..9c31105772f0ec460d80f3313ee294b54831d733 100644 (file)
@@ -244,7 +244,7 @@ static int genl_message_new(
         if (!policy_set)
                 return -EOPNOTSUPP;
 
-        r = message_new_full(nl, family->id, policy_set,
+        r = message_new_full(nl, family->id, NLM_F_REQUEST | NLM_F_ACK, policy_set,
                              sizeof(struct genlmsghdr) + family->additional_header_size, &m);
         if (r < 0)
                 return r;
index 5b9ccb336ec964806f296f147e5d37858f45a10d..7346902bdc92058ee817f7c762bb4a5502f2ff32 100644 (file)
@@ -131,10 +131,11 @@ int message_new_empty(sd_netlink *nl, sd_netlink_message **ret);
 int message_new_full(
                 sd_netlink *nl,
                 uint16_t nlmsg_type,
+                uint16_t nlmsg_flags,
                 const NLAPolicySet *policy_set,
                 size_t header_size,
                 sd_netlink_message **ret);
-int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type);
+int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type, uint16_t flags);
 int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_netlink_message **ret);
 
 static inline uint32_t message_get_serial(sd_netlink_message *m) {
index 72bcdde1bdd60be0056462daff8d18d5a2333753..321b9b2006dd0d8dc412adc9b56444d171a86576 100644 (file)
@@ -34,7 +34,7 @@ int sd_nfnl_message_new(sd_netlink *nfnl, sd_netlink_message **ret, int nfproto,
         assert_return(nfproto_is_valid(nfproto), -EINVAL);
         assert_return(NFNL_MSG_TYPE(msg_type) == msg_type, -EINVAL);
 
-        r = message_new(nfnl, &m, subsys << 8 | msg_type);
+        r = message_new(nfnl, &m, subsys << 8 | msg_type, NLM_F_REQUEST | NLM_F_ACK);
         if (r < 0)
                 return r;
 
index fdde1fb2c80f63e0e32a61e57d5e952cd8d62328..b730b63fb02ef3148ff03fb5696656aa2de0b87b 100644 (file)
@@ -244,13 +244,13 @@ int sd_rtnl_message_new_route(
                       IN_SET(family, AF_INET, AF_INET6), -EINVAL);
         assert_return(ret, -EINVAL);
 
-        r = message_new(rtnl, ret, nlmsg_type);
+        r = message_new(rtnl,
+                        ret,
+                        nlmsg_type,
+                        NLM_F_REQUEST|NLM_F_ACK|(nlmsg_type == RTM_NEWROUTE ? NLM_F_CREATE | NLM_F_APPEND : 0));
         if (r < 0)
                 return r;
 
-        if (nlmsg_type == RTM_NEWROUTE)
-                (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
-
         rtm = NLMSG_DATA((*ret)->hdr);
 
         rtm->rtm_family = family;
@@ -281,13 +281,13 @@ int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret,
         }
         assert_return(ret, -EINVAL);
 
-        r = message_new(rtnl, ret, nlmsg_type);
+        r = message_new(rtnl,
+                        ret,
+                        nlmsg_type,
+                        NLM_F_REQUEST | NLM_F_ACK | (nlmsg_type == RTM_NEWNEXTHOP ? NLM_F_CREATE | NLM_F_REPLACE : 0));
         if (r < 0)
                 return r;
 
-        if (nlmsg_type == RTM_NEWNEXTHOP)
-                (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
-
         nhm = NLMSG_DATA((*ret)->hdr);
 
         nhm->nh_family = family;
@@ -311,17 +311,18 @@ int sd_rtnl_message_new_neigh(
         assert_return(IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6, AF_BRIDGE), -EINVAL);
         assert_return(ret, -EINVAL);
 
-        r = message_new(rtnl, ret, nlmsg_type);
-        if (r < 0)
-                return r;
-
+        uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
         if (nlmsg_type == RTM_NEWNEIGH) {
                 if (family == AF_BRIDGE)
-                        (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
+                        flags |= NLM_F_CREATE | NLM_F_APPEND;
                 else
-                        (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
+                        flags |= NLM_F_CREATE | NLM_F_REPLACE;
         }
 
+        r = message_new(rtnl, ret, nlmsg_type, flags);
+        if (r < 0)
+                return r;
+
         ndm = NLMSG_DATA((*ret)->hdr);
 
         ndm->ndm_family = family;
@@ -337,14 +338,15 @@ int sd_rtnl_message_new_link(sd_netlink *rtnl, sd_netlink_message **ret, uint16_
         assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
         assert_return(ret, -EINVAL);
 
-        r = message_new(rtnl, ret, nlmsg_type);
-        if (r < 0)
-                return r;
-
+        uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
         if (nlmsg_type == RTM_NEWLINK && ifindex == 0)
-                (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
+                flags |= NLM_F_CREATE | NLM_F_EXCL;
         else if (nlmsg_type == RTM_NEWLINKPROP)
-                (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL | NLM_F_APPEND;
+                flags |= NLM_F_CREATE | NLM_F_EXCL | NLM_F_APPEND;
+
+        r = message_new(rtnl, ret, nlmsg_type, flags);
+        if (r < 0)
+                return r;
 
         ifi = NLMSG_DATA((*ret)->hdr);
 
@@ -371,7 +373,7 @@ int sd_rtnl_message_new_addr(
                       IN_SET(family, AF_INET, AF_INET6), -EINVAL);
         assert_return(ret, -EINVAL);
 
-        r = message_new(rtnl, ret, nlmsg_type);
+        r = message_new(rtnl, ret, nlmsg_type, NLM_F_REQUEST | NLM_F_ACK);
         if (r < 0)
                 return r;
 
@@ -439,13 +441,13 @@ int sd_rtnl_message_new_addrlabel(
         assert_return(rtnl_message_type_is_addrlabel(nlmsg_type), -EINVAL);
         assert_return(ret, -EINVAL);
 
-        r = message_new(rtnl, ret, nlmsg_type);
+        r = message_new(rtnl,
+                        ret,
+                        nlmsg_type,
+                        NLM_F_REQUEST | NLM_F_ACK | (nlmsg_type == RTM_NEWADDRLABEL ? NLM_F_CREATE | NLM_F_REPLACE : 0));
         if (r < 0)
                 return r;
 
-        if (nlmsg_type == RTM_NEWADDRLABEL)
-                (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
-
         addrlabel = NLMSG_DATA((*ret)->hdr);
 
         addrlabel->ifal_family = family;
@@ -466,13 +468,13 @@ int sd_rtnl_message_new_routing_policy_rule(
         assert_return(rtnl_message_type_is_routing_policy_rule(nlmsg_type), -EINVAL);
         assert_return(ret, -EINVAL);
 
-        r = message_new(rtnl, ret, nlmsg_type);
+        r = message_new(rtnl,
+                        ret,
+                        nlmsg_type,
+                        NLM_F_REQUEST | NLM_F_ACK | (nlmsg_type == RTM_NEWRULE ? NLM_F_CREATE | NLM_F_EXCL : 0));
         if (r < 0)
                 return r;
 
-        if (nlmsg_type == RTM_NEWRULE)
-                (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
-
         frh = NLMSG_DATA((*ret)->hdr);
         frh->family = family;
 
@@ -493,13 +495,13 @@ int sd_rtnl_message_new_traffic_control(
         assert_return(rtnl_message_type_is_traffic_control(nlmsg_type), -EINVAL);
         assert_return(ret, -EINVAL);
 
-        r = message_new(rtnl, ret, nlmsg_type);
+        r = message_new(rtnl,
+                        ret,
+                        nlmsg_type,
+                        NLM_F_REQUEST | NLM_F_ACK | (IN_SET(nlmsg_type, RTM_NEWQDISC, RTM_NEWTCLASS) ? NLM_F_CREATE | NLM_F_REPLACE : 0));
         if (r < 0)
                 return r;
 
-        if (IN_SET(nlmsg_type, RTM_NEWQDISC, RTM_NEWTCLASS))
-                (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
-
         tcm = NLMSG_DATA((*ret)->hdr);
         tcm->tcm_ifindex = ifindex;
         tcm->tcm_handle = handle;
@@ -520,13 +522,13 @@ int sd_rtnl_message_new_mdb(
         assert_return(rtnl_message_type_is_mdb(nlmsg_type), -EINVAL);
         assert_return(ret, -EINVAL);
 
-        r = message_new(rtnl, ret, nlmsg_type);
+        r = message_new(rtnl,
+                        ret,
+                        nlmsg_type,
+                        NLM_F_REQUEST | NLM_F_ACK | (nlmsg_type == RTM_NEWMDB ? NLM_F_CREATE | NLM_F_REPLACE : 0));
         if (r < 0)
                 return r;
 
-        if (nlmsg_type == RTM_NEWMDB)
-                (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
-
         bpm = NLMSG_DATA((*ret)->hdr);
         bpm->family = AF_BRIDGE;
         bpm->ifindex = ifindex;
@@ -545,7 +547,7 @@ int sd_rtnl_message_new_nsid(
         assert_return(rtnl_message_type_is_nsid(nlmsg_type), -EINVAL);
         assert_return(ret, -EINVAL);
 
-        r = message_new(rtnl, ret, nlmsg_type);
+        r = message_new(rtnl, ret, nlmsg_type, NLM_F_REQUEST | NLM_F_ACK);
         if (r < 0)
                 return r;
 
index eb88ae5e2b73159229759b62a3813b240600b3d7..8052e46768e638475d1fda54d720ce777751bee7 100644 (file)
@@ -44,6 +44,7 @@ int message_new_empty(sd_netlink *nl, sd_netlink_message **ret) {
 int message_new_full(
                 sd_netlink *nl,
                 uint16_t nlmsg_type,
+                uint16_t nlmsg_flags,
                 const NLAPolicySet *policy_set,
                 size_t header_size,
                 sd_netlink_message **ret) {
@@ -69,7 +70,7 @@ int message_new_full(
         if (!m->hdr)
                 return -ENOMEM;
 
-        m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+        m->hdr->nlmsg_flags = nlmsg_flags;
         m->hdr->nlmsg_len = size;
         m->hdr->nlmsg_type = nlmsg_type;
 
@@ -77,7 +78,7 @@ int message_new_full(
         return 0;
 }
 
-int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t nlmsg_type) {
+int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t nlmsg_type, uint16_t nlmsg_flags) {
         const NLAPolicySet *policy_set;
         size_t size;
         int r;
@@ -85,11 +86,11 @@ int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t nlmsg_type) {
         assert_return(nl, -EINVAL);
         assert_return(ret, -EINVAL);
 
-        r = netlink_get_policy_set_and_header_size(nl, nlmsg_type, &policy_set, &size);
+        r = netlink_get_policy_set_and_header_size(nl, nlmsg_type, nlmsg_flags, &policy_set, &size);
         if (r < 0)
                 return r;
 
-        return message_new_full(nl, nlmsg_type, policy_set, size, ret);
+        return message_new_full(nl, nlmsg_type, nlmsg_flags, policy_set, size, ret);
 }
 
 int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_netlink_message **ret) {
@@ -98,7 +99,7 @@ int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_n
 
         assert(error <= 0);
 
-        r = message_new(nl, ret, NLMSG_ERROR);
+        r = message_new(nl, ret, NLMSG_ERROR, 0);
         if (r < 0)
                 return r;
 
@@ -1328,8 +1329,12 @@ int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *nl) {
 
         assert(m->hdr);
 
-        r = netlink_get_policy_set_and_header_size(nl, m->hdr->nlmsg_type,
-                                                   &m->containers[0].policy_set, &size);
+        r = netlink_get_policy_set_and_header_size(
+                        nl,
+                        m->hdr->nlmsg_type,
+                        m->hdr->nlmsg_flags,
+                        &m->containers[0].policy_set,
+                        &size);
         if (r < 0)
                 return r;
 
index 1b098cadeebc94379980980983b126dd219feac2..0f00e3f2fcc21ada04ae26800b0b07dbd7be2e8e 100644 (file)
@@ -307,7 +307,7 @@ static int parse_message_one(sd_netlink *nl, uint32_t group, const struct nlmsgh
                 goto finalize;
 
         /* check that we support this message type */
-        r = netlink_get_policy_set_and_header_size(nl, hdr->nlmsg_type, NULL, &size);
+        r = netlink_get_policy_set_and_header_size(nl, hdr->nlmsg_type, hdr->nlmsg_flags, NULL, &size);
         if (r == -EOPNOTSUPP) {
                 log_debug("sd-netlink: ignored message with unknown type: %i", hdr->nlmsg_type);
                 goto finalize;
index 21ef80c2ece987dfc96f073458b09b08c64491de..8ce3fc0ec9a88b7909ffdc1765330cdc2591d41c 100644 (file)
@@ -51,6 +51,7 @@ const NLAPolicySetUnion *policy_get_policy_set_union(const NLAPolicy *policy) {
 int netlink_get_policy_set_and_header_size(
                 sd_netlink *nl,
                 uint16_t type,
+                uint16_t flags,
                 const NLAPolicySet **ret_policy_set,
                 size_t *ret_header_size) {
 
index e034a984e9b0d0e1860d8804fc5f2d77e9f6290e..46439527299d79205515465c09777baaf33b3b5a 100644 (file)
@@ -52,6 +52,7 @@ const NLAPolicySetUnion *policy_get_policy_set_union(const NLAPolicy *policy);
 int netlink_get_policy_set_and_header_size(
                 sd_netlink *nl,
                 uint16_t type,
+                uint16_t flags,
                 const NLAPolicySet **ret_policy_set,
                 size_t *ret_header_size);