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