HS 2.0: Add Hotspot 2.0 station ctrl_iface
Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
66aadbd7bf
commit
a8918e86b6
2 changed files with 177 additions and 0 deletions
|
@ -28,6 +28,7 @@
|
||||||
#include "ap.h"
|
#include "ap.h"
|
||||||
#include "p2p_supplicant.h"
|
#include "p2p_supplicant.h"
|
||||||
#include "p2p/p2p.h"
|
#include "p2p/p2p.h"
|
||||||
|
#include "hs20_supplicant.h"
|
||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
#include "bss.h"
|
#include "bss.h"
|
||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
|
@ -3713,6 +3714,111 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
|
||||||
#endif /* CONFIG_INTERWORKING */
|
#endif /* CONFIG_INTERWORKING */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_HS20
|
||||||
|
|
||||||
|
static int get_hs20_anqp(struct wpa_supplicant *wpa_s, char *dst)
|
||||||
|
{
|
||||||
|
u8 dst_addr[ETH_ALEN];
|
||||||
|
int used;
|
||||||
|
char *pos;
|
||||||
|
u32 subtypes = 0;
|
||||||
|
|
||||||
|
used = hwaddr_aton2(dst, dst_addr);
|
||||||
|
if (used < 0)
|
||||||
|
return -1;
|
||||||
|
pos = dst + used;
|
||||||
|
for (;;) {
|
||||||
|
int num = atoi(pos);
|
||||||
|
if (num <= 0 || num > 31)
|
||||||
|
return -1;
|
||||||
|
subtypes |= BIT(num);
|
||||||
|
pos = os_strchr(pos + 1, ',');
|
||||||
|
if (pos == NULL)
|
||||||
|
break;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subtypes == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hs20_nai_home_realm_list(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *addr, const char *realm)
|
||||||
|
{
|
||||||
|
u8 *buf;
|
||||||
|
size_t rlen, len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
rlen = os_strlen(realm);
|
||||||
|
len = 3 + rlen;
|
||||||
|
buf = os_malloc(len);
|
||||||
|
if (buf == NULL)
|
||||||
|
return -1;
|
||||||
|
buf[0] = 1; /* NAI Home Realm Count */
|
||||||
|
buf[1] = 0; /* Formatted in accordance with RFC 4282 */
|
||||||
|
buf[2] = rlen;
|
||||||
|
os_memcpy(buf + 3, realm, rlen);
|
||||||
|
|
||||||
|
ret = hs20_anqp_send_req(wpa_s, addr,
|
||||||
|
BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
|
||||||
|
buf, len);
|
||||||
|
|
||||||
|
os_free(buf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hs20_get_nai_home_realm_list(struct wpa_supplicant *wpa_s,
|
||||||
|
char *dst)
|
||||||
|
{
|
||||||
|
struct wpa_cred *cred = wpa_s->conf->cred;
|
||||||
|
u8 dst_addr[ETH_ALEN];
|
||||||
|
int used;
|
||||||
|
u8 *buf;
|
||||||
|
size_t len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
used = hwaddr_aton2(dst, dst_addr);
|
||||||
|
if (used < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while (dst[used] == ' ')
|
||||||
|
used++;
|
||||||
|
if (os_strncmp(dst + used, "realm=", 6) == 0)
|
||||||
|
return hs20_nai_home_realm_list(wpa_s, dst_addr,
|
||||||
|
dst + used + 6);
|
||||||
|
|
||||||
|
len = os_strlen(dst + used);
|
||||||
|
|
||||||
|
if (len == 0 && cred && cred->realm)
|
||||||
|
return hs20_nai_home_realm_list(wpa_s, dst_addr, cred->realm);
|
||||||
|
|
||||||
|
if (len % 1)
|
||||||
|
return -1;
|
||||||
|
len /= 2;
|
||||||
|
buf = os_malloc(len);
|
||||||
|
if (buf == NULL)
|
||||||
|
return -1;
|
||||||
|
if (hexstr2bin(dst + used, buf, len) < 0) {
|
||||||
|
os_free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = hs20_anqp_send_req(wpa_s, dst_addr,
|
||||||
|
BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
|
||||||
|
buf, len);
|
||||||
|
os_free(buf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_HS20 */
|
||||||
|
|
||||||
|
|
||||||
static int wpa_supplicant_ctrl_iface_sta_autoconnect(
|
static int wpa_supplicant_ctrl_iface_sta_autoconnect(
|
||||||
struct wpa_supplicant *wpa_s, char *cmd)
|
struct wpa_supplicant *wpa_s, char *cmd)
|
||||||
{
|
{
|
||||||
|
@ -4026,6 +4132,14 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
if (get_anqp(wpa_s, buf + 9) < 0)
|
if (get_anqp(wpa_s, buf + 9) < 0)
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
#endif /* CONFIG_INTERWORKING */
|
#endif /* CONFIG_INTERWORKING */
|
||||||
|
#ifdef CONFIG_HS20
|
||||||
|
} else if (os_strncmp(buf, "HS20_ANQP_GET ", 14) == 0) {
|
||||||
|
if (get_hs20_anqp(wpa_s, buf + 14) < 0)
|
||||||
|
reply_len = -1;
|
||||||
|
} else if (os_strncmp(buf, "HS20_GET_NAI_HOME_REALM_LIST ", 29) == 0) {
|
||||||
|
if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
|
||||||
|
reply_len = -1;
|
||||||
|
#endif /* CONFIG_HS20 */
|
||||||
} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
|
} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
|
||||||
{
|
{
|
||||||
if (wpa_supplicant_ctrl_iface_ctrl_rsp(
|
if (wpa_supplicant_ctrl_iface_ctrl_rsp(
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "utils/edit.h"
|
#include "utils/edit.h"
|
||||||
#include "utils/list.h"
|
#include "utils/list.h"
|
||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
|
#include "common/ieee802_11_defs.h"
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
#include <cutils/properties.h>
|
#include <cutils/properties.h>
|
||||||
#endif /* ANDROID */
|
#endif /* ANDROID */
|
||||||
|
@ -2659,6 +2660,60 @@ static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||||
#endif /* CONFIG_INTERWORKING */
|
#endif /* CONFIG_INTERWORKING */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_HS20
|
||||||
|
|
||||||
|
static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
char cmd[100];
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Invalid HS20_ANQP_GET command: needs two arguments "
|
||||||
|
"(addr and subtype list)\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = os_snprintf(cmd, sizeof(cmd), "HS20_ANQP_GET %s %s",
|
||||||
|
argv[0], argv[1]);
|
||||||
|
if (res < 0 || (size_t) res >= sizeof(cmd))
|
||||||
|
return -1;
|
||||||
|
cmd[sizeof(cmd) - 1] = '\0';
|
||||||
|
return wpa_ctrl_command(ctrl, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
char cmd[512];
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (argc == 0) {
|
||||||
|
printf("Command needs one or two arguments (dst mac addr and "
|
||||||
|
"optional home realm)\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
res = os_snprintf(cmd, sizeof(cmd),
|
||||||
|
"HS20_GET_NAI_HOME_REALM_LIST %s",
|
||||||
|
argv[0]);
|
||||||
|
else
|
||||||
|
res = os_snprintf(cmd, sizeof(cmd),
|
||||||
|
"HS20_GET_NAI_HOME_REALM_LIST %s %s",
|
||||||
|
argv[0], argv[1]);
|
||||||
|
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||||
|
printf("Too long command.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wpa_ctrl_command(ctrl, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_HS20 */
|
||||||
|
|
||||||
|
|
||||||
static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
|
static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
|
||||||
char *argv[])
|
char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -3102,6 +3157,14 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
|
||||||
{ "anqp_get", wpa_cli_cmd_anqp_get, cli_cmd_flag_none,
|
{ "anqp_get", wpa_cli_cmd_anqp_get, cli_cmd_flag_none,
|
||||||
"<addr> <info id>[,<info id>]... = request ANQP information" },
|
"<addr> <info id>[,<info id>]... = request ANQP information" },
|
||||||
#endif /* CONFIG_INTERWORKING */
|
#endif /* CONFIG_INTERWORKING */
|
||||||
|
#ifdef CONFIG_HS20
|
||||||
|
{ "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, cli_cmd_flag_none,
|
||||||
|
"<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
|
||||||
|
},
|
||||||
|
{ "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
|
||||||
|
cli_cmd_flag_none,
|
||||||
|
"<addr> <home realm> = get HS20 nai home realm list" },
|
||||||
|
#endif /* CONFIG_HS20 */
|
||||||
{ "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
|
{ "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
|
||||||
"<0/1> = disable/enable automatic reconnection" },
|
"<0/1> = disable/enable automatic reconnection" },
|
||||||
{ "tdls_discover", wpa_cli_cmd_tdls_discover,
|
{ "tdls_discover", wpa_cli_cmd_tdls_discover,
|
||||||
|
|
Loading…
Reference in a new issue