HS 2.0: Add Hotspot 2.0 station ctrl_iface

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jay Katabathuni 2011-09-08 20:52:23 +03:00 committed by Jouni Malinen
parent 66aadbd7bf
commit a8918e86b6
2 changed files with 177 additions and 0 deletions

View File

@ -28,6 +28,7 @@
#include "ap.h"
#include "p2p_supplicant.h"
#include "p2p/p2p.h"
#include "hs20_supplicant.h"
#include "notify.h"
#include "bss.h"
#include "scan.h"
@ -3713,6 +3714,111 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
#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(
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)
reply_len = -1;
#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)
{
if (wpa_supplicant_ctrl_iface_ctrl_rsp(

View File

@ -20,6 +20,7 @@
#include "utils/edit.h"
#include "utils/list.h"
#include "common/version.h"
#include "common/ieee802_11_defs.h"
#ifdef ANDROID
#include <cutils/properties.h>
#endif /* ANDROID */
@ -2659,6 +2660,60 @@ static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
#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,
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,
"<addr> <info id>[,<info id>]... = request ANQP information" },
#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,
"<0/1> = disable/enable automatic reconnection" },
{ "tdls_discover", wpa_cli_cmd_tdls_discover,