1 #include <linux/genetlink.h>
3 #include "sd-netlink.h"
4 #include "netlink-internal.h"
5 #include "alloc-util.h"
12 static const genl_family genl_families
[] = {
13 [SD_GENL_ID_CTRL
] = { .name
= "", .version
= 1 },
14 [SD_GENL_WIREGUARD
] = { .name
= "wireguard", .version
= 1 },
17 int sd_genl_socket_open(sd_netlink
**ret
) {
18 return netlink_open_family(ret
, NETLINK_GENERIC
);
20 static int lookup_id(sd_netlink
*nl
, sd_genl_family family
, uint16_t *id
);
22 static int genl_message_new(sd_netlink
*nl
, sd_genl_family family
, uint16_t nlmsg_type
, uint8_t cmd
, sd_netlink_message
**ret
) {
24 struct genlmsghdr
*genl
;
25 const NLType
*genl_cmd_type
, *nl_type
;
26 const NLTypeSystem
*type_system
;
28 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
30 assert_return(nl
->protocol
== NETLINK_GENERIC
, -EINVAL
);
32 r
= type_system_get_type(&genl_family_type_system_root
, &genl_cmd_type
, family
);
36 r
= message_new_empty(nl
, &m
);
40 size
= NLMSG_SPACE(sizeof(struct genlmsghdr
));
41 m
->hdr
= malloc0(size
);
45 m
->hdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
47 type_get_type_system(genl_cmd_type
, &type_system
);
49 r
= type_system_get_type(type_system
, &nl_type
, cmd
);
53 m
->hdr
->nlmsg_len
= size
;
54 m
->hdr
->nlmsg_type
= nlmsg_type
;
56 type_get_type_system(nl_type
, &m
->containers
[0].type_system
);
57 genl
= NLMSG_DATA(m
->hdr
);
59 genl
->version
= genl_families
[family
].version
;
67 int sd_genl_message_new(sd_netlink
*nl
, sd_genl_family family
, uint8_t cmd
, sd_netlink_message
**ret
) {
69 uint16_t id
= GENL_ID_CTRL
;
71 if (family
!= SD_GENL_ID_CTRL
) {
72 r
= lookup_id(nl
, family
, &id
);
77 return genl_message_new(nl
, family
, id
, cmd
, ret
);
80 static int lookup_id(sd_netlink
*nl
, sd_genl_family family
, uint16_t *id
) {
82 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
84 r
= sd_genl_message_new(nl
, SD_GENL_ID_CTRL
, CTRL_CMD_GETFAMILY
, &req
);
88 r
= sd_netlink_message_append_string(req
, CTRL_ATTR_FAMILY_NAME
, genl_families
[family
].name
);
92 r
= sd_netlink_call(nl
, req
, 0, &reply
);
96 return sd_netlink_message_read_u16(reply
, CTRL_ATTR_FAMILY_ID
, id
);