From: Luciano Coelho <luciano.coelho@xxxxxxxxx> The scheduled scan structure is pretty much the same as the net-detect WoWLAN trigger's. Move the bulk of the command line parsing code to a generic function so we can reuse it for sched_scan. Signed-off-by: Luciano Coelho <luciano.coelho@xxxxxxxxx> --- iw.h | 4 ++ scan.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ wowlan.c | 174 +++------------------------------------------------------------ 3 files changed, 181 insertions(+), 167 deletions(-) diff --git a/iw.h b/iw.h index db88a86..efc21d6 100644 --- a/iw.h +++ b/iw.h @@ -173,6 +173,10 @@ void print_ies(unsigned char *ie, int ielen, bool unknown, void parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen); void iw_hexdump(const char *prefix, const __u8 *data, size_t len); +#define SCHED_SCAN_OPTIONS "interval <in_msecs> [delay <in_secs>] " \ + "[freqs <freq>+] [matches [ssid <ssid>]+]]" +int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv); + DECLARE_SECTION(set); DECLARE_SECTION(get); diff --git a/scan.c b/scan.c index 538b30e..d1c3bf2 100644 --- a/scan.c +++ b/scan.c @@ -99,6 +99,176 @@ static int parse_random_mac_addr(struct nl_msg *msg, char *arg) return -ENOBUFS; } +int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv) +{ + struct nl_msg *matchset = NULL, *freqs = NULL; + struct nlattr *match = NULL; + enum { + ND_TOPLEVEL, + ND_MATCH, + ND_FREQS, + } parse_state = ND_TOPLEVEL; + int c = *argc; + char *end, **v = *argv; + int err = 0, i = 0; + unsigned int freq, interval = 0, delay = 0; + bool have_matchset = false, have_freqs = false; + + matchset = nlmsg_alloc(); + if (!matchset) { + err = -ENOBUFS; + goto out; + } + + freqs = nlmsg_alloc(); + if (!freqs) { + err = -ENOBUFS; + goto out; + } + + while (c) { + switch (parse_state) { + case ND_TOPLEVEL: + if (!strcmp(v[0], "interval")) { + c--; v++; + if (c == 0) { + err = -EINVAL; + goto nla_put_failure; + } + + if (interval) { + err = -EINVAL; + goto nla_put_failure; + } + interval = strtoul(v[0], &end, 10); + if (*end || !interval) { + err = -EINVAL; + goto nla_put_failure; + } + NLA_PUT_U32(msg, + NL80211_ATTR_SCHED_SCAN_INTERVAL, + interval); + } else if (!strcmp(v[0], "delay")) { + c--; v++; + if (c == 0) { + err = -EINVAL; + goto nla_put_failure; + } + + if (delay) { + err = -EINVAL; + goto nla_put_failure; + } + delay = strtoul(v[0], &end, 10); + if (*end) { + err = -EINVAL; + goto nla_put_failure; + } + NLA_PUT_U32(msg, + NL80211_ATTR_SCHED_SCAN_DELAY, + delay); + } else if (!strcmp(v[0], "matches")) { + parse_state = ND_MATCH; + if (have_matchset) { + err = -EINVAL; + goto nla_put_failure; + } + + i = 0; + } else if (!strcmp(v[0], "freqs")) { + parse_state = ND_FREQS; + if (have_freqs) { + err = -EINVAL; + goto nla_put_failure; + } + + have_freqs = true; + i = 0; + } else { + /* this element is not for us, so + * return to continue parsing. + */ + goto nla_put_failure; + } + c--; v++; + + break; + case ND_MATCH: + if (!strcmp(v[0], "ssid")) { + c--; v++; + if (c == 0) { + err = -EINVAL; + goto nla_put_failure; + } + + /* TODO: for now we can only have an + * SSID in the match, so we can start + * the match nest here. + */ + match = nla_nest_start(matchset, i); + if (!match) { + err = -ENOBUFS; + goto nla_put_failure; + } + + NLA_PUT(matchset, + NL80211_SCHED_SCAN_MATCH_ATTR_SSID, + strlen(v[0]), v[0]); + nla_nest_end(matchset, match); + match = NULL; + + have_matchset = true; + i++; + c--; v++; + } else { + /* other element that cannot be part + * of a match indicates the end of the + * match. */ + /* need at least one match in the matchset */ + if (i == 0) { + err = -EINVAL; + goto nla_put_failure; + } + + parse_state = ND_TOPLEVEL; + } + + break; + case ND_FREQS: + freq = strtoul(v[0], &end, 10); + if (*end) { + if (i == 0) { + err = -EINVAL; + goto nla_put_failure; + } + + parse_state = ND_TOPLEVEL; + } else { + NLA_PUT_U32(freqs, i, freq); + i++; + c--; v++; + } + break; + } + } + + if (have_freqs) + nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs); + if (have_matchset) + nla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_MATCH, matchset); + +nla_put_failure: + if (match) + nla_nest_end(msg, match); + nlmsg_free(freqs); + nlmsg_free(matchset); + +out: + *argc = c; + *argv = v; + return err; +} + static int handle_scan(struct nl80211_state *state, struct nl_cb *cb, struct nl_msg *msg, diff --git a/wowlan.c b/wowlan.c index 82932e8..3a87665 100644 --- a/wowlan.c +++ b/wowlan.c @@ -183,177 +183,17 @@ static int wowlan_parse_tcp_file(struct nl_msg *msg, const char *fn) static int wowlan_parse_net_detect(struct nl_msg *msg, int *argc, char ***argv) { - struct nl_msg *matchset = NULL, *freqs = NULL; - struct nlattr *nd, *match = NULL; - enum { - ND_TOPLEVEL, - ND_MATCH, - ND_FREQS, - } parse_state = ND_TOPLEVEL; - int c = *argc; - char *end, **v = *argv; - int err = 0, i = 0; - unsigned int freq, interval = 0, delay = 0; - bool have_matchset = false, have_freqs = false; + struct nlattr *nd; + int err = 0; nd = nla_nest_start(msg, NL80211_WOWLAN_TRIG_NET_DETECT); - if (!nd) { - err = -ENOBUFS; - goto out; - } - - matchset = nlmsg_alloc(); - if (!matchset) { - err = -ENOBUFS; - goto out; - } - - freqs = nlmsg_alloc(); - if (!freqs) { - err = -ENOBUFS; - goto out; - } - - while (c) { - switch (parse_state) { - case ND_TOPLEVEL: - if (!strcmp(v[0], "interval")) { - c--; v++; - if (c == 0) { - err = -EINVAL; - goto nla_put_failure; - } - - if (interval) { - err = -EINVAL; - goto nla_put_failure; - } - interval = strtoul(v[0], &end, 10); - if (*end || !interval) { - err = -EINVAL; - goto nla_put_failure; - } - NLA_PUT_U32(msg, - NL80211_ATTR_SCHED_SCAN_INTERVAL, - interval); - } else if (!strcmp(v[0], "delay")) { - c--; v++; - if (c == 0) { - err = -EINVAL; - goto nla_put_failure; - } - - if (delay) { - err = -EINVAL; - goto nla_put_failure; - } - delay = strtoul(v[0], &end, 10); - if (*end) { - err = -EINVAL; - goto nla_put_failure; - } - NLA_PUT_U32(msg, - NL80211_ATTR_SCHED_SCAN_DELAY, - delay); - } else if (!strcmp(v[0], "matches")) { - parse_state = ND_MATCH; - if (have_matchset) { - err = -EINVAL; - goto nla_put_failure; - } - - i = 0; - } else if (!strcmp(v[0], "freqs")) { - parse_state = ND_FREQS; - if (have_freqs) { - err = -EINVAL; - goto nla_put_failure; - } - - have_freqs = true; - i = 0; - } else { - /* this element is not for us, so - * return to continue parsing. - */ - goto nla_put_failure; - } - c--; v++; - - break; - case ND_MATCH: - if (!strcmp(v[0], "ssid")) { - c--; v++; - if (c == 0) { - err = -EINVAL; - goto nla_put_failure; - } - - /* TODO: for now we can only have an - * SSID in the match, so we can start - * the match nest here. - */ - match = nla_nest_start(matchset, i); - if (!match) { - err = -ENOBUFS; - goto nla_put_failure; - } - - NLA_PUT(matchset, - NL80211_SCHED_SCAN_MATCH_ATTR_SSID, - strlen(v[0]), v[0]); - nla_nest_end(matchset, match); - match = NULL; - - have_matchset = true; - i++; - c--; v++; - } else { - /* other element that cannot be part - * of a match indicates the end of the - * match. */ - /* need at least one match in the matchset */ - if (i == 0) { - err = -EINVAL; - goto nla_put_failure; - } - - parse_state = ND_TOPLEVEL; - } - - break; - case ND_FREQS: - freq = strtoul(v[0], &end, 10); - if (*end) { - if (i == 0) { - err = -EINVAL; - goto nla_put_failure; - } - - parse_state = ND_TOPLEVEL; - } else { - NLA_PUT_U32(freqs, i, freq); - i++; - c--; v++; - } - break; - } - } + if (!nd) + return -ENOBUFS; - if (have_freqs) - nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs); - if (have_matchset) - nla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_MATCH, matchset); + err = parse_sched_scan(msg, argc, argv); -nla_put_failure: - if (match) - nla_nest_end(msg, match); - nlmsg_free(freqs); - nlmsg_free(matchset); nla_nest_end(msg, nd); -out: - *argc = c; - *argv = v; + return err; } @@ -473,7 +313,7 @@ static int handle_wowlan_enable(struct nl80211_state *state, struct nl_cb *cb, return err; } COMMAND(wowlan, enable, "[any] [disconnect] [magic-packet] [gtk-rekey-failure] [eap-identity-request]" - " [4way-handshake] [rfkill-release] [net-detect interval <in_msecs> [delay <in_secs>] [freqs <freq>+] [matches [ssid <ssid>]+]]" + " [4way-handshake] [rfkill-release] [net-detect " SCHED_SCAN_OPTIONS "]" " [tcp <config-file>] [patterns [offset1+]<pattern1> ...]", NL80211_CMD_SET_WOWLAN, 0, CIB_PHY, handle_wowlan_enable, "Enable WoWLAN with the given triggers.\n" -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html