Skip to content

Commit 56fdc16

Browse files
committed
sd-netlink: drop sd_genl_family_t and introduce GenericNetlinkFamily
Kernel manages each genl family by its name, e.g. "nlctrl" or WG_GENL_NAME, and its ID (used for nlmsg_type) is determined dynamically when the corresponding module is loaded. This commit makes sd-netlink follow the same way; now, sd_genl_family_t is dropped, and sd_genl_message_new() takes a genl family name. Each genl family is resolved when it is used first time, and its information is stored in GenericNetlinkFamily.
1 parent 1cedca0 commit 56fdc16

18 files changed

+363
-199
lines changed

src/libsystemd/sd-netlink/netlink-genl.c

Lines changed: 240 additions & 83 deletions
Large diffs are not rendered by default.

src/libsystemd/sd-netlink/netlink-genl.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@
33

44
#include "sd-netlink.h"
55

6-
int nlmsg_type_to_genl_family(const sd_netlink *nl, uint16_t type, sd_genl_family_t *ret);
6+
#define CTRL_GENL_NAME "nlctrl"
7+
8+
void genl_clear_family(sd_netlink *nl);

src/libsystemd/sd-netlink/netlink-internal.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ struct sd_netlink {
9595
sd_event_source *exit_event_source;
9696
sd_event *event;
9797

98-
Hashmap *genl_family_to_nlmsg_type;
99-
Hashmap *nlmsg_type_to_genl_family;
98+
Hashmap *genl_family_by_name;
99+
Hashmap *genl_family_by_id;
100100
};
101101

102102
struct netlink_attribute {

src/libsystemd/sd-netlink/netlink-message.c

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,18 @@ int message_new_full(
8080
}
8181

8282
int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type) {
83-
const NLType *nl_type;
83+
const NLTypeSystem *type_system;
84+
size_t size;
8485
int r;
8586

8687
assert_return(nl, -EINVAL);
8788
assert_return(ret, -EINVAL);
8889

89-
r = type_system_root_get_type(nl, &nl_type, type);
90+
r = type_system_root_get_type_system_and_header_size(nl, type, &type_system, &size);
9091
if (r < 0)
9192
return r;
9293

93-
if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
94-
return -EINVAL;
95-
96-
return message_new_full(nl, type, type_get_type_system(nl_type), type_get_size(nl_type), ret);
94+
return message_new_full(nl, type, type_system, size, ret);
9795
}
9896

