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