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