]> git.ipfire.org Git - thirdparty/iw.git/blobdiff - scan.c
iw: version.sh: update to get version with git correctly
[thirdparty/iw.git] / scan.c
diff --git a/scan.c b/scan.c
index e98f5d72e6db33000ff86253a4e49d6f94490eef..a942769dbc3e4f6a48d0e9e902298934a93332d8 100644 (file)
--- a/scan.c
+++ b/scan.c
@@ -1,7 +1,6 @@
 #include <net/if.h>
 #include <errno.h>
 #include <string.h>
-#include <ctype.h>
 #include <stdbool.h>
 
 #include <netlink/genl/genl.h>
@@ -102,19 +101,21 @@ static int parse_random_mac_addr(struct nl_msg *msg, char *arg)
 int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv)
 {
        struct nl_msg *matchset = NULL, *freqs = NULL, *ssids = NULL;
-       struct nlattr *match = NULL;
+       struct nl_msg *scan_plans = NULL;
+       struct nlattr *match = NULL, *plan = NULL;
        enum {
                ND_TOPLEVEL,
                ND_MATCH,
                ND_FREQS,
                ND_ACTIVE,
+               ND_PLANS,
        } parse_state = ND_TOPLEVEL;
        int c  = *argc;
        char *end, **v = *argv;
        int err = 0, i = 0;
-       unsigned int freq, interval = 0, delay = 0;
+       unsigned int freq, interval = 0, delay = 0, iterations = 0;
        bool have_matchset = false, have_freqs = false, have_ssids = false;
-       bool have_active = false, have_passive = false;
+       bool have_active = false, have_passive = false, have_plans = false;
        uint32_t flags = 0;
 
        matchset = nlmsg_alloc();
@@ -135,6 +136,12 @@ int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv)
                goto out;
        }
 
+       scan_plans = nlmsg_alloc();
+       if (!scan_plans) {
+               err = -ENOBUFS;
+               goto out;
+       }
+
        while (c) {
                switch (parse_state) {
                case ND_TOPLEVEL:
@@ -145,7 +152,7 @@ int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv)
                                        goto nla_put_failure;
                                }
 
-                               if (interval) {
+                               if (interval || have_plans) {
                                        err = -EINVAL;
                                        goto nla_put_failure;
                                }
@@ -157,6 +164,15 @@ int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv)
                                NLA_PUT_U32(msg,
                                            NL80211_ATTR_SCHED_SCAN_INTERVAL,
                                            interval);
+                       } else if (!strcmp(v[0], "scan_plans")) {
+                               parse_state = ND_PLANS;
+                               if (have_plans || interval) {
+                                       err = -EINVAL;
+                                       goto nla_put_failure;
+                               }
+
+                               have_plans = true;
+                               i = 0;
                        } else if (!strcmp(v[0], "delay")) {
                                c--; v++;
                                if (c == 0) {
@@ -310,6 +326,47 @@ int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv)
                                parse_state = ND_TOPLEVEL;
                        }
                        break;
+               case ND_PLANS:
+                       iterations = 0;
+                       interval = strtoul(v[0], &end, 10);
+                       if (*end) {
+                               char *iter;
+
+                               if (*end != ':') {
+                                       err = -EINVAL;
+                                       goto nla_put_failure;
+                               }
+
+                               iter = ++end;
+                               iterations = strtoul(iter, &end, 10);
+                               if (*end || !iterations) {
+                                       err = -EINVAL;
+                                       goto nla_put_failure;
+                               }
+                       }
+
+                       plan = nla_nest_start(scan_plans, i + 1);
+                       if (!plan) {
+                               err = -ENOBUFS;
+                               goto nla_put_failure;
+                       }
+
+                       NLA_PUT_U32(scan_plans,
+                                   NL80211_SCHED_SCAN_PLAN_INTERVAL,
+                                   interval);
+
+                       if (iterations)
+                               NLA_PUT_U32(scan_plans,
+                                           NL80211_SCHED_SCAN_PLAN_ITERATIONS,
+                                           iterations);
+                       else
+                               parse_state = ND_TOPLEVEL;
+
+                       nla_nest_end(scan_plans, plan);
+                       plan = NULL;
+                       i++;
+                       c--; v++;
+                       break;
                }
        }
 
@@ -321,6 +378,8 @@ int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv)
                nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);
        if (have_matchset)
                nla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_MATCH, matchset);
+       if (have_plans)
+               nla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_PLANS, scan_plans);
        if (flags)
                NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS, flags);
 
@@ -329,6 +388,7 @@ nla_put_failure:
                nla_nest_end(msg, match);
        nlmsg_free(freqs);
        nlmsg_free(matchset);
+       nlmsg_free(scan_plans);
 
 out:
        *argc = c;
@@ -446,8 +506,11 @@ static int handle_scan(struct nl80211_state *state,
 
        if (ies || meshid) {
                tmpies = (unsigned char *) malloc(ies_len + meshid_len);
-               if (!tmpies)
+               if (!tmpies) {
+                       free(ies);
+                       free(meshid);
                        goto nla_put_failure;
+               }
                if (ies) {
                        memcpy(tmpies, ies, ies_len);
                        free(ies);
@@ -456,7 +519,10 @@ static int handle_scan(struct nl80211_state *state,
                        memcpy(&tmpies[ies_len], meshid, meshid_len);
                        free(meshid);
                }
-               NLA_PUT(msg, NL80211_ATTR_IE, ies_len + meshid_len, tmpies);
+               if (nla_put(msg, NL80211_ATTR_IE, ies_len + meshid_len, tmpies) < 0) {
+                       free(tmpies);
+                       goto nla_put_failure;
+               }
                free(tmpies);
        }
 
@@ -1160,6 +1226,8 @@ static void print_capabilities(const uint8_t type, uint8_t len, const uint8_t *d
                        CAPA(46, "WNM-Notification");
                        CAPA(47, "Reserved");
                        CAPA(48, "UTF-8 SSID");
+                       CAPA(70, "FTM Responder");
+                       CAPA(71, "FTM Initiator");
                        default:
                                printf(" %d", bit);
                                break;
@@ -1912,6 +1980,12 @@ static int print_bss_handler(struct nl_msg *msg, void *arg)
        }
        printf("\n");
 
+       if (bss[NL80211_BSS_LAST_SEEN_BOOTTIME]) {
+               unsigned long long bt;
+               bt = (unsigned long long)nla_get_u64(bss[NL80211_BSS_LAST_SEEN_BOOTTIME]);
+               printf("\tlast seen: %llu.%.3llus [boottime]\n", bt/1000000000, (bt%1000000000)/1000000);
+       }
+
        if (bss[NL80211_BSS_TSF]) {
                unsigned long long tsf;
                tsf = (unsigned long long)nla_get_u64(bss[NL80211_BSS_TSF]);
@@ -2009,6 +2083,7 @@ static int handle_scan_combined(struct nl80211_state *state,
                NL80211_CMD_SCAN_ABORTED,
        };
        int trig_argc, dump_argc, err;
+       int i;
 
        if (argc >= 3 && !strcmp(argv[2], "-u")) {
                dump_argc = 4;
@@ -2026,7 +2101,7 @@ static int handle_scan_combined(struct nl80211_state *state,
        trig_argv[0] = argv[0];
        trig_argv[1] = "scan";
        trig_argv[2] = "trigger";
-       int i;
+
        for (i = 0; i < argc - 2 - (dump_argc - 3); i++)
                trig_argv[i + 3] = argv[i + 2 + (dump_argc - 3)];
        err = handle_cmd(state, id, trig_argc, trig_argv);