wps_upnp_web.c

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

C
1,965
字号
"<stateVariable sendEvents=\"no\">\n""<name>WLANResponse</name>\n""<dataType>bin.base64</dataType>\n""</stateVariable>\n""</serviceStateTable>\n""</scpd>\n";static const char *wps_device_xml_prefix =	"<?xml version=\"1.0\"?>\n"	"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">\n"	"<specVersion>\n"	"<major>1</major>\n"	"<minor>0</minor>\n"	"</specVersion>\n"	"<device>\n"	"<deviceType>urn:schemas-wifialliance-org:device:WFADevice:1"	"</deviceType>\n";static const char *wps_device_xml_postfix =	"<serviceList>\n"	"<service>\n"	"<serviceType>urn:schemas-wifialliance-org:service:WFAWLANConfig:1"	"</serviceType>\n"	"<serviceId>urn:wifialliance-org:serviceId:WFAWLANConfig1</serviceId>"	"\n"	"<SCPDURL>" UPNP_WPS_SCPD_XML_FILE "</SCPDURL>\n"	"<controlURL>" UPNP_WPS_DEVICE_CONTROL_FILE "</controlURL>\n"	"<eventSubURL>" UPNP_WPS_DEVICE_EVENT_FILE "</eventSubURL>\n"	"</service>\n"	"</serviceList>\n"	"</device>\n"	"</root>\n";/* 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,				  struct wpabuf *buf){	const char *s;	char uuid_string[80];	wpabuf_put_str(buf, wps_device_xml_prefix);	/*	 * Add required fields with default values if not configured. Add	 * optional and recommended fields only if configured.	 */	s = sm->wps->friendly_name;	s = ((s && *s) ? s : "WPS Access Point");	xml_add_tagged_data(buf, "friendlyName", s);	s = sm->wps->dev.manufacturer;	s = ((s && *s) ? s : "");	xml_add_tagged_data(buf, "manufacturer", s);	if (sm->wps->manufacturer_url)		xml_add_tagged_data(buf, "manufacturerURL",				    sm->wps->manufacturer_url);	if (sm->wps->model_description)		xml_add_tagged_data(buf, "modelDescription",				    sm->wps->model_description);	s = sm->wps->dev.model_name;	s = ((s && *s) ? s : "");	xml_add_tagged_data(buf, "modelName", s);	if (sm->wps->dev.model_number)		xml_add_tagged_data(buf, "modelNumber",				    sm->wps->dev.model_number);	if (sm->wps->model_url)		xml_add_tagged_data(buf, "modelURL", sm->wps->model_url);	if (sm->wps->dev.serial_number)		xml_add_tagged_data(buf, "serialNumber",				    sm->wps->dev.serial_number);	uuid_bin2str(sm->wps->uuid, uuid_string, sizeof(uuid_string));	s = uuid_string;	/* Need "uuid:" prefix, thus we can't use xml_add_tagged_data()	 * easily...	 */	wpabuf_put_str(buf, "<UDN>uuid:");	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);	wpabuf_put_str(buf, wps_device_xml_postfix);}void web_connection_stop(struct web_connection *c){	struct upnp_wps_device_sm *sm = c->sm;	httpread_destroy(c->hread);	c->hread = NULL;	close(c->sd);	c->sd = -1;	if (c->next == c) {		sm->web_connections = NULL;	} else {		if (sm->web_connections == c)			sm->web_connections = c->next;		c->next->prev = c->prev;		c->prev->next = c->next;	}	os_free(c);	sm->n_web_connections--;}static void http_put_reply_code(struct wpabuf *buf, enum http_reply_code code){	wpabuf_put_str(buf, "HTTP/1.1 ");	switch (code) {	case HTTP_OK:		wpabuf_put_str(buf, "200 OK\r\n");		break;	case HTTP_BAD_REQUEST:		wpabuf_put_str(buf, "400 Bad request\r\n");		break;	case HTTP_PRECONDITION_FAILED:		wpabuf_put_str(buf, "412 Precondition failed\r\n");		break;	case HTTP_UNIMPLEMENTED:		wpabuf_put_str(buf, "501 Unimplemented\r\n");		break;	case HTTP_INTERNAL_SERVER_ERROR:	default:		wpabuf_put_str(buf, "500 Internal server error\r\n");		break;	}}static void http_put_date(struct wpabuf *buf){	wpabuf_put_str(buf, "Date: ");	format_date(buf);	wpabuf_put_str(buf, "\r\n");}static void http_put_empty(struct wpabuf *buf, enum http_reply_code code){	http_put_reply_code(buf, code);	wpabuf_put_str(buf, http_server_hdr);	wpabuf_put_str(buf, http_connection_close);	wpabuf_put_str(buf, "Content-Length: 0\r\n"		       "\r\n");}/* Given that we have received a header w/ GET, act upon it * * Format of GET (case-insensitive): * * First line must be: *      GET /<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_get(struct web_connection *c, char *filename){	struct upnp_wps_device_sm *sm = c->sm;	struct wpabuf *buf; /* output buffer, allocated */	char *put_length_here;	char *body_start;	enum {		GET_DEVICE_XML_FILE,		GET_SCPD_XML_FILE	} req;	size_t extra_len = 0;	int body_length;	char len_buf[10];	/*	 * 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);	} 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;		extra_len = os_strlen(wps_scpd_xml);	} else {		/* File not found */		wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP GET file not found: %s",			   filename);		buf = wpabuf_alloc(200);		if (buf == NULL)			return;		wpabuf_put_str(buf,			       "HTTP/1.1 404 Not Found\r\n"			       "Connection: close\r\n");		http_put_date(buf);		/* terminating empty line */		wpabuf_put_str(buf, "\r\n");		goto send_buf;	}	buf = wpabuf_alloc(1000 + extra_len);	if (buf == NULL)		return;	wpabuf_put_str(buf,		       "HTTP/1.1 200 OK\r\n"		       "Content-Type: text/xml; charset=\"utf-8\"\r\n");	wpabuf_put_str(buf, "Server: Unspecified, UPnP/1.0, Unspecified\r\n");	wpabuf_put_str(buf, "Connection: close\r\n");	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);	switch (req) {	case GET_DEVICE_XML_FILE:		format_wps_device_xml(sm, buf);		break;	case GET_SCPD_XML_FILE:		wpabuf_put_str(buf, wps_scpd_xml);		break;	}	/* Now patch in the content length at the end */	body_length = (char *) wpabuf_put(buf, 0) - body_start;	os_snprintf(len_buf, 10, "%d", body_length);	os_memcpy(put_length_here, len_buf, os_strlen(len_buf));send_buf:	send_wpabuf(c->sd, buf);	wpabuf_free(buf);}static struct wpabuf * web_get_item(char *data, const char *name,				    enum http_reply_code *ret){	char *msg;	struct wpabuf *buf;	unsigned char *decoded;	size_t len;	if (upnp_get_first_document_item(data, name, &msg)) {		*ret = UPNP_ARG_VALUE_INVALID;		return NULL;	}	decoded = base64_decode((unsigned char *) msg, os_strlen(msg), &len);	os_free(msg);	if (decoded == NULL) {		*ret = UPNP_OUT_OF_MEMORY;		return NULL;	}	buf = wpabuf_alloc_ext_data(decoded, len);	if (buf == NULL) {		os_free(decoded);		*ret = UPNP_OUT_OF_MEMORY;		return NULL;	}	return buf;}static enum http_reply_codeweb_process_get_device_info(struct upnp_wps_device_sm *sm,			    struct wpabuf **reply, const char **replyname){	static const char *name = "NewDeviceInfo";	wpa_printf(MSG_DEBUG, "WPS UPnP: GetDeviceInfo");	if (sm->ctx->rx_req_get_device_info == NULL)		return HTTP_INTERNAL_SERVER_ERROR;	*reply = sm->ctx->rx_req_get_device_info(sm->priv, &sm->peer);	if (*reply == NULL) {		wpa_printf(MSG_INFO, "WPS UPnP: Failed to get DeviceInfo");		return HTTP_INTERNAL_SERVER_ERROR;	}	*replyname = name;	return HTTP_OK;}static enum http_reply_codeweb_process_put_message(struct upnp_wps_device_sm *sm, char *data,			struct wpabuf **reply, const char **replyname){	struct wpabuf *msg;	static const char *name = "NewOutMessage";	enum http_reply_code ret;	/*	 * PutMessage is used by external UPnP-based Registrar to perform WPS	 * operation with the access point itself; as compared with	 * PutWLANResponse which is for proxying.	 */	wpa_printf(MSG_DEBUG, "WPS UPnP: PutMessage");	if (sm->ctx->rx_req_put_message == NULL)		return HTTP_INTERNAL_SERVER_ERROR;	msg = web_get_item(data, "NewInMessage", &ret);	if (msg == NULL)		return ret;	*reply = sm->ctx->rx_req_put_message(sm->priv, &sm->peer, msg);	wpabuf_free(msg);	if (*reply == NULL)		return HTTP_INTERNAL_SERVER_ERROR;	*replyname = name;	return HTTP_OK;}static enum http_reply_codeweb_process_get_ap_settings(struct upnp_wps_device_sm *sm, char *data,			    struct wpabuf **reply, const char **replyname){	struct wpabuf *msg;	static const char *name = "NewAPSettings";	enum http_reply_code ret;	wpa_printf(MSG_DEBUG, "WPS UPnP: GetAPSettings");	if (sm->ctx->rx_req_get_ap_settings == NULL)		return HTTP_INTERNAL_SERVER_ERROR;	msg = web_get_item(data, "NewMessage", &ret);	if (msg == NULL)		return ret;	*reply = sm->ctx->rx_req_get_ap_settings(sm->priv, msg);	wpabuf_free(msg);	if (*reply == NULL)		return HTTP_INTERNAL_SERVER_ERROR;	*replyname = name;	return HTTP_OK;}static enum http_reply_codeweb_process_set_ap_settings(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: SetAPSettings");	msg = web_get_item(data, "NewAPSettings", &ret);	if (msg == NULL)		return ret;	if (!sm->ctx->rx_req_set_ap_settings ||	    sm->ctx->rx_req_set_ap_settings(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_del_ap_settings(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: DelAPSettings");	msg = web_get_item(data, "NewAPSettings", &ret);	if (msg == NULL)		return ret;	if (!sm->ctx->rx_req_del_ap_settings ||	    sm->ctx->rx_req_del_ap_settings(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_get_sta_settings(struct upnp_wps_device_sm *sm, char *data,			     struct wpabuf **reply, const char **replyname){	struct wpabuf *msg;	static const char *name = "NewSTASettings";	enum http_reply_code ret;	wpa_printf(MSG_DEBUG, "WPS UPnP: GetSTASettings");	if (sm->ctx->rx_req_get_sta_settings == NULL)		return HTTP_INTERNAL_SERVER_ERROR;	msg = web_get_item(data, "NewMessage", &ret);	if (msg == NULL)		return ret;	*reply = sm->ctx->rx_req_get_sta_settings(sm->priv, msg);	wpabuf_free(msg);	if (*reply == NULL)		return HTTP_INTERNAL_SERVER_ERROR;	*replyname = name;	return HTTP_OK;}static enum http_reply_codeweb_process_set_sta_settings(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: SetSTASettings");	msg = web_get_item(data, "NewSTASettings", &ret);	if (msg == NULL)		return ret;	if (!sm->ctx->rx_req_set_sta_settings ||	    sm->ctx->rx_req_set_sta_settings(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_del_sta_settings(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: DelSTASettings");	msg = web_get_item(data, "NewSTASettings", &ret);	if (msg == NULL)		return ret;	if (!sm->ctx->rx_req_del_sta_settings ||	    sm->ctx->rx_req_del_sta_settings(sm->priv, msg)) {		wpabuf_free(msg);		return HTTP_INTERNAL_SERVER_ERROR;	}	wpabuf_free(msg);	*replyname = NULL;	*reply = NULL;	return HTTP_OK;

⌨️ 快捷键说明

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