]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
iw: add FTM responder commands
authorJohannes Berg <johannes.berg@intel.com>
Fri, 1 Feb 2019 22:00:40 +0000 (23:00 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 1 Feb 2019 22:01:12 +0000 (23:01 +0100)
Signed-off-by: David Spinadel <david.spinadel@intel.com>
Signed-off-by: Beni Lev <beni.lev@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Makefile
ftm.c [new file with mode: 0644]

index 73ee15731937eb671f14c1a8cf55aefcb31683b3..46d30306f63109dccf620b99a7dac79174079335 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,8 @@ OBJS = iw.o genl.o event.o info.o phy.o \
        mesh.o mpath.o mpp.o scan.o reg.o version.o \
        reason.o status.o connect.o link.o offch.o ps.o cqm.o \
        bitrate.o wowlan.o coalesce.o roc.o p2p.o vendor.o mgmt.o \
-       ap.o sha256.o nan.o bloom.o measurements.o
+       ap.o sha256.o nan.o bloom.o \
+       measurements.o ftm.o
 OBJS += sections.o
 
 OBJS-$(HWSIM) += hwsim.o
diff --git a/ftm.c b/ftm.c
new file mode 100644 (file)
index 0000000..23be38e
--- /dev/null
+++ b/ftm.c
@@ -0,0 +1,157 @@
+#include <errno.h>
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+#include <inttypes.h>
+
+#include "nl80211.h"
+#include "iw.h"
+
+SECTION(ftm);
+
+static int handle_ftm_stats(struct nl_msg *msg, void *arg)
+{
+       struct nlattr *tb[NL80211_ATTR_MAX + 1];
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       struct nlattr *info[NL80211_FTM_STATS_MAX + 1];
+       static struct nla_policy info_policy[NL80211_FTM_STATS_MAX + 1] = {
+               [NL80211_FTM_STATS_SUCCESS_NUM]         = { .type = NLA_U32 },
+               [NL80211_FTM_STATS_PARTIAL_NUM]         = { .type = NLA_U32 },
+               [NL80211_FTM_STATS_FAILED_NUM]          = { .type = NLA_U32 },
+               [NL80211_FTM_STATS_ASAP_NUM]            = { .type = NLA_U32 },
+               [NL80211_FTM_STATS_NON_ASAP_NUM]                = { .type = NLA_U32 },
+               [NL80211_FTM_STATS_TOTAL_DURATION_MSEC] = { .type = NLA_U64 },
+               [NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM]        = { .type = NLA_U32 },
+               [NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM]
+                                                       = { .type = NLA_U32 },
+               [NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM]
+                                                       = { .type = NLA_U32 },
+       };
+
+       nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+                 genlmsg_attrlen(gnlh, 0), NULL);
+
+       if (!tb[NL80211_ATTR_FTM_RESPONDER_STATS]) {
+               fprintf(stderr, "FTM responder statistics are missing");
+               return NL_SKIP;
+       }
+
+       nla_parse(info, NL80211_REG_RULE_ATTR_MAX,
+                 nla_data(tb[NL80211_ATTR_FTM_RESPONDER_STATS]),
+                 nla_len(tb[NL80211_ATTR_FTM_RESPONDER_STATS]),
+                 info_policy);
+
+       printf("FTM responder stats:\n");
+
+       if (info[NL80211_FTM_STATS_SUCCESS_NUM])
+               printf("\tSuccess num %u\n",
+                      nla_get_u32(info[NL80211_FTM_STATS_SUCCESS_NUM]));
+
+       if (info[NL80211_FTM_STATS_PARTIAL_NUM])
+               printf("\tPartial success num %u\n",
+                      nla_get_u32(info[NL80211_FTM_STATS_PARTIAL_NUM]));
+
+       if (info[NL80211_FTM_STATS_FAILED_NUM])
+               printf("\tFailed num %u\n",
+                      nla_get_u32(info[NL80211_FTM_STATS_FAILED_NUM]));
+
+       if (info[NL80211_FTM_STATS_ASAP_NUM])
+               printf("\tASAP success num %u\n",
+                      nla_get_u32(info[NL80211_FTM_STATS_ASAP_NUM]));
+
+       if (info[NL80211_FTM_STATS_NON_ASAP_NUM])
+               printf("\tNon ASAP num %u\n",
+                      nla_get_u32(info[NL80211_FTM_STATS_NON_ASAP_NUM]));
+
+       if (info[NL80211_FTM_STATS_TOTAL_DURATION_MSEC])
+               printf("\tTotal duration %" PRIu64 "\n",
+                      nla_get_u64(info[NL80211_FTM_STATS_TOTAL_DURATION_MSEC]));
+
+       if (info[NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM])
+               printf("\tUnknown triggers num %u\n",
+                      nla_get_u32(info[NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM]));
+
+       if (info[NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM])
+               printf("\tRescheduled requests num %u\n",
+                      nla_get_u32(info[NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM]));
+
+       if (info[NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM])
+               printf("\tOut of window num %u\n",
+                      nla_get_u32(info[NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM]));
+
+       return NL_SKIP;
+}
+
+static int handle_ftm_get_stats(struct nl80211_state *state,
+                              struct nl_msg *msg, int argc, char **argv,
+                              enum id_input id)
+{
+       register_handler(handle_ftm_stats, NULL);
+       return 0;
+}
+
+COMMAND(ftm, get_stats, "",
+       NL80211_CMD_GET_FTM_RESPONDER_STATS, 0, CIB_NETDEV, handle_ftm_get_stats,
+       "Get FTM responder statistics.\n");
+
+static int handle_ftm_start_responder(struct nl80211_state *state,
+                                     struct nl_msg *msg, int argc, char **argv,
+                                     enum id_input id)
+{
+       int i;
+       char buf[256];
+       bool lci_present = false, civic_present = false;
+       struct nlattr *ftm = nla_nest_start(msg, NL80211_ATTR_FTM_RESPONDER);
+
+       if (!ftm)
+               return -ENOBUFS;
+
+       nla_put_flag(msg, NL80211_FTM_RESP_ATTR_ENABLED);
+
+       for (i = 0; i < argc; i++) {
+               if (strncmp(argv[i], "lci=", 4) == 0) {
+                       size_t lci_len = strlen(argv[i] + 4);
+
+                       if (lci_present || !lci_len || lci_len % 2 ||
+                           !hex2bin(argv[i] + 4, buf)) {
+                               printf("Illegal LCI buffer!\n");
+                               return HANDLER_RET_USAGE;
+                       }
+
+                       lci_present = true;
+                       NLA_PUT(msg, NL80211_FTM_RESP_ATTR_LCI,
+                               lci_len / 2, buf);
+               } else if (strncmp(argv[i], "civic=", 6) == 0) {
+                       size_t civic_len = strlen(argv[i] + 6);
+
+                       if (civic_present || !civic_len || civic_len % 2 ||
+                           !hex2bin(argv[i] + 6, buf)) {
+                               printf("Illegal CIVIC buffer!\n");
+                               return HANDLER_RET_USAGE;
+                       }
+
+                       civic_present = true;
+                       NLA_PUT(msg, NL80211_FTM_RESP_ATTR_CIVICLOC,
+                               civic_len / 2, buf);
+               } else {
+                       printf("Illegal argument: %s\n", argv[i]);
+                       return HANDLER_RET_USAGE;
+               }
+       }
+
+       nla_nest_end(msg, ftm);
+
+       return 0;
+
+nla_put_failure:
+       return -ENOMEM;
+}
+
+COMMAND(ftm, start_responder,
+       "[lci=<lci buffer in hex>] [civic=<civic buffer in hex>]",
+       NL80211_CMD_SET_BEACON, 0, CIB_NETDEV,
+       handle_ftm_start_responder,
+       "Start an FTM responder. Needs a running ap interface\n");