9997
int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_netlink_message **ret) {
@@ -1319,8 +1317,6 @@ static int netlink_message_parse_error(sd_netlink_message *m) {
13191317
}
13201318

13211319
int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *nl) {
1322-
const NLType *nl_type;
1323-
uint16_t type;
13241320
size_t size;
13251321
int r;
13261322

@@ -1341,28 +1337,18 @@ int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *nl) {
13411337

13421338
assert(m->hdr);
13431339

1344-
r = type_system_root_get_type(nl, &nl_type, m->hdr->nlmsg_type);
1340+
r = type_system_root_get_type_system_and_header_size(nl, m->hdr->nlmsg_type,
1341+
&m->containers[0].type_system, &size);
13451342
if (r < 0)
13461343
return r;
13471344

1348-
type = type_get_type(nl_type);
1349-
size = type_get_size(nl_type);
1350-
1351-
if (type == NETLINK_TYPE_NESTED) {
1352-
m->containers[0].type_system = type_get_type_system(nl_type);
1345+
if (sd_netlink_message_is_error(m))
1346+
return netlink_message_parse_error(m);
13531347

1354-
if (sd_netlink_message_is_error(m))
1355-
r = netlink_message_parse_error(m);
1356-
else
1357-
r = netlink_container_parse(m,
1358-
&m->containers[m->n_containers],
1359-
(struct rtattr*)((uint8_t*) NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
1360-
NLMSG_PAYLOAD(m->hdr, size));
1361-
if (r < 0)
1362-
return r;
1363-
}
1364-
1365-
return 0;
1348+
return netlink_container_parse(m,
1349+
&m->containers[0],
1350+
(struct rtattr*)((uint8_t*) NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
1351+
NLMSG_PAYLOAD(m->hdr, size));
13661352
}
13671353

13681354
void message_seal(sd_netlink_message *m) {

src/libsystemd/sd-netlink/netlink-socket.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ int socket_read_message(sd_netlink *nl) {
326326

327327
for (struct nlmsghdr *new_msg = nl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
328328
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
329-
const NLType *nl_type;
329+
size_t size;
330330

331331
if (!group && new_msg->nlmsg_pid != nl->sockaddr.nl.nl_pid)
332332
/* not broadcast and not for us */
@@ -346,7 +346,7 @@ int socket_read_message(sd_netlink *nl) {
346346
}
347347

348348
/* check that we support this message type */
349-
r = type_system_root_get_type(nl, &nl_type, new_msg->nlmsg_type);
349+
r = type_system_root_get_type_system_and_header_size(nl, new_msg->nlmsg_type, NULL, &size);
350350
if (r < 0) {
351351
if (r == -EOPNOTSUPP)
352352
log_debug("sd-netlink: ignored message with unknown type: %i",
@@ -356,7 +356,7 @@ int socket_read_message(sd_netlink *nl) {
356356
}
357357

358358
/* check that the size matches the message type */
359-
if (new_msg->nlmsg_len < NLMSG_LENGTH(type_get_size(nl_type))) {
359+
if (new_msg->nlmsg_len < NLMSG_LENGTH(size)) {
360360
log_debug("sd-netlink: message is shorter than expected, dropping");
361361
continue;
362362
}

src/libsystemd/sd-netlink/netlink-types-genl.c

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ static const NLType genl_ctrl_types[] = {
4444
[CTRL_ATTR_OP] = { .type = NETLINK_TYPE_U32 },
4545
};
4646

47-
DEFINE_TYPE_SYSTEM(genl_ctrl);
48-
4947
/***************** genl batadv type systems *****************/
5048
static const NLType genl_batadv_types[] = {
5149
[BATADV_ATTR_VERSION] = { .type = NETLINK_TYPE_STRING },
@@ -110,8 +108,6 @@ static const NLType genl_batadv_types[] = {
110108
[BATADV_ATTR_THROUGHPUT_OVERRIDE] = { .type = NETLINK_TYPE_U32 },
111109
};
112110

113-
DEFINE_TYPE_SYSTEM(genl_batadv);
114-
115111
/***************** genl fou type systems *****************/
116112
static const NLType genl_fou_types[] = {
117113
[FOU_ATTR_PORT] = { .type = NETLINK_TYPE_U16 },
@@ -127,8 +123,6 @@ static const NLType genl_fou_types[] = {
127123
[FOU_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32},
128124
};
129125

130-
DEFINE_TYPE_SYSTEM(genl_fou);
131-
132126
/***************** genl l2tp type systems *****************/
133127
static const NLType genl_l2tp_types[] = {
134128
[L2TP_ATTR_PW_TYPE] = { .type = NETLINK_TYPE_U16 },
@@ -160,8 +154,6 @@ static const NLType genl_l2tp_types[] = {
160154
[L2TP_ATTR_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_FLAG },
161155
};
162156

163-
DEFINE_TYPE_SYSTEM(genl_l2tp);
164-
165157
/***************** genl macsec type systems *****************/
166158
static const NLType genl_macsec_rxsc_types[] = {
167159
[MACSEC_RXSC_ATTR_SCI] = { .type = NETLINK_TYPE_U64 },
@@ -185,8 +177,6 @@ static const NLType genl_macsec_types[] = {
185177
[MACSEC_ATTR_SA_CONFIG] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_sa_type_system },
186178
};
187179

188-
DEFINE_TYPE_SYSTEM(genl_macsec);
189-
190180
/***************** genl nl80211 type systems *****************/
191181
static const NLType genl_nl80211_types[] = {
192182
[NL80211_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32 },
@@ -195,8 +185,6 @@ static const NLType genl_nl80211_types[] = {
195185
[NL80211_ATTR_IFTYPE] = { .type = NETLINK_TYPE_U32 },
196186
};
197187

198-
DEFINE_TYPE_SYSTEM(genl_nl80211);
199-
200188
/***************** genl wireguard type systems *****************/
201189
static const NLType genl_wireguard_allowedip_types[] = {
202190
[WGALLOWEDIP_A_FAMILY] = { .type = NETLINK_TYPE_U16 },
@@ -227,28 +215,20 @@ static const NLType genl_wireguard_types[] = {
227215
[WGDEVICE_A_PEERS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_peer_type_system },
228216
};
229217

230-
DEFINE_TYPE_SYSTEM(genl_wireguard);
231-
232218
/***************** genl families *****************/
233-
static const NLType genl_types[] = {
234-
[SD_GENL_ID_CTRL] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_ctrl_type_system, .size = sizeof(struct genlmsghdr) },
235-
[SD_GENL_WIREGUARD] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_type_system, .size = sizeof(struct genlmsghdr) },
236-
[SD_GENL_FOU] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_fou_type_system, .size = sizeof(struct genlmsghdr) },
237-
[SD_GENL_L2TP] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_l2tp_type_system, .size = sizeof(struct genlmsghdr) },
238-
[SD_GENL_MACSEC] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_type_system, .size = sizeof(struct genlmsghdr) },
239-
[SD_GENL_NL80211] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system, .size = sizeof(struct genlmsghdr) },
240-
[SD_GENL_BATADV] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_batadv_type_system, .size = sizeof(struct genlmsghdr) },
219+
static const NLTypeSystemUnionElement genl_type_systems[] = {
220+
{ .name = CTRL_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_ctrl), },
221+
{ .name = BATADV_NL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_batadv), },
222+
{ .name = FOU_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_fou), },
223+
{ .name = L2TP_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_l2tp), },
224+
{ .name = MACSEC_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_macsec), },
225+
{ .name = NL80211_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_nl80211), },
226+
{ .name = WG_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_wireguard), },
241227
};
242228

