WPS ER: Add command for fetching current AP settings
This commit is contained in:
parent
82b857ec0b
commit
e64dcfd54b
8 changed files with 355 additions and 11 deletions
|
@ -677,5 +677,7 @@ void wps_er_deinit(struct wps_er *er);
|
||||||
void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id,
|
void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id,
|
||||||
u16 sel_reg_config_methods);
|
u16 sel_reg_config_methods);
|
||||||
int wps_er_pbc(struct wps_er *er, const u8 *uuid);
|
int wps_er_pbc(struct wps_er *er, const u8 *uuid);
|
||||||
|
int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin,
|
||||||
|
size_t pin_len);
|
||||||
|
|
||||||
#endif /* WPS_H */
|
#endif /* WPS_H */
|
||||||
|
|
291
src/wps/wps_er.c
291
src/wps/wps_er.c
|
@ -63,6 +63,7 @@ struct wps_er_ap {
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
char *location;
|
char *location;
|
||||||
struct http_client *http;
|
struct http_client *http;
|
||||||
|
struct wps_data *wps;
|
||||||
|
|
||||||
u8 uuid[WPS_UUID_LEN];
|
u8 uuid[WPS_UUID_LEN];
|
||||||
char *friendly_name;
|
char *friendly_name;
|
||||||
|
@ -82,6 +83,8 @@ struct wps_er_ap {
|
||||||
|
|
||||||
int subscribed;
|
int subscribed;
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
|
|
||||||
|
struct wps_credential *ap_settings;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wps_er {
|
struct wps_er {
|
||||||
|
@ -100,6 +103,9 @@ struct wps_er {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg);
|
||||||
|
|
||||||
|
|
||||||
static void wps_er_sta_event(struct wps_context *wps, struct wps_er_sta *sta,
|
static void wps_er_sta_event(struct wps_context *wps, struct wps_er_sta *sta,
|
||||||
enum wps_event event)
|
enum wps_event event)
|
||||||
{
|
{
|
||||||
|
@ -180,6 +186,17 @@ static struct wps_er_ap * wps_er_ap_get(struct wps_er *er,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct wps_er_ap * wps_er_ap_get_uuid(struct wps_er *er, const u8 *uuid)
|
||||||
|
{
|
||||||
|
struct wps_er_ap *ap;
|
||||||
|
for (ap = er->ap; ap; ap = ap->next) {
|
||||||
|
if (os_memcmp(uuid, ap->uuid, WPS_UUID_LEN) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct wps_er_ap * wps_er_ap_get_id(struct wps_er *er, unsigned int id)
|
static struct wps_er_ap * wps_er_ap_get_id(struct wps_er *er, unsigned int id)
|
||||||
{
|
{
|
||||||
struct wps_er_ap *ap;
|
struct wps_er_ap *ap;
|
||||||
|
@ -815,7 +832,8 @@ static const char *urn_wfawlanconfig =
|
||||||
"urn:schemas-wifialliance-org:service:WFAWLANConfig:1";
|
"urn:schemas-wifialliance-org:service:WFAWLANConfig:1";
|
||||||
|
|
||||||
static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg,
|
static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg,
|
||||||
const char *name, const char *path,
|
const char *name, const char *arg_name,
|
||||||
|
const char *path,
|
||||||
const struct sockaddr_in *dst,
|
const struct sockaddr_in *dst,
|
||||||
char **len_ptr, char **body_ptr)
|
char **len_ptr, char **body_ptr)
|
||||||
{
|
{
|
||||||
|
@ -823,10 +841,15 @@ static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg,
|
||||||
size_t encoded_len;
|
size_t encoded_len;
|
||||||
struct wpabuf *buf;
|
struct wpabuf *buf;
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
encoded = base64_encode(wpabuf_head(msg), wpabuf_len(msg),
|
encoded = base64_encode(wpabuf_head(msg), wpabuf_len(msg),
|
||||||
&encoded_len);
|
&encoded_len);
|
||||||
if (encoded == NULL)
|
if (encoded == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
} else {
|
||||||
|
encoded = NULL;
|
||||||
|
encoded_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
buf = wpabuf_alloc(1000 + encoded_len);
|
buf = wpabuf_alloc(1000 + encoded_len);
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
|
@ -854,8 +877,11 @@ static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg,
|
||||||
wpabuf_printf(buf, "<u:%s xmlns:u=\"", name);
|
wpabuf_printf(buf, "<u:%s xmlns:u=\"", name);
|
||||||
wpabuf_put_str(buf, urn_wfawlanconfig);
|
wpabuf_put_str(buf, urn_wfawlanconfig);
|
||||||
wpabuf_put_str(buf, "\">\n");
|
wpabuf_put_str(buf, "\">\n");
|
||||||
wpabuf_printf(buf, "<NewMessage>%s</NewMessage>\n", (char *) encoded);
|
if (encoded) {
|
||||||
|
wpabuf_printf(buf, "<%s>%s</%s>\n",
|
||||||
|
arg_name, (char *) encoded, arg_name);
|
||||||
os_free(encoded);
|
os_free(encoded);
|
||||||
|
}
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
@ -900,8 +926,8 @@ static void wps_er_sta_send_msg(struct wps_er_sta *sta, struct wpabuf *msg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = wps_er_soap_hdr(msg, "PutWLANResponse", path, &dst, &len_ptr,
|
buf = wps_er_soap_hdr(msg, "PutWLANResponse", "NewMessage", path, &dst,
|
||||||
&body_ptr);
|
&len_ptr, &body_ptr);
|
||||||
wpabuf_free(msg);
|
wpabuf_free(msg);
|
||||||
os_free(url);
|
os_free(url);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
|
@ -1254,8 +1280,8 @@ static void wps_er_send_set_sel_reg(struct wps_er_ap *ap, struct wpabuf *msg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = wps_er_soap_hdr(msg, "SetSelectedRegistrar", path, &dst,
|
buf = wps_er_soap_hdr(msg, "SetSelectedRegistrar", "NewMessage", path,
|
||||||
&len_ptr, &body_ptr);
|
&dst, &len_ptr, &body_ptr);
|
||||||
os_free(url);
|
os_free(url);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -1338,3 +1364,256 @@ int wps_er_pbc(struct wps_er *er, const u8 *uuid)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wps_er_ap_settings_cb(void *ctx, const struct wps_credential *cred)
|
||||||
|
{
|
||||||
|
struct wps_er_ap *ap = ctx;
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: AP Settings received");
|
||||||
|
os_free(ap->ap_settings);
|
||||||
|
ap->ap_settings = os_malloc(sizeof(*cred));
|
||||||
|
if (ap->ap_settings) {
|
||||||
|
os_memcpy(ap->ap_settings, cred, sizeof(*cred));
|
||||||
|
ap->ap_settings->cred_attr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: send info through ctrl_iface */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wps_er_http_put_message_cb(void *ctx, struct http_client *c,
|
||||||
|
enum http_client_event event)
|
||||||
|
{
|
||||||
|
struct wps_er_ap *ap = ctx;
|
||||||
|
struct wpabuf *reply;
|
||||||
|
char *msg = NULL;
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case HTTP_CLIENT_OK:
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: PutMessage OK");
|
||||||
|
reply = http_client_get_body(c);
|
||||||
|
if (reply == NULL)
|
||||||
|
break;
|
||||||
|
msg = os_zalloc(wpabuf_len(reply) + 1);
|
||||||
|
if (msg == NULL)
|
||||||
|
break;
|
||||||
|
os_memcpy(msg, wpabuf_head(reply), wpabuf_len(reply));
|
||||||
|
break;
|
||||||
|
case HTTP_CLIENT_FAILED:
|
||||||
|
case HTTP_CLIENT_INVALID_REPLY:
|
||||||
|
case HTTP_CLIENT_TIMEOUT:
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: PutMessage failed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
http_client_free(ap->http);
|
||||||
|
ap->http = NULL;
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
|
struct wpabuf *buf;
|
||||||
|
enum http_reply_code ret;
|
||||||
|
buf = xml_get_base64_item(msg, "NewOutMessage", &ret);
|
||||||
|
os_free(msg);
|
||||||
|
if (buf == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: Could not extract "
|
||||||
|
"NewOutMessage from PutMessage response");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wps_er_ap_process(ap, buf);
|
||||||
|
wpabuf_free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wps_er_ap_put_message(struct wps_er_ap *ap,
|
||||||
|
const struct wpabuf *msg)
|
||||||
|
{
|
||||||
|
struct wpabuf *buf;
|
||||||
|
char *len_ptr, *body_ptr;
|
||||||
|
struct sockaddr_in dst;
|
||||||
|
char *url, *path;
|
||||||
|
|
||||||
|
if (ap->http) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP operation ongoing "
|
||||||
|
"with the AP - cannot continue learn");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ap->control_url == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
url = http_client_url_parse(ap->control_url, &dst, &path);
|
||||||
|
if (url == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = wps_er_soap_hdr(msg, "PutMessage", "NewInMessage", path, &dst,
|
||||||
|
&len_ptr, &body_ptr);
|
||||||
|
os_free(url);
|
||||||
|
if (buf == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wps_er_soap_end(buf, "PutMessage", len_ptr, body_ptr);
|
||||||
|
|
||||||
|
ap->http = http_client_addr(&dst, buf, 10000,
|
||||||
|
wps_er_http_put_message_cb, ap);
|
||||||
|
if (ap->http == NULL)
|
||||||
|
wpabuf_free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg)
|
||||||
|
{
|
||||||
|
enum wps_process_res res;
|
||||||
|
|
||||||
|
res = wps_process_msg(ap->wps, WSC_MSG, msg);
|
||||||
|
if (res == WPS_CONTINUE) {
|
||||||
|
enum wsc_op_code op_code;
|
||||||
|
struct wpabuf *next = wps_get_msg(ap->wps, &op_code);
|
||||||
|
if (next) {
|
||||||
|
wps_er_ap_put_message(ap, next);
|
||||||
|
wpabuf_free(next);
|
||||||
|
} else {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: Failed to build "
|
||||||
|
"message");
|
||||||
|
wps_deinit(ap->wps);
|
||||||
|
ap->wps = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: Failed to process message from "
|
||||||
|
"AP (res=%d)", res);
|
||||||
|
wps_deinit(ap->wps);
|
||||||
|
ap->wps = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wps_er_ap_learn(struct wps_er_ap *ap, const char *dev_info)
|
||||||
|
{
|
||||||
|
struct wpabuf *info;
|
||||||
|
enum http_reply_code ret;
|
||||||
|
struct wps_config cfg;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: Received GetDeviceInfo response (M1) "
|
||||||
|
"from the AP");
|
||||||
|
info = xml_get_base64_item(dev_info, "NewDeviceInfo", &ret);
|
||||||
|
if (info == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: Could not extract "
|
||||||
|
"NewDeviceInfo from GetDeviceInfo response");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ap->wps) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: Protocol run already in "
|
||||||
|
"progress with this AP");
|
||||||
|
wpabuf_free(info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_memset(&cfg, 0, sizeof(cfg));
|
||||||
|
cfg.wps = ap->er->wps;
|
||||||
|
cfg.registrar = 1;
|
||||||
|
ap->wps = wps_init(&cfg);
|
||||||
|
if (ap->wps == NULL) {
|
||||||
|
wpabuf_free(info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ap->wps->ap_settings_cb = wps_er_ap_settings_cb;
|
||||||
|
ap->wps->ap_settings_cb_ctx = ap;
|
||||||
|
|
||||||
|
wps_er_ap_process(ap, info);
|
||||||
|
wpabuf_free(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wps_er_http_get_dev_info_cb(void *ctx, struct http_client *c,
|
||||||
|
enum http_client_event event)
|
||||||
|
{
|
||||||
|
struct wps_er_ap *ap = ctx;
|
||||||
|
struct wpabuf *reply;
|
||||||
|
char *dev_info = NULL;
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case HTTP_CLIENT_OK:
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo OK");
|
||||||
|
reply = http_client_get_body(c);
|
||||||
|
if (reply == NULL)
|
||||||
|
break;
|
||||||
|
dev_info = os_zalloc(wpabuf_len(reply) + 1);
|
||||||
|
if (dev_info == NULL)
|
||||||
|
break;
|
||||||
|
os_memcpy(dev_info, wpabuf_head(reply), wpabuf_len(reply));
|
||||||
|
break;
|
||||||
|
case HTTP_CLIENT_FAILED:
|
||||||
|
case HTTP_CLIENT_INVALID_REPLY:
|
||||||
|
case HTTP_CLIENT_TIMEOUT:
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: GetDeviceInfo failed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
http_client_free(ap->http);
|
||||||
|
ap->http = NULL;
|
||||||
|
|
||||||
|
if (dev_info) {
|
||||||
|
wps_er_ap_learn(ap, dev_info);
|
||||||
|
os_free(dev_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin,
|
||||||
|
size_t pin_len)
|
||||||
|
{
|
||||||
|
struct wps_er_ap *ap;
|
||||||
|
struct wpabuf *buf;
|
||||||
|
char *len_ptr, *body_ptr;
|
||||||
|
struct sockaddr_in dst;
|
||||||
|
char *url, *path;
|
||||||
|
|
||||||
|
if (er == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ap = wps_er_ap_get_uuid(er, uuid);
|
||||||
|
if (ap == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: AP not found for learn "
|
||||||
|
"request");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ap->wps || ap->http) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: Pending operation ongoing "
|
||||||
|
"with the AP - cannot start learn");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ap->control_url == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
url = http_client_url_parse(ap->control_url, &dst, &path);
|
||||||
|
if (url == NULL) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = wps_er_soap_hdr(NULL, "GetDeviceInfo", NULL, path, &dst,
|
||||||
|
&len_ptr, &body_ptr);
|
||||||
|
os_free(url);
|
||||||
|
if (buf == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
wps_er_soap_end(buf, "GetDeviceInfo", len_ptr, body_ptr);
|
||||||
|
|
||||||
|
ap->http = http_client_addr(&dst, buf, 10000,
|
||||||
|
wps_er_http_get_dev_info_cb, ap);
|
||||||
|
if (ap->http == NULL) {
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: add PIN without SetSelectedRegistrar trigger to all APs */
|
||||||
|
wps_registrar_add_pin(er->wps->registrar, uuid, pin, pin_len, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -108,6 +108,9 @@ struct wps_data {
|
||||||
struct wps_credential *new_ap_settings;
|
struct wps_credential *new_ap_settings;
|
||||||
|
|
||||||
void *dh_ctx;
|
void *dh_ctx;
|
||||||
|
|
||||||
|
void (*ap_settings_cb)(void *ctx, const struct wps_credential *cred);
|
||||||
|
void *ap_settings_cb_ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2234,6 +2234,11 @@ static int wps_process_ap_settings_r(struct wps_data *wps,
|
||||||
* Use the AP PIN only to receive the current AP settings, not
|
* Use the AP PIN only to receive the current AP settings, not
|
||||||
* to reconfigure the AP.
|
* to reconfigure the AP.
|
||||||
*/
|
*/
|
||||||
|
if (wps->ap_settings_cb) {
|
||||||
|
wps->ap_settings_cb(wps->ap_settings_cb_ctx,
|
||||||
|
&wps->cred);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
wps_sta_cred_cb(wps);
|
wps_sta_cred_cb(wps);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,6 +308,18 @@ static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
|
||||||
*pin++ = '\0';
|
*pin++ = '\0';
|
||||||
return wpas_wps_er_add_pin(wpa_s, uuid, pin);
|
return wpas_wps_er_add_pin(wpa_s, uuid, pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_supplicant_ctrl_iface_wps_er_learn(struct wpa_supplicant *wpa_s,
|
||||||
|
char *cmd)
|
||||||
|
{
|
||||||
|
char *uuid = cmd, *pin;
|
||||||
|
pin = os_strchr(uuid, ' ');
|
||||||
|
if (pin == NULL)
|
||||||
|
return -1;
|
||||||
|
*pin++ = '\0';
|
||||||
|
return wpas_wps_er_learn(wpa_s, uuid, pin);
|
||||||
|
}
|
||||||
#endif /* CONFIG_WPS_ER */
|
#endif /* CONFIG_WPS_ER */
|
||||||
|
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
|
@ -1660,6 +1672,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
} else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
|
} else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
|
||||||
if (wpas_wps_er_pbc(wpa_s, buf + 11))
|
if (wpas_wps_er_pbc(wpa_s, buf + 11))
|
||||||
reply_len = -1;
|
reply_len = -1;
|
||||||
|
} else if (os_strncmp(buf, "WPS_ER_LEARN ", 13) == 0) {
|
||||||
|
if (wpa_supplicant_ctrl_iface_wps_er_learn(wpa_s, buf + 13))
|
||||||
|
reply_len = -1;
|
||||||
#endif /* CONFIG_WPS_ER */
|
#endif /* CONFIG_WPS_ER */
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
#ifdef CONFIG_IBSS_RSN
|
#ifdef CONFIG_IBSS_RSN
|
||||||
|
|
|
@ -594,6 +594,29 @@ static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
char cmd[256];
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
|
||||||
|
"- UUID: specify which AP to use\n"
|
||||||
|
"- PIN: AP PIN\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
|
||||||
|
argv[0], argv[1]);
|
||||||
|
if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
|
||||||
|
printf("Too long WPS_ER_LEARN command.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return wpa_ctrl_command(ctrl, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char cmd[256];
|
char cmd[256];
|
||||||
|
@ -1470,6 +1493,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
|
||||||
{ "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
|
{ "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
|
||||||
cli_cmd_flag_none,
|
cli_cmd_flag_none,
|
||||||
"<UUID> = accept an Enrollee PBC using External Registrar" },
|
"<UUID> = accept an Enrollee PBC using External Registrar" },
|
||||||
|
{ "wps_er_learn", wpa_cli_cmd_wps_er_learn,
|
||||||
|
cli_cmd_flag_sensitive,
|
||||||
|
"<UUID> <PIN> = learn AP configuration" },
|
||||||
{ "ibss_rsn", wpa_cli_cmd_ibss_rsn,
|
{ "ibss_rsn", wpa_cli_cmd_ibss_rsn,
|
||||||
cli_cmd_flag_none,
|
cli_cmd_flag_none,
|
||||||
"<addr> = request RSN authentication with <addr> in IBSS" },
|
"<addr> = request RSN authentication with <addr> in IBSS" },
|
||||||
|
|
|
@ -1171,4 +1171,16 @@ int wpas_wps_er_pbc(struct wpa_supplicant *wpa_s, const char *uuid)
|
||||||
return -1;
|
return -1;
|
||||||
return wps_er_pbc(wpa_s->wps_er, u);
|
return wps_er_pbc(wpa_s->wps_er, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid,
|
||||||
|
const char *pin)
|
||||||
|
{
|
||||||
|
u8 u[UUID_LEN];
|
||||||
|
|
||||||
|
if (uuid_str2bin(uuid, u))
|
||||||
|
return -1;
|
||||||
|
return wps_er_learn(wpa_s->wps_er, u, (const u8 *) pin,
|
||||||
|
os_strlen(pin));
|
||||||
|
}
|
||||||
#endif /* CONFIG_WPS_ER */
|
#endif /* CONFIG_WPS_ER */
|
||||||
|
|
|
@ -54,6 +54,8 @@ int wpas_wps_er_stop(struct wpa_supplicant *wpa_s);
|
||||||
int wpas_wps_er_add_pin(struct wpa_supplicant *wpa_s, const char *uuid,
|
int wpas_wps_er_add_pin(struct wpa_supplicant *wpa_s, const char *uuid,
|
||||||
const char *pin);
|
const char *pin);
|
||||||
int wpas_wps_er_pbc(struct wpa_supplicant *wpa_s, const char *uuid);
|
int wpas_wps_er_pbc(struct wpa_supplicant *wpa_s, const char *uuid);
|
||||||
|
int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid,
|
||||||
|
const char *pin);
|
||||||
|
|
||||||
#else /* CONFIG_WPS */
|
#else /* CONFIG_WPS */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue