Branch data Line data Source code
1 : : #include <linux/genetlink.h>
2 : :
3 : : #include "sd-netlink.h"
4 : : #include "netlink-internal.h"
5 : : #include "alloc-util.h"
6 : :
7 : : typedef struct {
8 : : const char* name;
9 : : uint8_t version;
10 : : } genl_family;
11 : :
12 : : static const genl_family genl_families[] = {
13 : : [SD_GENL_ID_CTRL] = { .name = "", .version = 1 },
14 : : [SD_GENL_WIREGUARD] = { .name = "wireguard", .version = 1 },
15 : : [SD_GENL_FOU] = { .name = "fou", .version = 1 },
16 : : [SD_GENL_L2TP] = { .name = "l2tp", .version = 1 },
17 : : [SD_GENL_MACSEC] = { .name = "macsec", .version = 1 },
18 : : };
19 : :
20 : 8 : int sd_genl_socket_open(sd_netlink **ret) {
21 : 8 : return netlink_open_family(ret, NETLINK_GENERIC);
22 : : }
23 : : static int lookup_id(sd_netlink *nl, sd_genl_family family, uint16_t *id);
24 : :
25 : 4 : static int genl_message_new(sd_netlink *nl, sd_genl_family family, uint16_t nlmsg_type, uint8_t cmd, sd_netlink_message **ret) {
26 : : int r;
27 : : struct genlmsghdr *genl;
28 : : const NLType *genl_cmd_type, *nl_type;
29 : : const NLTypeSystem *type_system;
30 : : size_t size;
31 : 4 : _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
32 : :
33 [ - + - + ]: 4 : assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
34 : :
35 : 4 : r = type_system_get_type(&genl_family_type_system_root, &genl_cmd_type, family);
36 [ - + ]: 4 : if (r < 0)
37 : 0 : return r;
38 : :
39 : 4 : r = message_new_empty(nl, &m);
40 [ - + ]: 4 : if (r < 0)
41 : 0 : return r;
42 : :
43 : 4 : size = NLMSG_SPACE(sizeof(struct genlmsghdr));
44 : 4 : m->hdr = malloc0(size);
45 [ - + ]: 4 : if (!m->hdr)
46 : 0 : return -ENOMEM;
47 : :
48 : 4 : m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
49 : :
50 : 4 : type_get_type_system(genl_cmd_type, &type_system);
51 : :
52 : 4 : r = type_system_get_type(type_system, &nl_type, cmd);
53 [ - + ]: 4 : if (r < 0)
54 : 0 : return r;
55 : :
56 : 4 : m->hdr->nlmsg_len = size;
57 : 4 : m->hdr->nlmsg_type = nlmsg_type;
58 : :
59 : 4 : type_get_type_system(nl_type, &m->containers[0].type_system);
60 : 4 : genl = NLMSG_DATA(m->hdr);
61 : 4 : genl->cmd = cmd;
62 : 4 : genl->version = genl_families[family].version;
63 : :
64 : 4 : *ret = TAKE_PTR(m);
65 : :
66 : 4 : return 0;
67 : : }
68 : :
69 : 4 : int sd_genl_message_new(sd_netlink *nl, sd_genl_family family, uint8_t cmd, sd_netlink_message **ret) {
70 : : int r;
71 : 4 : uint16_t id = GENL_ID_CTRL;
72 : :
73 [ - + ]: 4 : if (family != SD_GENL_ID_CTRL) {
74 : 0 : r = lookup_id(nl, family, &id);
75 [ # # ]: 0 : if (r < 0)
76 : 0 : return r;
77 : : }
78 : :
79 : 4 : return genl_message_new(nl, family, id, cmd, ret);
80 : : }
81 : :
82 : 0 : static int lookup_id(sd_netlink *nl, sd_genl_family family, uint16_t *id) {
83 : : int r;
84 : 0 : _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
85 : :
86 : 0 : r = sd_genl_message_new(nl, SD_GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &req);
87 [ # # ]: 0 : if (r < 0)
88 : 0 : return r;
89 : :
90 : 0 : r = sd_netlink_message_append_string(req, CTRL_ATTR_FAMILY_NAME, genl_families[family].name);
91 [ # # ]: 0 : if (r < 0)
92 : 0 : return r;
93 : :
94 : 0 : r = sd_netlink_call(nl, req, 0, &reply);
95 [ # # ]: 0 : if (r < 0)
96 : 0 : return r;
97 : :
98 : 0 : return sd_netlink_message_read_u16(reply, CTRL_ATTR_FAMILY_ID, id);
99 : : }
|