243-
DEFINE_TYPE_SYSTEM(genl);
244-
245-
int genl_get_type(sd_netlink *genl, uint16_t nlmsg_type, const NLType **ret) {
246-
sd_genl_family_t family;
247-
int r;
248-
249-
r = nlmsg_type_to_genl_family(genl, nlmsg_type, &family);
250-
if (r < 0)
251-
return r;
229+
/* This is the root type system union, so match_attribute is not necessary. */
230+
DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(genl, 0);
252231

253-
return type_system_get_type(&genl_type_system, ret, family);
232+
int genl_get_type_system_by_name(const char *name, const NLTypeSystem **ret) {
233+
return type_system_union_get_type_system_by_string(&genl_type_system_union, ret, name);
254234
}

src/libsystemd/sd-netlink/netlink-types.c

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <linux/netlink.h>
44

5+
#include "netlink-genl.h"
56
#include "netlink-internal.h"
67
#include "netlink-types-internal.h"
78

@@ -54,20 +55,43 @@ uint16_t type_system_get_count(const NLTypeSystem *type_system) {
5455
return type_system->count;
5556
}
5657

57-
int type_system_root_get_type(sd_netlink *nl, const NLType **ret, uint16_t type) {
58-
if (!nl || IN_SET(type, NLMSG_DONE, NLMSG_ERROR))
59-
return type_system_get_type(&basic_type_system, ret, type);
60-
61-
switch(nl->protocol) {
62-
case NETLINK_ROUTE:
63-
return rtnl_get_type(type, ret);
64-
case NETLINK_NETFILTER:
65-
return nfnl_get_type(type, ret);
66-
case NETLINK_GENERIC:
67-
return genl_get_type(nl, type, ret);
68-
default:
58+
int type_system_root_get_type_system_and_header_size(
59+
sd_netlink *nl,
60+
uint16_t type,
61+
const NLTypeSystem **ret_type_system,
62+
size_t *ret_header_size) {
63+
64+
const NLType *nl_type;
65+
int r;
66+
67+
assert(nl);
68+
69+
if (IN_SET(type, NLMSG_DONE, NLMSG_ERROR))
70+
r = type_system_get_type(&basic_type_system, &nl_type, type);
71+
else
72+
switch(nl->protocol) {
73+
case NETLINK_ROUTE:
74+
r = rtnl_get_type(type, &nl_type);
75+
break;
76+
case NETLINK_NETFILTER:
77+
r = nfnl_get_type(type, &nl_type);
78+
break;
79+
case NETLINK_GENERIC:
80+
return genl_get_type_system_and_header_size(nl, type, ret_type_system, ret_header_size);
81+
default:
82+
return -EOPNOTSUPP;
83+
}
84+
if (r < 0)
85+
return r;
86+
87+
if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
6988
return -EOPNOTSUPP;
70-
}
89+
90+
if (ret_type_system)
91+
*ret_type_system = type_get_type_system(nl_type);
92+
if (ret_header_size)
93+
*ret_header_size = type_get_size(nl_type);
94+
return 0;
7195
}
7296

7397
int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type) {

src/libsystemd/sd-netlink/netlink-types.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,25 @@ typedef struct NLType NLType;
3737

3838
int rtnl_get_type(uint16_t nlmsg_type, const NLType **ret);
3939
int nfnl_get_type(uint16_t nlmsg_type, const NLType **ret);
40-
int genl_get_type(sd_netlink *genl, uint16_t nlmsg_type, const NLType **ret);
40+
int genl_get_type_system_by_name(const char *name, const NLTypeSystem **ret);
41+
int genl_get_type_system_and_header_size(
42+
sd_netlink *nl,
43+
uint16_t id,
44+
const NLTypeSystem **ret_type_system,
45+
size_t *ret_header_size);
4146

4247
uint16_t type_get_type(const NLType *type);
4348
size_t type_get_size(const NLType *type);
4449
const NLTypeSystem *type_get_type_system(const NLType *type);
4550
const NLTypeSystemUnion *type_get_type_system_union(const NLType *type);
4651

52+
int type_system_root_get_type_system_and_header_size(
53+
sd_netlink *nl,
54+
uint16_t type,
55+
const NLTypeSystem **ret_type_system,
56+
size_t *ret_header_size);
57+
4758
uint16_t type_system_get_count(const NLTypeSystem *type_system);
48-
int type_system_root_get_type(sd_netlink *nl, const NLType **ret, uint16_t type);
4959
int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type);
5060
int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type);
5161
int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type);

