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 + -
显示快捷键?