]> git.proxmox.com Git - mirror_iproute2.git/blame - lib/libgenl.c
bridge: fdb: add support for src_vni option
[mirror_iproute2.git] / lib / libgenl.c
CommitLineData
6054c1eb 1/* SPDX-License-Identifier: GPL-2.0 */
8afcc288
JA
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
13static 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
49int genl_resolve_family(struct rtnl_handle *grth, const char *family)
50{
328d482c
JA
51 GENL_REQUEST(req, 1024, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY,
52 NLM_F_REQUEST);
86bf43c7
HL
53 struct nlmsghdr *answer;
54 int fnum;
8afcc288 55
328d482c 56 addattr_l(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME,
8afcc288
JA
57 family, strlen(family) + 1);
58
86bf43c7 59 if (rtnl_talk(grth, &req.n, &answer) < 0) {
8afcc288
JA
60 fprintf(stderr, "Error talking to the kernel\n");
61 return -2;
62 }
63
86bf43c7
HL
64 fnum = genl_parse_getfamily(answer);
65 free(answer);
66
67 return fnum;
8afcc288 68}
2b68cb77
SD
69
70int 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}