src/libsystemd/sd-netlink/sd-netlink.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "hashmap.h"
1010
#include "io-util.h"
1111
#include "macro.h"
12+
#include "netlink-genl.h"
1213
#include "netlink-internal.h"
1314
#include "netlink-slot.h"
1415
#include "process-util.h"
@@ -196,8 +197,7 @@ static sd_netlink *netlink_free(sd_netlink *nl) {
196197

197198
hashmap_free(nl->broadcast_group_refs);
198199

199-
hashmap_free(nl->genl_family_to_nlmsg_type);
200-
hashmap_free(nl->nlmsg_type_to_genl_family);
200+
genl_clear_family(nl);
201201

202202
safe_close(nl->fd);
203203
return mfree(nl);

src/libsystemd/sd-netlink/test-netlink.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "alloc-util.h"
1010
#include "ether-addr-util.h"
1111
#include "macro.h"
12+
#include "netlink-genl.h"
1213
#include "netlink-internal.h"
1314
#include "netlink-util.h"
1415
#include "socket-util.h"
@@ -514,7 +515,7 @@ static void test_array(void) {
514515
log_debug("/* %s */", __func__);
515516

516517
assert_se(sd_genl_socket_open(&genl) >= 0);
517-
assert_se(sd_genl_message_new(genl, SD_GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &m) >= 0);
518+
assert_se(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m) >= 0);
518519

519520
assert_se(sd_netlink_message_open_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
520521
for (unsigned i = 0; i < 10; i++) {
@@ -582,6 +583,23 @@ static void test_strv(sd_netlink *rtnl) {
582583
assert_se(sd_netlink_message_exit_container(m) >= 0);
583584
}
584585

586+
static void test_genl(void) {
587+
_cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
588+
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
589+
const char *name;
590+
591+
log_debug("/* %s */", __func__);
592+
593+
assert_se(sd_genl_socket_open(&genl) >= 0);
594+
assert_se(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m) >= 0);
595+
assert_se(sd_genl_message_get_family_name(genl, m, &name) >= 0);
596+
assert_se(streq(name, CTRL_GENL_NAME));
597+
598+
m = sd_netlink_message_unref(m);
599+
assert_se(sd_genl_message_new(genl, "should-not-exist", CTRL_CMD_GETFAMILY, &m) < 0);
600+
assert_se(sd_genl_message_new(genl, "should-not-exist", CTRL_CMD_GETFAMILY, &m) == -EOPNOTSUPP);
601+
}
602+
585603
int main(void) {
586604
sd_netlink *rtnl;
587605
sd_netlink_message *m;
@@ -642,5 +660,7 @@ int main(void) {
642660
assert_se((r = sd_netlink_message_unref(r)) == NULL);
643661
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
644662

663+
test_genl();
664+
645665
return EXIT_SUCCESS;
646666
}

0 commit comments

Comments
 (0)