xref: /aosp_15_r20/external/iw/mgmt.c (revision 92022041c981f431db0b590d0c3272306d0ea2a2)
1*92022041SSam Saccone #include <string.h>
2*92022041SSam Saccone #include <errno.h>
3*92022041SSam Saccone 
4*92022041SSam Saccone #include <netlink/genl/genl.h>
5*92022041SSam Saccone #include <netlink/genl/family.h>
6*92022041SSam Saccone #include <netlink/genl/ctrl.h>
7*92022041SSam Saccone #include <netlink/msg.h>
8*92022041SSam Saccone #include <netlink/attr.h>
9*92022041SSam Saccone 
10*92022041SSam Saccone #include "nl80211.h"
11*92022041SSam Saccone #include "iw.h"
12*92022041SSam Saccone 
13*92022041SSam Saccone SECTION(mgmt);
14*92022041SSam Saccone 
seq_handler(struct nl_msg * msg,void * arg)15*92022041SSam Saccone static int seq_handler(struct nl_msg *msg, void *arg)
16*92022041SSam Saccone {
17*92022041SSam Saccone 	return NL_OK;
18*92022041SSam Saccone }
19*92022041SSam Saccone 
dump_mgmt_frame(struct nl_msg * msg,void * arg)20*92022041SSam Saccone static int dump_mgmt_frame(struct nl_msg *msg, void *arg)
21*92022041SSam Saccone {
22*92022041SSam Saccone 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
23*92022041SSam Saccone 	struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
24*92022041SSam Saccone 
25*92022041SSam Saccone 	nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
26*92022041SSam Saccone 		  genlmsg_attrlen(gnlh, 0), NULL);
27*92022041SSam Saccone 
28*92022041SSam Saccone 	if (tb_msg[NL80211_ATTR_WIPHY_FREQ]) {
29*92022041SSam Saccone 		uint32_t freq = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]);
30*92022041SSam Saccone 		printf("freq %u MHz\n", freq);
31*92022041SSam Saccone 	}
32*92022041SSam Saccone 
33*92022041SSam Saccone 	if (tb_msg[NL80211_ATTR_RX_SIGNAL_DBM]) {
34*92022041SSam Saccone 		/* nl80211_send_mgmt sends signed dBm value as u32 */
35*92022041SSam Saccone 		int dbm = nla_get_u32(tb_msg[NL80211_ATTR_RX_SIGNAL_DBM]);
36*92022041SSam Saccone 		printf("rssi %d dBm\n", dbm);
37*92022041SSam Saccone 	}
38*92022041SSam Saccone 
39*92022041SSam Saccone 	if (tb_msg[NL80211_ATTR_FRAME]) {
40*92022041SSam Saccone 		int len = nla_len(tb_msg[NL80211_ATTR_FRAME]);
41*92022041SSam Saccone 		uint8_t *data = nla_data(tb_msg[NL80211_ATTR_FRAME]);
42*92022041SSam Saccone 		iw_hexdump("mgmt", data, len);
43*92022041SSam Saccone 	}
44*92022041SSam Saccone 
45*92022041SSam Saccone 	return 0;
46*92022041SSam Saccone }
47*92022041SSam Saccone 
register_mgmt_frame(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)48*92022041SSam Saccone static int register_mgmt_frame(struct nl80211_state *state,
49*92022041SSam Saccone 			       struct nl_msg *msg, int argc, char **argv,
50*92022041SSam Saccone 			       enum id_input id)
51*92022041SSam Saccone {
52*92022041SSam Saccone 	unsigned int type;
53*92022041SSam Saccone 	unsigned char *match;
54*92022041SSam Saccone 	size_t match_len;
55*92022041SSam Saccone 	int ret;
56*92022041SSam Saccone 
57*92022041SSam Saccone 	if (argc < 2)
58*92022041SSam Saccone 		return HANDLER_RET_USAGE;
59*92022041SSam Saccone 
60*92022041SSam Saccone 	ret = sscanf(argv[0], "%x", &type);
61*92022041SSam Saccone 	if (ret != 1) {
62*92022041SSam Saccone 		printf("invalid frame type: %s\n", argv[0]);
63*92022041SSam Saccone 		return 2;
64*92022041SSam Saccone 	}
65*92022041SSam Saccone 
66*92022041SSam Saccone 	match = parse_hex(argv[1], &match_len);
67*92022041SSam Saccone 	if (!match) {
68*92022041SSam Saccone 		printf("invalid frame pattern: %s\n", argv[1]);
69*92022041SSam Saccone 		return 2;
70*92022041SSam Saccone 	}
71*92022041SSam Saccone 
72*92022041SSam Saccone 	NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type);
73*92022041SSam Saccone 	NLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match);
74*92022041SSam Saccone 
75*92022041SSam Saccone 	free(match);
76*92022041SSam Saccone 	return 0;
77*92022041SSam Saccone 
78*92022041SSam Saccone nla_put_failure:
79*92022041SSam Saccone 	free(match);
80*92022041SSam Saccone 	return -ENOBUFS;
81*92022041SSam Saccone }
82*92022041SSam Saccone 
handle_mgmt_reg(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)83*92022041SSam Saccone static int handle_mgmt_reg(struct nl80211_state *state,
84*92022041SSam Saccone 				    struct nl_msg *msg, int argc,
85*92022041SSam Saccone 				    char **argv, enum id_input id)
86*92022041SSam Saccone {
87*92022041SSam Saccone 	return register_mgmt_frame(state, msg, argc, argv, id);
88*92022041SSam Saccone }
89*92022041SSam Saccone 
90*92022041SSam Saccone HIDDEN(mgmt, reg, "", NL80211_CMD_REGISTER_FRAME, 0, CIB_NETDEV, handle_mgmt_reg);
91*92022041SSam Saccone 
handle_mgmt_dump(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)92*92022041SSam Saccone static int handle_mgmt_dump(struct nl80211_state *state,
93*92022041SSam Saccone 			       struct nl_msg *msg, int argc,
94*92022041SSam Saccone 			       char **argv, enum id_input id)
95*92022041SSam Saccone {
96*92022041SSam Saccone 	struct nl_cb *mgmt_cb;
97*92022041SSam Saccone 	char *ndev = argv[0];
98*92022041SSam Saccone 	int mgmt_argc = 5;
99*92022041SSam Saccone 	char **mgmt_argv;
100*92022041SSam Saccone 	unsigned int count = 0;
101*92022041SSam Saccone 	int err = 0;
102*92022041SSam Saccone 
103*92022041SSam Saccone 	mgmt_argv = calloc(mgmt_argc, sizeof(char*));
104*92022041SSam Saccone 	if (!mgmt_argv)
105*92022041SSam Saccone 		return -ENOMEM;
106*92022041SSam Saccone 
107*92022041SSam Saccone 	mgmt_argv[0] = ndev;
108*92022041SSam Saccone 	mgmt_argv[1] = "mgmt";
109*92022041SSam Saccone 	mgmt_argv[2] = "reg";
110*92022041SSam Saccone 
111*92022041SSam Saccone 	if (argc < 6) {
112*92022041SSam Saccone 		err = HANDLER_RET_USAGE;
113*92022041SSam Saccone 		goto out;
114*92022041SSam Saccone 	}
115*92022041SSam Saccone 
116*92022041SSam Saccone 	argc -= 3;
117*92022041SSam Saccone 	argv += 3;
118*92022041SSam Saccone 	while (argc >= 3) {
119*92022041SSam Saccone 		if (strcmp(argv[0], "frame") != 0) {
120*92022041SSam Saccone 			err = HANDLER_RET_USAGE;
121*92022041SSam Saccone 			goto out;
122*92022041SSam Saccone 		}
123*92022041SSam Saccone 
124*92022041SSam Saccone 		mgmt_argv[3] = argv[1];
125*92022041SSam Saccone 		mgmt_argv[4] = argv[2];
126*92022041SSam Saccone 
127*92022041SSam Saccone 		argc -= 3;
128*92022041SSam Saccone 		argv += 3;
129*92022041SSam Saccone 
130*92022041SSam Saccone 		err = handle_cmd(state, II_NETDEV, mgmt_argc, mgmt_argv);
131*92022041SSam Saccone 		if (err)
132*92022041SSam Saccone 			goto out;
133*92022041SSam Saccone 	}
134*92022041SSam Saccone 
135*92022041SSam Saccone 	if (argc == 2 && strcmp(argv[0], "count") == 0) {
136*92022041SSam Saccone 		count = 1 + atoi(argv[1]);
137*92022041SSam Saccone 		if (count < 1)
138*92022041SSam Saccone 			count = 1;
139*92022041SSam Saccone 
140*92022041SSam Saccone 		argc -= 2;
141*92022041SSam Saccone 		argv += 2;
142*92022041SSam Saccone 	} else if (argc) {
143*92022041SSam Saccone 		err = HANDLER_RET_USAGE;
144*92022041SSam Saccone 		goto out;
145*92022041SSam Saccone 	}
146*92022041SSam Saccone 
147*92022041SSam Saccone 	mgmt_cb = nl_cb_alloc(iw_debug ? NL_CB_DEBUG : NL_CB_DEFAULT);
148*92022041SSam Saccone 	if (!mgmt_cb) {
149*92022041SSam Saccone 		err = 1;
150*92022041SSam Saccone 		goto out;
151*92022041SSam Saccone 	}
152*92022041SSam Saccone 
153*92022041SSam Saccone 	/* need to turn off sequence number checking */
154*92022041SSam Saccone 	nl_cb_set(mgmt_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, seq_handler, NULL);
155*92022041SSam Saccone 	nl_cb_set(mgmt_cb, NL_CB_VALID, NL_CB_CUSTOM, dump_mgmt_frame, NULL);
156*92022041SSam Saccone 
157*92022041SSam Saccone 	while (--count)
158*92022041SSam Saccone 		nl_recvmsgs(state->nl_sock, mgmt_cb);
159*92022041SSam Saccone 
160*92022041SSam Saccone 	nl_cb_put(mgmt_cb);
161*92022041SSam Saccone out:
162*92022041SSam Saccone 	free(mgmt_argv);
163*92022041SSam Saccone 	return err;
164*92022041SSam Saccone }
165*92022041SSam Saccone 
166*92022041SSam Saccone COMMAND(mgmt, dump, "frame <type as hex ab> <pattern as hex ab:cd:..> [frame <type> <pattern>]* [count <frames>]",
167*92022041SSam Saccone 	0, 0, CIB_NETDEV, handle_mgmt_dump,
168*92022041SSam Saccone 	"Register for receiving certain mgmt frames and print them.\n"
169*92022041SSam Saccone 	"Frames are selected by their type and pattern containing\n"
170*92022041SSam Saccone 	"the first several bytes of the frame that should match.\n\n"
171*92022041SSam Saccone 	"Example: iw dev wlan0 mgmt dump frame 40 00 frame 40 01:02 count 10\n");
172