]> git.ipfire.org Git - thirdparty/iw.git/blob - genl.c
Merge branch 'master' into scan-test
[thirdparty/iw.git] / genl.c
1 /*
2 * This ought to be provided by libnl
3 */
4
5 #include <asm/errno.h>
6 #include <netlink/genl/genl.h>
7 #include <netlink/genl/family.h>
8 #include <netlink/genl/ctrl.h>
9 #include <netlink/msg.h>
10 #include <netlink/attr.h>
11
12 static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
13 void *arg)
14 {
15 int *ret = arg;
16 *ret = err->error;
17 return NL_STOP;
18 }
19
20 static int ack_handler(struct nl_msg *msg, void *arg)
21 {
22 int *ret = arg;
23 *ret = 0;
24 return NL_STOP;
25 }
26
27 struct handler_args {
28 const char *group;
29 int id;
30 };
31
32 static int family_handler(struct nl_msg *msg, void *arg)
33 {
34 struct handler_args *grp = arg;
35 struct nlattr *tb[CTRL_ATTR_MAX + 1];
36 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
37 struct nlattr *mcgrp;
38 int rem_mcgrp;
39
40 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
41 genlmsg_attrlen(gnlh, 0), NULL);
42
43 if (!tb[CTRL_ATTR_MCAST_GROUPS])
44 return NL_SKIP;
45
46 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp) {
47 struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
48
49 nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX,
50 nla_data(mcgrp), nla_len(mcgrp), NULL);
51
52 if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] ||
53 !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
54 continue;
55 if (strncmp(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]),
56 grp->group, nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])))
57 continue;
58 grp->id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
59 break;
60 }
61
62 return NL_SKIP;
63 }
64
65 int nl_get_multicast_id(struct nl_handle *handle, const char *family, const char *group)
66 {
67 struct nl_msg *msg;
68 struct nl_cb *cb;
69 int ret, ctrlid;
70 struct handler_args grp = {
71 .group = group,
72 .id = -ENOENT,
73 };
74
75 msg = nlmsg_alloc();
76 if (!msg)
77 return -ENOMEM;
78
79 cb = nl_cb_alloc(NL_CB_DEFAULT);
80 if (!cb) {
81 ret = -ENOMEM;
82 goto out_fail_cb;
83 }
84
85 ctrlid = genl_ctrl_resolve(handle, "nlctrl");
86
87 genlmsg_put(msg, 0, 0, ctrlid, 0,
88 0, CTRL_CMD_GETFAMILY, 0);
89
90 ret = -ENOBUFS;
91 NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
92
93 ret = nl_send_auto_complete(handle, msg);
94 if (ret < 0)
95 goto out;
96
97 ret = 1;
98
99 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &ret);
100 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &ret);
101 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, family_handler, &grp);
102
103 while (ret > 0)
104 nl_recvmsgs(handle, cb);
105
106 if (ret == 0)
107 ret = grp.id;
108 nla_put_failure:
109 out:
110 nl_cb_put(cb);
111 out_fail_cb:
112 nlmsg_free(msg);
113 return ret;
114 }