xref: /aosp_15_r20/external/iw/ftm.c (revision 92022041c981f431db0b590d0c3272306d0ea2a2)
1*92022041SSam Saccone #include <errno.h>
2*92022041SSam Saccone 
3*92022041SSam Saccone #include <netlink/genl/genl.h>
4*92022041SSam Saccone #include <netlink/genl/family.h>
5*92022041SSam Saccone #include <netlink/genl/ctrl.h>
6*92022041SSam Saccone #include <netlink/msg.h>
7*92022041SSam Saccone #include <netlink/attr.h>
8*92022041SSam Saccone #include <inttypes.h>
9*92022041SSam Saccone 
10*92022041SSam Saccone #include "nl80211.h"
11*92022041SSam Saccone #include "iw.h"
12*92022041SSam Saccone 
13*92022041SSam Saccone SECTION(ftm);
14*92022041SSam Saccone 
handle_ftm_stats(struct nl_msg * msg,void * arg)15*92022041SSam Saccone static int handle_ftm_stats(struct nl_msg *msg, void *arg)
16*92022041SSam Saccone {
17*92022041SSam Saccone 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
18*92022041SSam Saccone 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
19*92022041SSam Saccone 	struct nlattr *info[NL80211_FTM_STATS_MAX + 1];
20*92022041SSam Saccone 	static struct nla_policy info_policy[NL80211_FTM_STATS_MAX + 1] = {
21*92022041SSam Saccone 		[NL80211_FTM_STATS_SUCCESS_NUM]		= { .type = NLA_U32 },
22*92022041SSam Saccone 		[NL80211_FTM_STATS_PARTIAL_NUM]		= { .type = NLA_U32 },
23*92022041SSam Saccone 		[NL80211_FTM_STATS_FAILED_NUM]		= { .type = NLA_U32 },
24*92022041SSam Saccone 		[NL80211_FTM_STATS_ASAP_NUM]		= { .type = NLA_U32 },
25*92022041SSam Saccone 		[NL80211_FTM_STATS_NON_ASAP_NUM]		= { .type = NLA_U32 },
26*92022041SSam Saccone 		[NL80211_FTM_STATS_TOTAL_DURATION_MSEC]	= { .type = NLA_U64 },
27*92022041SSam Saccone 		[NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM]	= { .type = NLA_U32 },
28*92022041SSam Saccone 		[NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM]
29*92022041SSam Saccone 							= { .type = NLA_U32 },
30*92022041SSam Saccone 		[NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM]
31*92022041SSam Saccone 							= { .type = NLA_U32 },
32*92022041SSam Saccone 	};
33*92022041SSam Saccone 
34*92022041SSam Saccone 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
35*92022041SSam Saccone 		  genlmsg_attrlen(gnlh, 0), NULL);
36*92022041SSam Saccone 
37*92022041SSam Saccone 	if (!tb[NL80211_ATTR_FTM_RESPONDER_STATS]) {
38*92022041SSam Saccone 		fprintf(stderr, "FTM responder statistics are missing");
39*92022041SSam Saccone 		return NL_SKIP;
40*92022041SSam Saccone 	}
41*92022041SSam Saccone 
42*92022041SSam Saccone 	nla_parse(info, NL80211_REG_RULE_ATTR_MAX,
43*92022041SSam Saccone 		  nla_data(tb[NL80211_ATTR_FTM_RESPONDER_STATS]),
44*92022041SSam Saccone 		  nla_len(tb[NL80211_ATTR_FTM_RESPONDER_STATS]),
45*92022041SSam Saccone 		  info_policy);
46*92022041SSam Saccone 
47*92022041SSam Saccone 	printf("FTM responder stats:\n");
48*92022041SSam Saccone 
49*92022041SSam Saccone 	if (info[NL80211_FTM_STATS_SUCCESS_NUM])
50*92022041SSam Saccone 		printf("\tSuccess num %u\n",
51*92022041SSam Saccone 		       nla_get_u32(info[NL80211_FTM_STATS_SUCCESS_NUM]));
52*92022041SSam Saccone 
53*92022041SSam Saccone 	if (info[NL80211_FTM_STATS_PARTIAL_NUM])
54*92022041SSam Saccone 		printf("\tPartial success num %u\n",
55*92022041SSam Saccone 		       nla_get_u32(info[NL80211_FTM_STATS_PARTIAL_NUM]));
56*92022041SSam Saccone 
57*92022041SSam Saccone 	if (info[NL80211_FTM_STATS_FAILED_NUM])
58*92022041SSam Saccone 		printf("\tFailed num %u\n",
59*92022041SSam Saccone 		       nla_get_u32(info[NL80211_FTM_STATS_FAILED_NUM]));
60*92022041SSam Saccone 
61*92022041SSam Saccone 	if (info[NL80211_FTM_STATS_ASAP_NUM])
62*92022041SSam Saccone 		printf("\tASAP success num %u\n",
63*92022041SSam Saccone 		       nla_get_u32(info[NL80211_FTM_STATS_ASAP_NUM]));
64*92022041SSam Saccone 
65*92022041SSam Saccone 	if (info[NL80211_FTM_STATS_NON_ASAP_NUM])
66*92022041SSam Saccone 		printf("\tNon ASAP num %u\n",
67*92022041SSam Saccone 		       nla_get_u32(info[NL80211_FTM_STATS_NON_ASAP_NUM]));
68*92022041SSam Saccone 
69*92022041SSam Saccone 	if (info[NL80211_FTM_STATS_TOTAL_DURATION_MSEC])
70*92022041SSam Saccone 		printf("\tTotal duration %" PRIu64 "\n",
71*92022041SSam Saccone 		       nla_get_u64(info[NL80211_FTM_STATS_TOTAL_DURATION_MSEC]));
72*92022041SSam Saccone 
73*92022041SSam Saccone 	if (info[NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM])
74*92022041SSam Saccone 		printf("\tUnknown triggers num %u\n",
75*92022041SSam Saccone 		       nla_get_u32(info[NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM]));
76*92022041SSam Saccone 
77*92022041SSam Saccone 	if (info[NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM])
78*92022041SSam Saccone 		printf("\tRescheduled requests num %u\n",
79*92022041SSam Saccone 		       nla_get_u32(info[NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM]));
80*92022041SSam Saccone 
81*92022041SSam Saccone 	if (info[NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM])
82*92022041SSam Saccone 		printf("\tOut of window num %u\n",
83*92022041SSam Saccone 		       nla_get_u32(info[NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM]));
84*92022041SSam Saccone 
85*92022041SSam Saccone 	return NL_SKIP;
86*92022041SSam Saccone }
87*92022041SSam Saccone 
handle_ftm_get_stats(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)88*92022041SSam Saccone static int handle_ftm_get_stats(struct nl80211_state *state,
89*92022041SSam Saccone 			       struct nl_msg *msg, int argc, char **argv,
90*92022041SSam Saccone 			       enum id_input id)
91*92022041SSam Saccone {
92*92022041SSam Saccone 	register_handler(handle_ftm_stats, NULL);
93*92022041SSam Saccone 	return 0;
94*92022041SSam Saccone }
95*92022041SSam Saccone 
96*92022041SSam Saccone COMMAND(ftm, get_stats, "",
97*92022041SSam Saccone 	NL80211_CMD_GET_FTM_RESPONDER_STATS, 0, CIB_NETDEV, handle_ftm_get_stats,
98*92022041SSam Saccone 	"Get FTM responder statistics.\n");
99*92022041SSam Saccone 
handle_ftm_start_responder(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)100*92022041SSam Saccone static int handle_ftm_start_responder(struct nl80211_state *state,
101*92022041SSam Saccone 				      struct nl_msg *msg, int argc, char **argv,
102*92022041SSam Saccone 				      enum id_input id)
103*92022041SSam Saccone {
104*92022041SSam Saccone 	int i;
105*92022041SSam Saccone 	char buf[256];
106*92022041SSam Saccone 	bool lci_present = false, civic_present = false;
107*92022041SSam Saccone 	struct nlattr *ftm = nla_nest_start(msg, NL80211_ATTR_FTM_RESPONDER);
108*92022041SSam Saccone 
109*92022041SSam Saccone 	if (!ftm)
110*92022041SSam Saccone 		return -ENOBUFS;
111*92022041SSam Saccone 
112*92022041SSam Saccone 	nla_put_flag(msg, NL80211_FTM_RESP_ATTR_ENABLED);
113*92022041SSam Saccone 
114*92022041SSam Saccone 	for (i = 0; i < argc; i++) {
115*92022041SSam Saccone 		if (strncmp(argv[i], "lci=", 4) == 0) {
116*92022041SSam Saccone 			size_t lci_len = strlen(argv[i] + 4);
117*92022041SSam Saccone 
118*92022041SSam Saccone 			if (lci_present || !lci_len || lci_len % 2 ||
119*92022041SSam Saccone 			    !hex2bin(argv[i] + 4, buf)) {
120*92022041SSam Saccone 				printf("Illegal LCI buffer!\n");
121*92022041SSam Saccone 				return HANDLER_RET_USAGE;
122*92022041SSam Saccone 			}
123*92022041SSam Saccone 
124*92022041SSam Saccone 			lci_present = true;
125*92022041SSam Saccone 			NLA_PUT(msg, NL80211_FTM_RESP_ATTR_LCI,
126*92022041SSam Saccone 				lci_len / 2, buf);
127*92022041SSam Saccone 		} else if (strncmp(argv[i], "civic=", 6) == 0) {
128*92022041SSam Saccone 			size_t civic_len = strlen(argv[i] + 6);
129*92022041SSam Saccone 
130*92022041SSam Saccone 			if (civic_present || !civic_len || civic_len % 2 ||
131*92022041SSam Saccone 			    !hex2bin(argv[i] + 6, buf)) {
132*92022041SSam Saccone 				printf("Illegal CIVIC buffer!\n");
133*92022041SSam Saccone 				return HANDLER_RET_USAGE;
134*92022041SSam Saccone 			}
135*92022041SSam Saccone 
136*92022041SSam Saccone 			civic_present = true;
137*92022041SSam Saccone 			NLA_PUT(msg, NL80211_FTM_RESP_ATTR_CIVICLOC,
138*92022041SSam Saccone 				civic_len / 2, buf);
139*92022041SSam Saccone 		} else {
140*92022041SSam Saccone 			printf("Illegal argument: %s\n", argv[i]);
141*92022041SSam Saccone 			return HANDLER_RET_USAGE;
142*92022041SSam Saccone 		}
143*92022041SSam Saccone 	}
144*92022041SSam Saccone 
145*92022041SSam Saccone 	nla_nest_end(msg, ftm);
146*92022041SSam Saccone 
147*92022041SSam Saccone 	return 0;
148*92022041SSam Saccone 
149*92022041SSam Saccone nla_put_failure:
150*92022041SSam Saccone 	return -ENOMEM;
151*92022041SSam Saccone }
152*92022041SSam Saccone 
153*92022041SSam Saccone COMMAND(ftm, start_responder,
154*92022041SSam Saccone 	"[lci=<lci buffer in hex>] [civic=<civic buffer in hex>]",
155*92022041SSam Saccone 	NL80211_CMD_SET_BEACON, 0, CIB_NETDEV,
156*92022041SSam Saccone 	handle_ftm_start_responder,
157*92022041SSam Saccone 	"Start an FTM responder. Needs a running ap interface\n");
158