/* format_wps_device_xml -- produce content of "file" wps_device.xml
* (UPNP_WPS_DEVICE_XML_FILE)
*/
-static void format_wps_device_xml(struct upnp_wps_device_sm *sm,
+static void format_wps_device_xml(struct upnp_wps_device_interface *iface,
+ struct upnp_wps_device_sm *sm,
struct wpabuf *buf)
{
const char *s;
* Add required fields with default values if not configured. Add
* optional and recommended fields only if configured.
*/
- s = sm->wps->friendly_name;
+ s = iface->wps->friendly_name;
s = ((s && *s) ? s : "WPS Access Point");
xml_add_tagged_data(buf, "friendlyName", s);
- s = sm->wps->dev.manufacturer;
+ s = iface->wps->dev.manufacturer;
s = ((s && *s) ? s : "");
xml_add_tagged_data(buf, "manufacturer", s);
- if (sm->wps->manufacturer_url)
+ if (iface->wps->manufacturer_url)
xml_add_tagged_data(buf, "manufacturerURL",
- sm->wps->manufacturer_url);
+ iface->wps->manufacturer_url);
- if (sm->wps->model_description)
+ if (iface->wps->model_description)
xml_add_tagged_data(buf, "modelDescription",
- sm->wps->model_description);
+ iface->wps->model_description);
- s = sm->wps->dev.model_name;
+ s = iface->wps->dev.model_name;
s = ((s && *s) ? s : "");
xml_add_tagged_data(buf, "modelName", s);
- if (sm->wps->dev.model_number)
+ if (iface->wps->dev.model_number)
xml_add_tagged_data(buf, "modelNumber",
- sm->wps->dev.model_number);
+ iface->wps->dev.model_number);
- if (sm->wps->model_url)
- xml_add_tagged_data(buf, "modelURL", sm->wps->model_url);
+ if (iface->wps->model_url)
+ xml_add_tagged_data(buf, "modelURL", iface->wps->model_url);
- if (sm->wps->dev.serial_number)
+ if (iface->wps->dev.serial_number)
xml_add_tagged_data(buf, "serialNumber",
- sm->wps->dev.serial_number);
+ iface->wps->dev.serial_number);
- uuid_bin2str(sm->wps->uuid, uuid_string, sizeof(uuid_string));
+ uuid_bin2str(iface->wps->uuid, uuid_string, sizeof(uuid_string));
s = uuid_string;
/* Need "uuid:" prefix, thus we can't use xml_add_tagged_data()
* easily...
xml_data_encode(buf, s, os_strlen(s));
wpabuf_put_str(buf, "</UDN>\n");
- if (sm->wps->upc)
- xml_add_tagged_data(buf, "UPC", sm->wps->upc);
+ if (iface->wps->upc)
+ xml_add_tagged_data(buf, "UPC", iface->wps->upc);
wpabuf_put_str(buf, wps_device_xml_postfix);
}
size_t extra_len = 0;
int body_length;
char len_buf[10];
+ struct upnp_wps_device_interface *iface;
+
+ iface = dl_list_first(&sm->interfaces,
+ struct upnp_wps_device_interface, list);
+ if (iface == NULL) {
+ http_request_deinit(hreq);
+ return;
+ }
/*
* It is not required that filenames be case insensitive but it is
* allowed and cannot hurt here.
*/
- if (filename == NULL)
- filename = "(null)"; /* just in case */
if (os_strcasecmp(filename, UPNP_WPS_DEVICE_XML_FILE) == 0) {
wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP GET for device XML");
req = GET_DEVICE_XML_FILE;
extra_len = 3000;
- if (sm->wps->friendly_name)
- extra_len += os_strlen(sm->wps->friendly_name);
- if (sm->wps->manufacturer_url)
- extra_len += os_strlen(sm->wps->manufacturer_url);
- if (sm->wps->model_description)
- extra_len += os_strlen(sm->wps->model_description);
- if (sm->wps->model_url)
- extra_len += os_strlen(sm->wps->model_url);
- if (sm->wps->upc)
- extra_len += os_strlen(sm->wps->upc);
+ if (iface->wps->friendly_name)
+ extra_len += os_strlen(iface->wps->friendly_name);
+ if (iface->wps->manufacturer_url)
+ extra_len += os_strlen(iface->wps->manufacturer_url);
+ if (iface->wps->model_description)
+ extra_len += os_strlen(iface->wps->model_description);
+ if (iface->wps->model_url)
+ extra_len += os_strlen(iface->wps->model_url);
+ if (iface->wps->upc)
+ extra_len += os_strlen(iface->wps->upc);
} else if (!os_strcasecmp(filename, UPNP_WPS_SCPD_XML_FILE)) {
wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP GET for SCPD XML");
req = GET_SCPD_XML_FILE;
switch (req) {
case GET_DEVICE_XML_FILE:
- format_wps_device_xml(sm, buf);
+ format_wps_device_xml(iface, sm, buf);
break;
case GET_SCPD_XML_FILE:
wpabuf_put_str(buf, wps_scpd_xml);
{
static const char *name = "NewDeviceInfo";
struct wps_config cfg;
- struct upnp_wps_peer *peer = &sm->peer;
+ struct upnp_wps_device_interface *iface;
+ struct upnp_wps_peer *peer;
+
+ iface = dl_list_first(&sm->interfaces,
+ struct upnp_wps_device_interface, list);
wpa_printf(MSG_DEBUG, "WPS UPnP: GetDeviceInfo");
- if (sm->ctx->ap_pin == NULL)
+ if (!iface || iface->ctx->ap_pin == NULL)
return HTTP_INTERNAL_SERVER_ERROR;
+ peer = &iface->peer;
+
/*
* Request for DeviceInfo, i.e., M1 TLVs. This is a start of WPS
* registration over UPnP with the AP acting as an Enrollee. It should
wps_deinit(peer->wps);
os_memset(&cfg, 0, sizeof(cfg));
- cfg.wps = sm->wps;
- cfg.pin = (u8 *) sm->ctx->ap_pin;
- cfg.pin_len = os_strlen(sm->ctx->ap_pin);
+ cfg.wps = iface->wps;
+ cfg.pin = (u8 *) iface->ctx->ap_pin;
+ cfg.pin_len = os_strlen(iface->ctx->ap_pin);
peer->wps = wps_init(&cfg);
if (peer->wps) {
enum wsc_op_code op_code;
enum http_reply_code ret;
enum wps_process_res res;
enum wsc_op_code op_code;
+ struct upnp_wps_device_interface *iface;
+
+ iface = dl_list_first(&sm->interfaces,
+ struct upnp_wps_device_interface, list);
+ if (!iface)
+ return HTTP_INTERNAL_SERVER_ERROR;
/*
* PutMessage is used by external UPnP-based Registrar to perform WPS
msg = xml_get_base64_item(data, "NewInMessage", &ret);
if (msg == NULL)
return ret;
- res = wps_process_msg(sm->peer.wps, WSC_UPnP, msg);
+ res = wps_process_msg(iface->peer.wps, WSC_UPnP, msg);
if (res == WPS_FAILURE)
*reply = NULL;
else
- *reply = wps_get_msg(sm->peer.wps, &op_code);
+ *reply = wps_get_msg(iface->peer.wps, &op_code);
wpabuf_free(msg);
if (*reply == NULL)
return HTTP_INTERNAL_SERVER_ERROR;
int ev_type;
int type;
char *val;
+ struct upnp_wps_device_interface *iface;
+ int ok = 0;
/*
* External UPnP-based Registrar is passing us a message to be proxied
wpa_printf(MSG_DEBUG, "WPS UPnP: Message Type %d", type);
} else
type = -1;
- if (!sm->ctx->rx_req_put_wlan_response ||
- sm->ctx->rx_req_put_wlan_response(sm->priv, ev_type, macaddr, msg,
- type)) {
+ dl_list_for_each(iface, &sm->interfaces,
+ struct upnp_wps_device_interface, list) {
+ if (iface->ctx->rx_req_put_wlan_response &&
+ iface->ctx->rx_req_put_wlan_response(iface->priv, ev_type,
+ macaddr, msg, type)
+ == 0)
+ ok = 1;
+ }
+
+ if (!ok) {
wpa_printf(MSG_INFO, "WPS UPnP: Fail: sm->ctx->"
"rx_req_put_wlan_response");
wpabuf_free(msg);
struct wpabuf *msg;
enum http_reply_code ret;
struct subscription *s;
+ struct upnp_wps_device_interface *iface;
+ int err = 0;
wpa_printf(MSG_DEBUG, "WPS UPnP: SetSelectedRegistrar");
s = find_er(sm, cli);
msg = xml_get_base64_item(data, "NewMessage", &ret);
if (msg == NULL)
return ret;
- if (upnp_er_set_selected_registrar(sm->wps->registrar, s, msg)) {
- wpabuf_free(msg);
- return HTTP_INTERNAL_SERVER_ERROR;
+ dl_list_for_each(iface, &sm->interfaces,
+ struct upnp_wps_device_interface, list) {
+ if (upnp_er_set_selected_registrar(iface->wps->registrar, s,
+ msg))
+ err = 1;
}
wpabuf_free(msg);
+ if (err)
+ return HTTP_INTERNAL_SERVER_ERROR;
*replyname = NULL;
*reply = NULL;
return HTTP_OK;
return;
}
+ wpa_hexdump_ascii(MSG_DEBUG, "WPS UPnP: HTTP SUBSCRIBE",
+ (u8 *) hdr, os_strlen(hdr));
+
/* Parse/validate headers */
h = hdr;
/* First line: SUBSCRIBE /wps_event HTTP/1.1
wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP SUBSCRIBE for event");
end = os_strchr(h, '\n');
- for (; end != NULL; h = end + 1) {
+ while (end) {
/* Option line by option line */
h = end + 1;
end = os_strchr(h, '\n');
break; /* no unterminated lines allowed */
/* NT assures that it is our type of subscription;
- * not used for a renewl.
+ * not used for a renewal.
**/
match = "NT:";
match_len = os_strlen(match);
h++;
len = end - h;
os_free(callback_urls);
- callback_urls = os_malloc(len + 1);
+ callback_urls = dup_binstr(h, len);
if (callback_urls == NULL) {
ret = HTTP_INTERNAL_SERVER_ERROR;
goto error;
}
- os_memcpy(callback_urls, h, len);
- callback_urls[len] = 0;
+ if (len > 0 && callback_urls[len - 1] == '\r')
+ callback_urls[len - 1] = '\0';
continue;
}
/* SID is only for renewal */
if (got_uuid) {
/* renewal */
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Subscription renewal");
if (callback_urls) {
ret = HTTP_BAD_REQUEST;
goto error;
}
s = subscription_renew(sm, uuid);
if (s == NULL) {
+ char str[80];
+ uuid_bin2str(uuid, str, sizeof(str));
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Could not find "
+ "SID %s", str);
ret = HTTP_PRECONDITION_FAILED;
goto error;
}
} else if (callback_urls) {
+ wpa_printf(MSG_DEBUG, "WPS UPnP: New subscription");
if (!got_nt) {
ret = HTTP_PRECONDITION_FAILED;
goto error;
/* subscription id */
b = wpabuf_put(buf, 0);
uuid_bin2str(s->uuid, b, 80);
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Assigned SID %s", b);
wpabuf_put(buf, os_strlen(b));
wpabuf_put_str(buf, "\r\n");
wpabuf_printf(buf, "Timeout: Second-%d\r\n", UPNP_SUBSCRIBE_SEC);
* HTTP 500-series error code.
* 599 Too many subscriptions (not a standard HTTP error)
*/
+ wpa_printf(MSG_DEBUG, "WPS UPnP: SUBSCRIBE failed - return %d", ret);
http_put_empty(buf, ret);
http_request_send_and_deinit(req, buf);
os_free(callback_urls);
wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP UNSUBSCRIBE for event");
end = os_strchr(h, '\n');
- for (; end != NULL; h = end + 1) {
+ while (end) {
/* Option line by option line */
h = end + 1;
end = os_strchr(h, '\n');
.....
}
#endif
- /* SID is only for renewal */
match = "SID:";
match_len = os_strlen(match);
if (os_strncasecmp(h, match, match_len) == 0) {
got_uuid = 1;
continue;
}
+
+ match = "NT:";
+ match_len = os_strlen(match);
+ if (os_strncasecmp(h, match, match_len) == 0) {
+ ret = HTTP_BAD_REQUEST;
+ goto send_msg;
+ }
+
+ match = "CALLBACK:";
+ match_len = os_strlen(match);
+ if (os_strncasecmp(h, match, match_len) == 0) {
+ ret = HTTP_BAD_REQUEST;
+ goto send_msg;
+ }
}
if (got_uuid) {
+ char str[80];
+
+ uuid_bin2str(uuid, str, sizeof(str));
+
s = subscription_find(sm, uuid);
if (s) {
struct subscr_addr *sa;
sa = dl_list_first(&s->addr_list, struct subscr_addr,
list);
- wpa_printf(MSG_DEBUG, "WPS UPnP: Unsubscribing %p %s",
- s, (sa && sa->domain_and_port) ?
+ wpa_printf(MSG_DEBUG,
+ "WPS UPnP: Unsubscribing %p (SID %s) %s",
+ s, str, (sa && sa->domain_and_port) ?
sa->domain_and_port : "-null-");
dl_list_del(&s->list);
subscription_destroy(s);
+ } else {
+ wpa_printf(MSG_INFO,
+ "WPS UPnP: Could not find matching subscription to unsubscribe (SID %s)",
+ str);
+ ret = HTTP_PRECONDITION_FAILED;
+ goto send_msg;
}
} else {
wpa_printf(MSG_INFO, "WPS UPnP: Unsubscribe fails (not "