]> git.proxmox.com Git - mirror_iproute2.git/blob - lib/libgenl.c
iproute: Set ip/ip6 lwtunnel flags
[mirror_iproute2.git] / lib / libgenl.c
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * libgenl.c GENL library
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9
10 #include <linux/genetlink.h>
11 #include "libgenl.h"
12
13 static int genl_parse_getfamily(struct nlmsghdr *nlh)
14 {
15 struct rtattr *tb[CTRL_ATTR_MAX + 1];
16 struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
17 int len = nlh->nlmsg_len;
18 struct rtattr *attrs;
19
20 if (nlh->nlmsg_type != GENL_ID_CTRL) {
21 fprintf(stderr, "Not a controller message, nlmsg_len=%d "
22 "nlmsg_type=0x%x\n", nlh->nlmsg_len, nlh->nlmsg_type);
23 return -1;
24 }
25
26 len -= NLMSG_LENGTH(GENL_HDRLEN);
27
28 if (len < 0) {
29 fprintf(stderr, "wrong controller message len %d\n", len);
30 return -1;
31 }
32
33 if (ghdr->cmd != CTRL_CMD_NEWFAMILY) {
34 fprintf(stderr, "Unknown controller command %d\n", ghdr->cmd);
35 return -1;
36 }
37
38 attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
39 parse_rtattr(tb, CTRL_ATTR_MAX, attrs, len);
40
41 if (tb[CTRL_ATTR_FAMILY_ID] == NULL) {
42 fprintf(stderr, "Missing family id TLV\n");
43 return -1;
44 }
45
46 return rta_getattr_u16(tb[CTRL_ATTR_FAMILY_ID]);
47 }
48
49 int genl_resolve_family(struct rtnl_handle *grth, const char *family)
50 {
51 GENL_REQUEST(req, 1024, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY,
52 NLM_F_REQUEST);
53 struct nlmsghdr *answer;
54 int fnum;
55
56 addattr_l(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME,
57 family, strlen(family) + 1);
58
59 if (rtnl_talk(grth, &req.n, &answer) < 0) {
60 fprintf(stderr, "Error talking to the kernel\n");
61 return -2;
62 }
63
64 fnum = genl_parse_getfamily(answer);
65 free(answer);
66
67 return fnum;
68 }
69
70 int genl_init_handle(struct rtnl_handle *grth, const char *family,
71 int *genl_family)
72 {
73 if (*genl_family >= 0)
74 return 0;
75
76 if (rtnl_open_byproto(grth, 0, NETLINK_GENERIC) < 0) {
77 fprintf(stderr, "Cannot open generic netlink socket\n");
78 return -1;
79 }
80
81 *genl_family = genl_resolve_family(grth, family);
82 if (*genl_family < 0)
83 return -1;
84
85 return 0;
86 }