wps_upnp_web.c

来自「最新的Host AP 新添加了许多pcmcia 的驱动」· C语言 代码 · 共 1,965 行 · 第 1/4 页

C
1,965
字号
}static enum http_reply_codeweb_process_put_wlan_response(struct upnp_wps_device_sm *sm, char *data,			      struct wpabuf **reply, const char **replyname){	struct wpabuf *msg;	enum http_reply_code ret;	u8 macaddr[ETH_ALEN];	int ev_type;	int type;	char *val;	/*	 * External UPnP-based Registrar is passing us a message to be proxied	 * over to a Wi-Fi -based client of ours.	 */	wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse");	msg = web_get_item(data, "NewMessage", &ret);	if (msg == NULL)		return ret;	if (upnp_get_first_document_item(data, "NewWLANEventType", &val)) {		wpabuf_free(msg);		return UPNP_ARG_VALUE_INVALID;	}	ev_type = atol(val);	os_free(val);	val = NULL;	if (upnp_get_first_document_item(data, "NewWLANEventMAC", &val) ||	    hwaddr_aton(val, macaddr)) {		wpabuf_free(msg);		os_free(val);		return UPNP_ARG_VALUE_INVALID;	}	os_free(val);	if (ev_type == UPNP_WPS_WLANEVENT_TYPE_EAP) {		struct wps_parse_attr attr;		if (wps_parse_msg(msg, &attr) < 0 ||		    attr.msg_type == NULL)			type = -1;		else			type = *attr.msg_type;		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)) {		wpa_printf(MSG_INFO, "WPS UPnP: Fail: sm->ctx->"			   "rx_req_put_wlan_response");		wpabuf_free(msg);		return HTTP_INTERNAL_SERVER_ERROR;	}	wpabuf_free(msg);	*replyname = NULL;	*reply = NULL;	return HTTP_OK;}static enum http_reply_codeweb_process_set_selected_registrar(struct upnp_wps_device_sm *sm, char *data,				   struct wpabuf **reply,				   const char **replyname){	struct wpabuf *msg;	enum http_reply_code ret;	wpa_printf(MSG_DEBUG, "WPS UPnP: SetSelectedRegistrar");	msg = web_get_item(data, "NewMessage", &ret);	if (msg == NULL)		return ret;	if (!sm->ctx->rx_req_set_selected_registrar ||	    sm->ctx->rx_req_set_selected_registrar(sm->priv, msg)) {		wpabuf_free(msg);		return HTTP_INTERNAL_SERVER_ERROR;	}	wpabuf_free(msg);	*replyname = NULL;	*reply = NULL;	return HTTP_OK;}static enum http_reply_codeweb_process_reboot_ap(struct upnp_wps_device_sm *sm, char *data,		      struct wpabuf **reply, const char **replyname){	struct wpabuf *msg;	enum http_reply_code ret;	wpa_printf(MSG_DEBUG, "WPS UPnP: RebootAP");	msg = web_get_item(data, "NewAPSettings", &ret);	if (msg == NULL)		return ret;	if (!sm->ctx->rx_req_reboot_ap ||	    sm->ctx->rx_req_reboot_ap(sm->priv, msg)) {		wpabuf_free(msg);		return HTTP_INTERNAL_SERVER_ERROR;	}	wpabuf_free(msg);	*replyname = NULL;	*reply = NULL;	return HTTP_OK;}static enum http_reply_codeweb_process_reset_ap(struct upnp_wps_device_sm *sm, char *data,		     struct wpabuf **reply, const char **replyname){	struct wpabuf *msg;	enum http_reply_code ret;	wpa_printf(MSG_DEBUG, "WPS UPnP: ResetAP");	msg = web_get_item(data, "NewMessage", &ret);	if (msg == NULL)		return ret;	if (!sm->ctx->rx_req_reset_ap ||	    sm->ctx->rx_req_reset_ap(sm->priv, msg)) {		wpabuf_free(msg);		return HTTP_INTERNAL_SERVER_ERROR;	}	wpabuf_free(msg);	*replyname = NULL;	*reply = NULL;	return HTTP_OK;}static enum http_reply_codeweb_process_reboot_sta(struct upnp_wps_device_sm *sm, char *data,		       struct wpabuf **reply, const char **replyname){	struct wpabuf *msg;	enum http_reply_code ret;	wpa_printf(MSG_DEBUG, "WPS UPnP: RebootSTA");	msg = web_get_item(data, "NewSTASettings", &ret);	if (msg == NULL)		return ret;	if (!sm->ctx->rx_req_reboot_sta ||	    sm->ctx->rx_req_reboot_sta(sm->priv, msg)) {		wpabuf_free(msg);		return HTTP_INTERNAL_SERVER_ERROR;	}	wpabuf_free(msg);	*replyname = NULL;	*reply = NULL;	return HTTP_OK;}static enum http_reply_codeweb_process_reset_sta(struct upnp_wps_device_sm *sm, char *data,		      struct wpabuf **reply, const char **replyname){	struct wpabuf *msg;	enum http_reply_code ret;	wpa_printf(MSG_DEBUG, "WPS UPnP: ResetSTA");	msg = web_get_item(data, "NewMessage", &ret);	if (msg == NULL)		return ret;	if (!sm->ctx->rx_req_reset_sta ||	    sm->ctx->rx_req_reset_sta(sm->priv, msg)) {		wpabuf_free(msg);		return HTTP_INTERNAL_SERVER_ERROR;	}	wpabuf_free(msg);	*replyname = NULL;	*reply = NULL;	return HTTP_OK;}static const char *soap_prefix =	"<?xml version=\"1.0\"?>\n"	"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "	"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"	"<s:Body>\n";static const char *soap_postfix =	"</s:Body>\n</s:Envelope>\n";static const char *soap_error_prefix =	"<s:Fault>\n"	"<faultcode>s:Client</faultcode>\n"	"<faultstring>UPnPError</faultstring>\n"	"<detail>\n"	"<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\n";static const char *soap_error_postfix =	"<errorDescription>Error</errorDescription>\n"	"</UPnPError>\n"	"</detail>\n"	"</s:Fault>\n";static void web_connection_send_reply(struct web_connection *c,				      enum http_reply_code ret,				      const char *action, int action_len,				      const struct wpabuf *reply,				      const char *replyname){	struct wpabuf *buf;	char *replydata;	char *put_length_here = NULL;	char *body_start = NULL;	if (reply) {		size_t len;		replydata = (char *) base64_encode(wpabuf_head(reply),						   wpabuf_len(reply), &len);	} else		replydata = NULL;	/* Parameters of the response:	 *      action(action_len) -- action we are responding to	 *      replyname -- a name we need for the reply	 *      replydata -- NULL or null-terminated string	 */	buf = wpabuf_alloc(1000 + (replydata ? os_strlen(replydata) : 0U) +			   (action_len > 0 ? action_len * 2 : 0));	if (buf == NULL) {		wpa_printf(MSG_INFO, "WPS UPnP: Cannot allocate reply to "			   "POST");		wpabuf_free(buf);		os_free(replydata);		return;	}	/*	 * Assuming we will be successful, put in the output header first.	 * Note: we do not keep connections alive (and httpread does	 * not support it)... therefore we must have Connection: close.	 */	if (ret == HTTP_OK) {		wpabuf_put_str(buf,			       "HTTP/1.1 200 OK\r\n"			       "Content-Type: text/xml; "			       "charset=\"utf-8\"\r\n");	} else {		wpabuf_printf(buf, "HTTP/1.1 %d Error\r\n", ret);	}	wpabuf_put_str(buf, http_connection_close);	wpabuf_put_str(buf, "Content-Length: ");	/*	 * We will paste the length in later, leaving some extra whitespace.	 * HTTP code is supposed to be tolerant of extra whitespace.	 */	put_length_here = wpabuf_put(buf, 0);	wpabuf_put_str(buf, "        \r\n");	http_put_date(buf);	/* terminating empty line */	wpabuf_put_str(buf, "\r\n");	body_start = wpabuf_put(buf, 0);	if (ret == HTTP_OK) {		wpabuf_put_str(buf, soap_prefix);		wpabuf_put_str(buf, "<u:");		wpabuf_put_data(buf, action, action_len);		wpabuf_put_str(buf, "Response xmlns:u=\"");		wpabuf_put_str(buf, urn_wfawlanconfig);		wpabuf_put_str(buf, "\">\n");		if (replydata && replyname) {			/* TODO: might possibly need to escape part of reply			 * data? ...			 * probably not, unlikely to have ampersand(&) or left			 * angle bracket (<) in it...			 */			wpabuf_printf(buf, "<%s>", replyname);			wpabuf_put_str(buf, replydata);			wpabuf_printf(buf, "</%s>\n", replyname);		}		wpabuf_put_str(buf, "</u:");		wpabuf_put_data(buf, action, action_len);		wpabuf_put_str(buf, "Response>\n");		wpabuf_put_str(buf, soap_postfix);	} else {		/* Error case */		wpabuf_put_str(buf, soap_prefix);		wpabuf_put_str(buf, soap_error_prefix);		wpabuf_printf(buf, "<errorCode>%d</errorCode>\n", ret);		wpabuf_put_str(buf, soap_error_postfix);		wpabuf_put_str(buf, soap_postfix);	}	os_free(replydata);	/* Now patch in the content length at the end */	if (body_start && put_length_here) {		int body_length = (char *) wpabuf_put(buf, 0) - body_start;		char len_buf[10];		os_snprintf(len_buf, sizeof(len_buf), "%d", body_length);		os_memcpy(put_length_here, len_buf, os_strlen(len_buf));	}	send_wpabuf(c->sd, buf);	wpabuf_free(buf);}static const char * web_get_action(struct web_connection *c,				   const char *filename, size_t *action_len){	const char *match;	int match_len;	char *b;	char *action;	*action_len = 0;	if (os_strcasecmp(filename, UPNP_WPS_DEVICE_CONTROL_FILE)) {		wpa_printf(MSG_INFO, "WPS UPnP: Invalid POST filename %s",			   filename);		return NULL;	}	/* The SOAPAction line of the header tells us what we want to do */	b = httpread_hdr_line_get(c->hread, "SOAPAction:");	if (b == NULL)		return NULL;	if (*b == '"')		b++;	else		return NULL;	match = urn_wfawlanconfig;	match_len = os_strlen(urn_wfawlanconfig) - 1;	if (os_strncasecmp(b, match, match_len))		return NULL;	b += match_len;	/* skip over version */	while (isgraph(*b) && *b != '#')		b++;	if (*b != '#')		return NULL;	b++;	/* Following the sharp(#) should be the action and a double quote */	action = b;	while (isgraph(*b) && *b != '"')		b++;	if (*b != '"')		return NULL;	*action_len = b - action;	return action;}/* Given that we have received a header w/ POST, act upon it * * Format of POST (case-insensitive): * * First line must be: *      POST /<file> HTTP/1.1 * Since we don't do anything fancy we just ignore other lines. * * Our response (if no error) which includes only required lines is: * HTTP/1.1 200 OK * Connection: close * Content-Type: text/xml * Date: <rfc1123-date> * * Header lines must end with \r\n * Per RFC 2616, content-length: is not required but connection:close * would appear to be required (given that we will be closing it!). */static void web_connection_parse_post(struct web_connection *c,				      const char *filename){	enum http_reply_code ret;	struct upnp_wps_device_sm *sm = c->sm;	char *data = httpread_data_get(c->hread); /* body of http msg */	const char *action;	size_t action_len;	const char *replyname = NULL; /* argument name for the reply */	struct wpabuf *reply = NULL; /* data for the reply */	ret = UPNP_INVALID_ACTION;	action = web_get_action(c, filename, &action_len);	if (action == NULL)		goto bad;	/*	 * There are quite a few possible actions. Although we appear to	 * support them all here, not all of them are necessarily supported by	 * callbacks at higher levels.	 */	if (!os_strncasecmp("GetDeviceInfo", action, action_len))		ret = web_process_get_device_info(sm, &reply, &replyname);	else if (!os_strncasecmp("PutMessage", action, action_len))		ret = web_process_put_message(sm, data, &reply, &replyname);	else if (!os_strncasecmp("GetAPSettings", action, action_len))		ret = web_process_get_ap_settings(sm, data, &reply,						  &replyname);	else if (!os_strncasecmp("SetAPSettings", action, action_len))		ret = web_process_set_ap_settings(sm, data, &reply,						  &replyname);	else if (!os_strncasecmp("DelAPSettings", action, action_len))		ret = web_process_del_ap_settings(sm, data, &reply,						  &replyname);	else if (!os_strncasecmp("GetSTASettings", action, action_len))		ret = web_process_get_sta_settings(sm, data, &reply,						   &replyname);	else if (!os_strncasecmp("SetSTASettings", action, action_len))		ret = web_process_set_sta_settings(sm, data, &reply,						   &replyname);	else if (!os_strncasecmp("DelSTASettings", action, action_len))		ret = web_process_del_sta_settings(sm, data, &reply,						  &replyname);	else if (!os_strncasecmp("PutWLANResponse", action, action_len))		ret = web_process_put_wlan_response(sm, data, &reply,						    &replyname);	else if (!os_strncasecmp("SetSelectedRegistrar", action, action_len))		ret = web_process_set_selected_registrar(sm, data, &reply,							 &replyname);	else if (!os_strncasecmp("RebootAP", action, action_len))		ret = web_process_reboot_ap(sm, data, &reply, &replyname);	else if (!os_strncasecmp("ResetAP", action, action_len))		ret = web_process_reset_ap(sm, data, &reply, &replyname);	else if (!os_strncasecmp("RebootSTA", action, action_len))		ret = web_process_reboot_sta(sm, data, &reply, &replyname);	else if (!os_strncasecmp("ResetSTA", action, action_len))		ret = web_process_reset_sta(sm, data, &reply, &replyname);	else		wpa_printf(MSG_INFO, "WPS UPnP: Unknown POST type");bad:	if (ret != HTTP_OK)		wpa_printf(MSG_INFO, "WPS UPnP: POST failure ret=%d", ret);	web_connection_send_reply(c, ret, action, action_len, reply,				  replyname);	wpabuf_free(reply);}/* Given that we have received a header w/ SUBSCRIBE, act upon it * * Format of SUBSCRIBE (case-insensitive): * * First line must be: *      SUBSCRIBE /wps_event HTTP/1.1 * * Our response (if no error) which includes only required lines is: * HTTP/1.1 200 OK * Server: xx, UPnP/1.0, xx * SID: uuid:xxxxxxxxx * Timeout: Second-<n> * Content-Length: 0 * Date: xxxx * * Header lines must end with \r\n * Per RFC 2616, content-length: is not required but connection:close * would appear to be required (given that we will be closing it!). */static void web_connection_parse_subscribe(struct web_connection *c,					   const char *filename){	struct upnp_wps_device_sm *sm = c->sm;	struct wpabuf *buf;	char *b;	char *hdr = httpread_hdr_get(c->hread);	char *h;	char *match;	int match_len;	char *end;	int len;	int got_nt = 0;	u8 uuid[UUID_LEN];	int got_uuid = 0;	char *callback_urls = NULL;	struct subscription *s = NULL;	enum http_reply_code ret = HTTP_INTERNAL_SERVER_ERROR;	buf = wpabuf_alloc(1000);	if (buf == NULL)		return;	/* Parse/validate headers */	h = hdr;	/* First line: SUBSCRIBE /wps_event HTTP/1.1	 * has already been parsed.	 */	if (os_strcasecmp(filename, UPNP_WPS_DEVICE_EVENT_FILE) != 0) {		ret = HTTP_PRECONDITION_FAILED;		goto error;	}	wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP SUBSCRIBE for event");	end = os_strchr(h, '\n');	for (; end != NULL; h = end + 1) {		/* Option line by option line */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?