#include "common.h"
#include "uuid.h"
#include "eloop.h"
+#include "httpread.h"
+#include "http_client.h"
+#include "http_server.h"
+#include "upnp_xml.h"
#include "wps_i.h"
#include "wps_upnp.h"
#include "wps_upnp_i.h"
/* TODO:
- * SSDP M-SEARCH multicast TX for WFA
- * create AP entry
- * fetch wps_device info based on LOCATION: from SSDP NOTIFY
- * parse wps_device info into AP entry (name, SCPD/control/eventSub URLs, etc.
- * subscribe to events
* send notification of new AP device with wpa_msg
* re-send notifications with wpa_msg if ER re-started (to update wpa_gui-qt4)
* (also re-send SSDP M-SEARCH in this case to find new APs)
*/
static void wps_er_ap_timeout(void *eloop_data, void *user_ctx);
+static void wps_er_sta_timeout(void *eloop_data, void *user_ctx);
+struct wps_er_sta {
+ struct wps_er_sta *next;
+ struct wps_er_ap *ap;
+ u8 addr[ETH_ALEN];
+ u16 config_methods;
+ u8 uuid[WPS_UUID_LEN];
+ u8 pri_dev_type[8];
+ u16 dev_passwd_id;
+ int m1_received;
+ char *manufacturer;
+ char *model_name;
+ char *model_number;
+ char *serial_number;
+ char *dev_name;
+ struct wps_data *wps;
+ struct http_client *http;
+};
+
struct wps_er_ap {
struct wps_er_ap *next;
+ struct wps_er *er;
+ struct wps_er_sta *sta; /* list of STAs/Enrollees using this AP */
struct in_addr addr;
char *location;
-
+ struct http_client *http;
+
+ char *friendly_name;
+ char *manufacturer;
+ char *manufacturer_url;
+ char *model_description;
+ char *model_name;
+ char *model_number;
+ char *model_url;
+ char *serial_number;
+ char *udn;
+ char *upc;
+
+ char *scpd_url;
+ char *control_url;
+ char *event_sub_url;
+
+ int subscribed;
+ unsigned int id;
};
struct wps_er {
- struct wps_registrar *reg;
+ struct wps_context *wps;
char ifname[17];
char *mac_addr_text; /* mac addr of network i.f. we use */
u8 mac_addr[ETH_ALEN]; /* mac addr of network i.f. we use */
int multicast_sd;
int ssdp_sd;
struct wps_er_ap *ap;
+ struct http_server *http_srv;
+ int http_port;
+ unsigned int next_ap_id;
};
+static struct wps_er_sta * wps_er_sta_get(struct wps_er_ap *ap, const u8 *addr)
+{
+ struct wps_er_sta *sta = ap->sta;
+ while (sta) {
+ if (os_memcmp(sta->addr, addr, ETH_ALEN) == 0)
+ return sta;
+ sta = sta->next;
+ }
+ return NULL;
+}
+
+
+static void wps_er_sta_free(struct wps_er_sta *sta)
+{
+ if (sta->wps)
+ wps_deinit(sta->wps);
+ os_free(sta->manufacturer);
+ os_free(sta->model_name);
+ os_free(sta->model_number);
+ os_free(sta->serial_number);
+ os_free(sta->dev_name);
+ http_client_free(sta->http);
+ eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL);
+ os_free(sta);
+}
+
+
+static void wps_er_sta_remove_all(struct wps_er_ap *ap)
+{
+ struct wps_er_sta *prev, *sta;
+
+ sta = ap->sta;
+ ap->sta = NULL;
+
+ while (sta) {
+ prev = sta;
+ sta = sta->next;
+ wps_er_sta_free(prev);
+ }
+}
+
+
static void wps_er_pin_needed_cb(void *ctx, const u8 *uuid_e,
const struct wps_device_data *dev)
{
}
+static struct wps_er_ap * wps_er_ap_get_id(struct wps_er *er, unsigned int id)
+{
+ struct wps_er_ap *ap;
+ for (ap = er->ap; ap; ap = ap->next) {
+ if (ap->id == id)
+ break;
+ }
+ return ap;
+}
+
+
static void wps_er_ap_free(struct wps_er *er, struct wps_er_ap *ap)
{
+ /* TODO: if ap->subscribed, unsubscribe from events if the AP is still
+ * alive */
wpa_printf(MSG_DEBUG, "WPS ER: Removing AP entry for %s (%s)",
inet_ntoa(ap->addr), ap->location);
eloop_cancel_timeout(wps_er_ap_timeout, er, ap);
os_free(ap->location);
+ http_client_free(ap->http);
+
+ os_free(ap->friendly_name);
+ os_free(ap->manufacturer);
+ os_free(ap->manufacturer_url);
+ os_free(ap->model_description);
+ os_free(ap->model_name);
+ os_free(ap->model_number);
+ os_free(ap->model_url);
+ os_free(ap->serial_number);
+ os_free(ap->udn);
+ os_free(ap->upc);
+
+ os_free(ap->scpd_url);
+ os_free(ap->control_url);
+ os_free(ap->event_sub_url);
+
+ wps_er_sta_remove_all(ap);
+
os_free(ap);
}
}
+static void wps_er_http_subscribe_cb(void *ctx, struct http_client *c,
+ enum http_client_event event)
+{
+ struct wps_er_ap *ap = ctx;
+
+ switch (event) {
+ case HTTP_CLIENT_OK:
+ wpa_printf(MSG_DEBUG, "WPS ER: Subscribed to events");
+ break;
+ case HTTP_CLIENT_FAILED:
+ case HTTP_CLIENT_INVALID_REPLY:
+ case HTTP_CLIENT_TIMEOUT:
+ wpa_printf(MSG_DEBUG, "WPS ER: Failed to subscribe to events");
+ break;
+ }
+ http_client_free(ap->http);
+ ap->http = NULL;
+}
+
+
+static void wps_er_subscribe(struct wps_er_ap *ap)
+{
+ struct wpabuf *req;
+ struct sockaddr_in dst;
+ char *url, *path;
+
+ if (ap->event_sub_url == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot "
+ "subscribe");
+ return;
+ }
+ if (ap->http) {
+ wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot "
+ "send subscribe request");
+ return;
+ }
+
+ url = http_client_url_parse(ap->event_sub_url, &dst, &path);
+ if (url == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL");
+ return;
+ }
+
+ req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000);
+ if (req == NULL) {
+ os_free(url);
+ return;
+ }
+ wpabuf_printf(req,
+ "SUBSCRIBE %s HTTP/1.1\r\n"
+ "HOST: %s:%d\r\n"
+ "CALLBACK: <http://%s:%d/event/%d>\r\n"
+ "NT: upnp:event\r\n"
+ "TIMEOUT: Second-%d\r\n"
+ "\r\n",
+ path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port),
+ ap->er->ip_addr_text, ap->er->http_port, ap->id, 1800);
+ os_free(url);
+ wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Subscription request",
+ wpabuf_head(req), wpabuf_len(req));
+
+ ap->http = http_client_addr(&dst, req, 1000, wps_er_http_subscribe_cb,
+ ap);
+ if (ap->http == NULL)
+ wpabuf_free(req);
+}
+
+
+static void wps_er_parse_device_description(struct wps_er_ap *ap,
+ struct wpabuf *reply)
+{
+ /* Note: reply includes null termination after the buffer data */
+ const char *data = wpabuf_head(reply);
+
+ wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Device info",
+ wpabuf_head(reply), wpabuf_len(reply));
+
+ ap->friendly_name = xml_get_first_item(data, "friendlyName");
+ wpa_printf(MSG_DEBUG, "WPS ER: friendlyName='%s'", ap->friendly_name);
+
+ ap->manufacturer = xml_get_first_item(data, "manufacturer");
+ wpa_printf(MSG_DEBUG, "WPS ER: manufacturer='%s'", ap->manufacturer);
+
+ ap->manufacturer_url = xml_get_first_item(data, "manufacturerURL");
+ wpa_printf(MSG_DEBUG, "WPS ER: manufacturerURL='%s'",
+ ap->manufacturer_url);
+
+ ap->model_description = xml_get_first_item(data, "modelDescription");
+ wpa_printf(MSG_DEBUG, "WPS ER: modelDescription='%s'",
+ ap->model_description);
+
+ ap->model_name = xml_get_first_item(data, "modelName");
+ wpa_printf(MSG_DEBUG, "WPS ER: modelName='%s'", ap->model_name);
+
+ ap->model_number = xml_get_first_item(data, "modelNumber");
+ wpa_printf(MSG_DEBUG, "WPS ER: modelNumber='%s'", ap->model_number);
+
+ ap->model_url = xml_get_first_item(data, "modelURL");
+ wpa_printf(MSG_DEBUG, "WPS ER: modelURL='%s'", ap->model_url);
+
+ ap->serial_number = xml_get_first_item(data, "serialNumber");
+ wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number);
+
+ ap->udn = xml_get_first_item(data, "UDN");
+ wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn);
+
+ ap->upc = xml_get_first_item(data, "UPC");
+ wpa_printf(MSG_DEBUG, "WPS ER: UPC='%s'", ap->upc);
+
+ ap->scpd_url = http_link_update(
+ xml_get_first_item(data, "SCPDURL"), ap->location);
+ wpa_printf(MSG_DEBUG, "WPS ER: SCPDURL='%s'", ap->scpd_url);
+
+ ap->control_url = http_link_update(
+ xml_get_first_item(data, "controlURL"), ap->location);
+ wpa_printf(MSG_DEBUG, "WPS ER: controlURL='%s'", ap->control_url);
+
+ ap->event_sub_url = http_link_update(
+ xml_get_first_item(data, "eventSubURL"), ap->location);
+ wpa_printf(MSG_DEBUG, "WPS ER: eventSubURL='%s'", ap->event_sub_url);
+}
+
+
+static void wps_er_http_dev_desc_cb(void *ctx, struct http_client *c,
+ enum http_client_event event)
+{
+ struct wps_er_ap *ap = ctx;
+ struct wpabuf *reply;
+ int subscribe = 0;
+
+ switch (event) {
+ case HTTP_CLIENT_OK:
+ reply = http_client_get_body(c);
+ if (reply == NULL)
+ break;
+ wps_er_parse_device_description(ap, reply);
+ subscribe = 1;
+ break;
+ case HTTP_CLIENT_FAILED:
+ case HTTP_CLIENT_INVALID_REPLY:
+ case HTTP_CLIENT_TIMEOUT:
+ wpa_printf(MSG_DEBUG, "WPS ER: Failed to fetch device info");
+ break;
+ }
+ http_client_free(ap->http);
+ ap->http = NULL;
+ if (subscribe)
+ wps_er_subscribe(ap);
+}
+
+
static void wps_er_ap_add(struct wps_er *er, struct in_addr *addr,
const char *location, int max_age)
{
ap = os_zalloc(sizeof(*ap));
if (ap == NULL)
return;
+ ap->er = er;
+ ap->id = ++er->next_ap_id;
ap->location = os_strdup(location);
if (ap->location == NULL) {
os_free(ap);
wpa_printf(MSG_DEBUG, "WPS ER: Added AP entry for %s (%s)",
inet_ntoa(ap->addr), ap->location);
- /* TODO: get device data and subscribe for events */
+ /* Fetch device description */
+ ap->http = http_client_url(ap->location, NULL, 10000,
+ wps_er_http_dev_desc_cb, ap);
}
}
+static void http_put_date(struct wpabuf *buf)
+{
+ wpabuf_put_str(buf, "Date: ");
+ format_date(buf);
+ wpabuf_put_str(buf, "\r\n");
+}
+
+
+static void wps_er_http_resp_not_found(struct http_request *req)
+{
+ struct wpabuf *buf;
+ buf = wpabuf_alloc(200);
+ if (buf == NULL) {
+ http_request_deinit(req);
+ return;
+ }
+
+ wpabuf_put_str(buf,
+ "HTTP/1.1 404 Not Found\r\n"
+ "Server: unspecified, UPnP/1.0, unspecified\r\n"
+ "Connection: close\r\n");
+ http_put_date(buf);
+ wpabuf_put_str(buf, "\r\n");
+ http_request_send_and_deinit(req, buf);
+}
+
+
+static void wps_er_http_resp_ok(struct http_request *req)
+{
+ struct wpabuf *buf;
+ buf = wpabuf_alloc(200);
+ if (buf == NULL) {
+ http_request_deinit(req);
+ return;
+ }
+
+ wpabuf_put_str(buf,
+ "HTTP/1.1 200 OK\r\n"
+ "Server: unspecified, UPnP/1.0, unspecified\r\n"
+ "Connection: close\r\n"
+ "Content-Length: 0\r\n");
+ http_put_date(buf);
+ wpabuf_put_str(buf, "\r\n");
+ http_request_send_and_deinit(req, buf);
+}
+
+
+static void wps_er_sta_timeout(void *eloop_data, void *user_ctx)
+{
+ struct wps_er_sta *sta = eloop_data;
+ wpa_printf(MSG_DEBUG, "WPS ER: STA entry timed out");
+ wps_er_sta_free(sta);
+}
+
+
+static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap,
+ const u8 *addr,
+ struct wps_parse_attr *attr,
+ int probe_req)
+{
+ struct wps_er_sta *sta = wps_er_sta_get(ap, addr);
+
+ if (sta == NULL) {
+ sta = os_zalloc(sizeof(*sta));
+ if (sta == NULL)
+ return NULL;
+ os_memcpy(sta->addr, addr, ETH_ALEN);
+ sta->ap = ap;
+ sta->next = ap->sta;
+ ap->sta = sta;
+ }
+
+ if (!probe_req)
+ sta->m1_received = 1;
+
+ if (attr->config_methods && (!probe_req || !sta->m1_received))
+ sta->config_methods = WPA_GET_BE16(attr->config_methods);
+ if (attr->uuid_e && (!probe_req || !sta->m1_received))
+ os_memcpy(sta->uuid, attr->uuid_e, WPS_UUID_LEN);
+ if (attr->primary_dev_type && (!probe_req || !sta->m1_received))
+ os_memcpy(sta->pri_dev_type, attr->primary_dev_type, 8);
+ if (attr->dev_password_id && (!probe_req || !sta->m1_received))
+ sta->dev_passwd_id = WPA_GET_BE16(attr->dev_password_id);
+
+ if (attr->manufacturer) {
+ os_free(sta->manufacturer);
+ sta->manufacturer = os_malloc(attr->manufacturer_len + 1);
+ if (sta->manufacturer) {
+ os_memcpy(sta->manufacturer, attr->manufacturer,
+ attr->manufacturer_len);
+ sta->manufacturer[attr->manufacturer_len] = '\0';
+ }
+ }
+
+ if (attr->model_name) {
+ os_free(sta->model_name);
+ sta->model_name = os_malloc(attr->model_name_len + 1);
+ if (sta->model_name) {
+ os_memcpy(sta->model_name, attr->model_name,
+ attr->model_name_len);
+ sta->model_name[attr->model_name_len] = '\0';
+ }
+ }
+
+ if (attr->model_number) {
+ os_free(sta->model_number);
+ sta->model_number = os_malloc(attr->model_number_len + 1);
+ if (sta->model_number) {
+ os_memcpy(sta->model_number, attr->model_number,
+ attr->model_number_len);
+ sta->model_number[attr->model_number_len] = '\0';
+ }
+ }
+
+ if (attr->serial_number) {
+ os_free(sta->serial_number);
+ sta->serial_number = os_malloc(attr->serial_number_len + 1);
+ if (sta->serial_number) {
+ os_memcpy(sta->serial_number, attr->serial_number,
+ attr->serial_number_len);
+ sta->serial_number[attr->serial_number_len] = '\0';
+ }
+ }
+
+ if (attr->dev_name) {
+ os_free(sta->dev_name);
+ sta->dev_name = os_malloc(attr->dev_name_len + 1);
+ if (sta->dev_name) {
+ os_memcpy(sta->dev_name, attr->dev_name,
+ attr->dev_name_len);
+ sta->dev_name[attr->dev_name_len] = '\0';
+ }
+ }
+
+ eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL);
+ eloop_register_timeout(300, 0, wps_er_sta_timeout, sta, NULL);
+
+ /* TODO: wpa_msg indication if new STA */
+
+ return sta;
+}
+
+
+static void wps_er_process_wlanevent_probe_req(struct wps_er_ap *ap,
+ const u8 *addr,
+ struct wpabuf *msg)
+{
+ struct wps_parse_attr attr;
+
+ wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - Probe Request - from "
+ MACSTR, MAC2STR(addr));
+ wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message "
+ "(TLVs from Probe Request)", msg);
+
+ if (wps_parse_msg(msg, &attr) < 0) {
+ wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in "
+ "WLANEvent message");
+ return;
+ }
+
+ wps_er_add_sta_data(ap, addr, &attr, 1);
+}
+
+
+static void wps_er_sta_send_msg(struct wps_er_sta *sta, struct wpabuf *msg)
+{
+ /* TODO: send msg as UPnP POST: PutWLANResponse(NewMessage,
+ * NewWLANEventType, NewWLANEventMAC) */
+
+ wpabuf_free(msg);
+}
+
+
+static void wps_er_sta_process(struct wps_er_sta *sta, struct wpabuf *msg)
+{
+ enum wps_process_res res;
+
+ res = wps_process_msg(sta->wps, WSC_MSG, msg);
+ if (res == WPS_CONTINUE) {
+ enum wsc_op_code op_code;
+ struct wpabuf *next = wps_get_msg(sta->wps, &op_code);
+ if (next)
+ wps_er_sta_send_msg(sta, next);
+ }
+}
+
+
+static void wps_er_sta_start(struct wps_er_sta *sta, struct wpabuf *msg)
+{
+ struct wps_config cfg;
+
+ if (sta->wps)
+ wps_deinit(sta->wps);
+
+ os_memset(&cfg, 0, sizeof(cfg));
+ cfg.wps = sta->ap->er->wps;
+ cfg.registrar = 1;
+ cfg.peer_addr = sta->addr;
+
+ sta->wps = wps_init(&cfg);
+ if (sta->wps == NULL)
+ return;
+
+ wps_er_sta_process(sta, msg);
+}
+
+
+static void wps_er_process_wlanevent_eap(struct wps_er_ap *ap, const u8 *addr,
+ struct wpabuf *msg)
+{
+ struct wps_parse_attr attr;
+ struct wps_er_sta *sta;
+
+ wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - EAP - from " MACSTR,
+ MAC2STR(addr));
+ wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message "
+ "(TLVs from EAP-WSC)", msg);
+
+ if (wps_parse_msg(msg, &attr) < 0) {
+ wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in "
+ "WLANEvent message");
+ return;
+ }
+
+ sta = wps_er_add_sta_data(ap, addr, &attr, 0);
+
+ if (attr.msg_type && *attr.msg_type == WPS_M1)
+ wps_er_sta_start(sta, msg);
+ else if (sta->wps)
+ wps_er_sta_process(sta, msg);
+}
+
+
+static void wps_er_process_wlanevent(struct wps_er_ap *ap,
+ struct wpabuf *event)
+{
+ u8 *data;
+ u8 wlan_event_type;
+ u8 wlan_event_mac[ETH_ALEN];
+ struct wpabuf msg;
+
+ wpa_hexdump(MSG_MSGDUMP, "WPS ER: Received WLANEvent",
+ wpabuf_head(event), wpabuf_len(event));
+ if (wpabuf_len(event) < 1 + 17) {
+ wpa_printf(MSG_DEBUG, "WPS ER: Too short WLANEvent");
+ return;
+ }
+
+ data = wpabuf_mhead(event);
+ wlan_event_type = data[0];
+ if (hwaddr_aton((char *) data + 1, wlan_event_mac) < 0) {
+ wpa_printf(MSG_DEBUG, "WPS ER: Invalid WLANEventMAC in "
+ "WLANEvent");
+ return;
+ }
+
+ wpabuf_set(&msg, data + 1 + 17, wpabuf_len(event) - (1 + 17));
+
+ switch (wlan_event_type) {
+ case 1:
+ wps_er_process_wlanevent_probe_req(ap, wlan_event_mac, &msg);
+ break;
+ case 2:
+ wps_er_process_wlanevent_eap(ap, wlan_event_mac, &msg);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "WPS ER: Unknown WLANEventType %d",
+ wlan_event_type);
+ break;
+ }
+}
+
+
+static void wps_er_http_event(struct wps_er *er, struct http_request *req,
+ unsigned int ap_id)
+{
+ struct wps_er_ap *ap = wps_er_ap_get_id(er, ap_id);
+ struct wpabuf *event;
+ enum http_reply_code ret;
+
+ if (ap == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS ER: HTTP event from unknown AP id "
+ "%u", ap_id);
+ wps_er_http_resp_not_found(req);
+ return;
+ }
+ wpa_printf(MSG_MSGDUMP, "WPS ER: HTTP event from AP id %u: %s",
+ ap_id, http_request_get_data(req));
+
+ event = xml_get_base64_item(http_request_get_data(req), "WLANEvent",
+ &ret);
+ if (event == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS ER: Could not extract WLANEvent "
+ "from the event notification");
+ /*
+ * Reply with OK anyway to avoid getting unregistered from
+ * events.
+ */
+ wps_er_http_resp_ok(req);
+ return;
+ }
+
+ wps_er_process_wlanevent(ap, event);
+
+ wpabuf_free(event);
+ wps_er_http_resp_ok(req);
+}
+
+
+static void wps_er_http_notify(struct wps_er *er, struct http_request *req)
+{
+ char *uri = http_request_get_uri(req);
+
+ if (os_strncmp(uri, "/event/", 7) == 0) {
+ wps_er_http_event(er, req, atoi(uri + 7));
+ } else {
+ wpa_printf(MSG_DEBUG, "WPS ER: Unknown HTTP NOTIFY for '%s'",
+ uri);
+ wps_er_http_resp_not_found(req);
+ }
+}
+
+
+static void wps_er_http_req(void *ctx, struct http_request *req)
+{
+ struct wps_er *er = ctx;
+ struct sockaddr_in *cli = http_request_get_cli_addr(req);
+ enum httpread_hdr_type type = http_request_get_type(req);
+ struct wpabuf *buf;
+
+ wpa_printf(MSG_DEBUG, "WPS ER: HTTP request: '%s' (type %d) from "
+ "%s:%d",
+ http_request_get_uri(req), type,
+ inet_ntoa(cli->sin_addr), ntohs(cli->sin_port));
+
+ switch (type) {
+ case HTTPREAD_HDR_TYPE_NOTIFY:
+ wps_er_http_notify(er, req);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "WPS ER: Unsupported HTTP request type "
+ "%d", type);
+ buf = wpabuf_alloc(200);
+ if (buf == NULL) {
+ http_request_deinit(req);
+ return;
+ }
+ wpabuf_put_str(buf,
+ "HTTP/1.1 501 Unimplemented\r\n"
+ "Connection: close\r\n");
+ http_put_date(buf);
+ wpabuf_put_str(buf, "\r\n");
+ http_request_send_and_deinit(req, buf);
+ break;
+ }
+}
+
+
struct wps_er *
wps_er_init(struct wps_context *wps, const char *ifname)
{
struct wps_er *er;
struct wps_registrar_config rcfg;
+ struct in_addr addr;
er = os_zalloc(sizeof(*er));
if (er == NULL)
er->ssdp_sd = -1;
os_strlcpy(er->ifname, ifname, sizeof(er->ifname));
+ er->wps = wps;
os_memset(&rcfg, 0, sizeof(rcfg));
rcfg.pin_needed_cb = wps_er_pin_needed_cb;
rcfg.cb_ctx = er;
- er->reg = wps_registrar_init(wps, &rcfg);
- if (er->reg == NULL) {
- wps_er_deinit(er);
- return NULL;
- }
-
if (get_netif_info(ifname,
&er->ip_addr, &er->ip_addr_text,
er->mac_addr, &er->mac_addr_text)) {
return NULL;
}
+ addr.s_addr = er->ip_addr;
+ er->http_srv = http_server_init(&addr, -1, wps_er_http_req, er);
+ if (er->http_srv == NULL) {
+ wps_er_deinit(er);
+ return NULL;
+ }
+ er->http_port = http_server_get_port(er->http_srv);
+
wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s "
"mac_addr=%s)",
er->ifname, er->ip_addr_text, er->mac_addr_text);
{
if (er == NULL)
return;
+ http_server_deinit(er->http_srv);
wps_er_ap_remove_all(er);
if (er->multicast_sd >= 0) {
eloop_unregister_sock(er->multicast_sd, EVENT_TYPE_READ);
eloop_unregister_sock(er->ssdp_sd, EVENT_TYPE_READ);
close(er->ssdp_sd);
}
- wps_registrar_deinit(er->reg);
os_free(er->ip_addr_text);
os_free(er->mac_addr_text);
os_free(er);