static void wps_er_ap_unsubscribe(struct wps_er *er, struct wps_er_ap *ap) { struct wpabuf *req; struct sockaddr_in dst; char *url, *path; char sid[100]; if (ap->event_sub_url == NULL) { wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot " "subscribe"); goto fail; } if (ap->http) { wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot " "send subscribe request"); goto fail; } url = http_client_url_parse(ap->event_sub_url, &dst, &path); if (url == NULL) { wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL"); goto fail; } req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000); if (req == NULL) { os_free(url); goto fail; } uuid_bin2str(ap->sid, sid, sizeof(sid)); wpabuf_printf(req, "UNSUBSCRIBE %s HTTP/1.1\r\n" "HOST: %s:%d\r\n" "SID: uuid:%s\r\n" "\r\n", path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port), sid); os_free(url); wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Unsubscription request", wpabuf_head(req), wpabuf_len(req)); ap->http = http_client_addr(&dst, req, 1000, wps_er_http_unsubscribe_cb, ap); if (ap->http == NULL) { wpabuf_free(req); goto fail; } return; fail: /* * Need to get rid of the AP entry even when we fail to unsubscribe * cleanly. */ wps_er_ap_unsubscribed(ap->er, ap); }
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/%u/%u>\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->er->event_id, 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); }
struct http_client * http_client_url(const char *url, struct wpabuf *req, size_t max_response, void (*cb)(void *ctx, struct http_client *c, enum http_client_event event), void *cb_ctx) { struct sockaddr_in dst; struct http_client *c; char *u, *path; struct wpabuf *req_buf = NULL; if (os_strncmp(url, "http://", 7) != 0) return NULL; u = http_client_url_parse(url, &dst, &path); if (u == NULL) return NULL; if (req == NULL) { req_buf = wpabuf_alloc(os_strlen(url) + 1000); if (req_buf == NULL) { os_free(u); return NULL; } req = req_buf; wpabuf_printf(req, "GET %s HTTP/1.1\r\n" "Cache-Control: no-cache\r\n" "Pragma: no-cache\r\n" "Accept: text/xml, application/xml\r\n" "User-Agent: wpa_supplicant\r\n" "Host: %s:%d\r\n" "\r\n", path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port)); } os_free(u); c = http_client_addr(&dst, req, max_response, cb, cb_ctx); if (c == NULL) { wpabuf_free(req_buf); return NULL; } return c; }
static void wps_er_sta_send_msg(struct wps_er_sta *sta, struct wpabuf *msg) { struct wpabuf *buf; char *len_ptr, *body_ptr; struct sockaddr_in dst; char *url, *path; if (sta->http) { wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for STA - " "ignore new request"); wpabuf_free(msg); return; } if (sta->ap->control_url == NULL) { wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); wpabuf_free(msg); return; } url = http_client_url_parse(sta->ap->control_url, &dst, &path); if (url == NULL) { wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse controlURL"); wpabuf_free(msg); return; } buf = wps_er_soap_hdr(msg, "PutWLANResponse", "NewMessage", path, &dst, &len_ptr, &body_ptr); wpabuf_free(msg); os_free(url); if (buf == NULL) return; wpabuf_printf(buf, "<NewWLANEventType>%d</NewWLANEventType>\n", UPNP_WPS_WLANEVENT_TYPE_EAP); wpabuf_printf(buf, "<NewWLANEventMAC>" MACSTR "</NewWLANEventMAC>\n", MAC2STR(sta->addr)); wps_er_soap_end(buf, "PutWLANResponse", len_ptr, body_ptr); sta->http = http_client_addr(&dst, buf, 1000, wps_er_http_put_wlan_response_cb, sta); if (sta->http == NULL) wpabuf_free(buf); }
static int wps_er_send_get_device_info(struct wps_er_ap *ap, void (*m1_handler)(struct wps_er_ap *ap, struct wpabuf *m1)) { 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 get device info"); 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; } ap->m1_handler = m1_handler; return 0; }
static void wps_er_send_set_sel_reg(struct wps_er_ap *ap, struct wpabuf *msg) { struct wpabuf *buf; char *len_ptr, *body_ptr; struct sockaddr_in dst; char *url, *path; if (ap->control_url == NULL) { wpa_printf(MSG_DEBUG, "WPS ER: No controlURL for AP"); return; } if (ap->http) { wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request for AP - " "ignore new request"); return; } if (ap->wps) { wpa_printf(MSG_DEBUG, "WPS ER: Pending WPS operation for AP - " "skip SetSelectedRegistrar"); 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, "SetSelectedRegistrar", "NewMessage", path, &dst, &len_ptr, &body_ptr); os_free(url); if (buf == NULL) return; wps_er_soap_end(buf, "SetSelectedRegistrar", len_ptr, body_ptr); ap->http = http_client_addr(&dst, buf, 1000, wps_er_http_set_sel_reg_cb, ap); if (ap->http == NULL) wpabuf_free(buf); }
/* event_send_start -- prepare to send a event message to subscriber * * This gets complicated because: * -- The message is sent via TCP and we have to keep the stream open * for 30 seconds to get a response... then close it. * -- But we might have other event happen in the meantime... * we have to queue them, if we lose them then the subscriber will * be forced to unsubscribe and subscribe again. * -- If multiple URLs are provided then we are supposed to try successive * ones after 30 second timeout. * -- The URLs might use domain names instead of dotted decimal addresses, * and resolution of those may cause unwanted sleeping. * -- Doing the initial TCP connect can take a while, so we have to come * back after connection and then send the data. * * Returns nonzero on error; * * Prerequisite: No current event send (s->current_event == NULL) * and non-empty queue. */ static int event_send_start(struct subscription *s) { struct wps_event_ *e; unsigned int itry; struct wpabuf *buf; /* * Assume we are called ONLY with no current event and ONLY with * nonempty event queue and ONLY with at least one address to send to. */ if (dl_list_empty(&s->addr_list) || s->current_event || dl_list_empty(&s->event_queue)) return -1; s->current_event = e = event_dequeue(s); /* Use address according to number of retries */ itry = 0; dl_list_for_each(e->addr, &s->addr_list, struct subscr_addr, list) if (itry++ == e->retry) break; if (itry < e->retry) return -1; buf = event_build_message(e); if (buf == NULL) { event_retry(e, 0); return -1; } e->http_event = http_client_addr(&e->addr->saddr, buf, 0, event_http_cb, e); if (e->http_event == NULL) { wpabuf_free(buf); event_retry(e, 0); return -1; } return 0; }
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); }