diff options
Diffstat (limited to 'src/plugins/http_static')
-rw-r--r-- | src/plugins/http_static/builtinurl/json_urls.c | 62 | ||||
-rw-r--r-- | src/plugins/http_static/http_static.h | 5 | ||||
-rw-r--r-- | src/plugins/http_static/static_server.c | 112 |
3 files changed, 103 insertions, 76 deletions
diff --git a/src/plugins/http_static/builtinurl/json_urls.c b/src/plugins/http_static/builtinurl/json_urls.c index 808893aac79..8578be147f3 100644 --- a/src/plugins/http_static/builtinurl/json_urls.c +++ b/src/plugins/http_static/builtinurl/json_urls.c @@ -20,9 +20,27 @@ hss_url_handler_rc_t handle_get_version (hss_url_handler_args_t *args) { u8 *s = 0; + unformat_input_t input; + int verbose = 0; + + if (args->query) + { + unformat_init_vector (&input, args->query); + if (unformat (&input, "verbose=")) + { + if (unformat (&input, "true")) + verbose = 1; + } + } s = format (s, "{\"vpp_details\": {"); s = format (s, " \"version\": \"%s\",", VPP_BUILD_VER); + if (verbose) + { + s = format (s, " \"build_by\": \"%s\",", VPP_BUILD_USER); + s = format (s, " \"build_host\": \"%s\",", VPP_BUILD_HOST); + s = format (s, " \"build_dir\": \"%s\",", VPP_BUILD_TOPDIR); + } s = format (s, " \"build_date\": \"%s\"}}\r\n", VPP_BUILD_DATE); args->data = s; @@ -31,66 +49,38 @@ handle_get_version (hss_url_handler_args_t *args) return HSS_URL_HANDLER_OK; } -void -trim_path_from_request (u8 *s, char *path) -{ - u8 *cp; - int trim_length = strlen (path) + 1 /* remove '?' */; - - /* Get rid of the path and question-mark */ - vec_delete (s, trim_length, 0); - - /* Tail trim irrelevant browser info */ - cp = s; - while ((cp - s) < vec_len (s)) - { - if (*cp == ' ') - { - /* - * Makes request a vector which happens to look - * like a c-string. - */ - *cp = 0; - vec_set_len (s, cp - s); - break; - } - cp++; - } -} - hss_url_handler_rc_t handle_get_interface_stats (hss_url_handler_args_t *args) { u8 *s = 0, *stats = 0; - uword *p; - u32 *sw_if_indices = 0; + u32 sw_if_index, *sw_if_indices = 0; vnet_hw_interface_t *hi; vnet_sw_interface_t *si; char *q = "\""; int i; int need_comma = 0; + unformat_input_t input; u8 *format_vnet_sw_interface_cntrs (u8 * s, vnet_interface_main_t * im, vnet_sw_interface_t * si, int json); vnet_main_t *vnm = vnet_get_main (); vnet_interface_main_t *im = &vnm->interface_main; /* Get stats for a single interface via http POST */ - if (args->reqtype == HTTP_REQ_POST) + if (args->req_type == HTTP_REQ_POST) { - trim_path_from_request (args->request, "interface_stats.json"); - + unformat_init_vector (&input, args->req_data); /* Find the sw_if_index */ - p = hash_get (im->hw_interface_by_name, args->request); - if (!p) + if (!unformat (&input, "%U", unformat_vnet_sw_interface, vnm, + &sw_if_index)) { s = format (s, "{\"interface_stats\": {[\n"); - s = format (s, " \"name\": \"%s\",", args->request); + s = format (s, " \"name\": \"%s\",", args->req_data); s = format (s, " \"error\": \"%s\"", "UnknownInterface"); s = format (s, "]}\n"); goto out; } - vec_add1 (sw_if_indices, p[0]); + vec_add1 (sw_if_indices, sw_if_index); } else /* default, HTTP_BUILTIN_METHOD_GET */ { diff --git a/src/plugins/http_static/http_static.h b/src/plugins/http_static/http_static.h index 2850d356b74..8f336e83d58 100644 --- a/src/plugins/http_static/http_static.h +++ b/src/plugins/http_static/http_static.h @@ -79,8 +79,9 @@ typedef struct hss_url_handler_args_ /* Request args */ struct { - u8 *request; - http_req_method_t reqtype; + u8 *query; + u8 *req_data; + http_req_method_t req_type; }; /* Reply args */ diff --git a/src/plugins/http_static/static_server.c b/src/plugins/http_static/static_server.c index f433238dcb1..c4284a45999 100644 --- a/src/plugins/http_static/static_server.c +++ b/src/plugins/http_static/static_server.c @@ -212,7 +212,7 @@ content_type_from_request (u8 *request) static int try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt, - u8 *request) + u8 *target_path, u8 *target_query, u8 *data) { http_status_code_t sc = HTTP_STATUS_OK; hss_url_handler_args_t args = {}; @@ -220,22 +220,22 @@ try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt, http_content_type_t type; int rv; - if (!hsm->enable_url_handlers || !request) + if (!hsm->enable_url_handlers || !target_path) return -1; /* zero-length? try "index.html" */ - if (vec_len (request) == 0) + if (vec_len (target_path) == 0) { - request = format (request, "index.html"); + target_path = format (target_path, "index.html"); } - type = content_type_from_request (request); + type = content_type_from_request (target_path); /* Look for built-in GET / POST handlers */ url_table = (rt == HTTP_REQ_GET) ? hsm->get_url_handlers : hsm->post_url_handlers; - p = hash_get_mem (url_table, request); + p = hash_get_mem (url_table, target_path); if (!p) return -1; @@ -244,10 +244,12 @@ try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt, hs->cache_pool_index = ~0; if (hsm->debug_level > 0) - clib_warning ("%s '%s'", (rt == HTTP_REQ_GET) ? "GET" : "POST", request); + clib_warning ("%s '%s'", (rt == HTTP_REQ_GET) ? "GET" : "POST", + target_path); - args.reqtype = rt; - args.request = request; + args.req_type = rt; + args.query = target_query; + args.req_data = data; args.sh.thread_index = hs->thread_index; args.sh.session_index = hs->session_index; @@ -260,7 +262,7 @@ try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt, if (rv == HSS_URL_HANDLER_ERROR) { clib_warning ("builtin handler %llx hit on %s '%s' but failed!", p[0], - (rt == HTTP_REQ_GET) ? "GET" : "POST", request); + (rt == HTTP_REQ_GET) ? "GET" : "POST", target_path); sc = HTTP_STATUS_NOT_FOUND; } @@ -354,7 +356,7 @@ try_index_file (hss_main_t *hsm, hss_session_t *hs, u8 *path) static int try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt, - u8 *request) + u8 *target) { http_status_code_t sc = HTTP_STATUS_OK; u8 *path, *sanitized_path; @@ -365,19 +367,16 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt, if (!hsm->www_root) return -1; - type = content_type_from_request (request); + type = content_type_from_request (target); /* Remove dot segments to prevent path traversal */ - sanitized_path = http_path_remove_dot_segments (request); + sanitized_path = http_path_remove_dot_segments (target); /* * Construct the file to open - * Browsers are capable of sporadically including a leading '/' */ - if (!request) + if (!target) path = format (0, "%s%c", hsm->www_root, 0); - else if (request[0] == '/') - path = format (0, "%s%s%c", hsm->www_root, sanitized_path, 0); else path = format (0, "%s/%s%c", hsm->www_root, sanitized_path, 0); @@ -431,33 +430,33 @@ done: return 0; } -static int -handle_request (hss_session_t *hs, http_req_method_t rt, u8 *request) +static void +handle_request (hss_session_t *hs, http_req_method_t rt, u8 *target_path, + u8 *target_query, u8 *data) { hss_main_t *hsm = &hss_main; - if (!try_url_handler (hsm, hs, rt, request)) - return 0; + if (!try_url_handler (hsm, hs, rt, target_path, target_query, data)) + return; - if (!try_file_handler (hsm, hs, rt, request)) - return 0; + if (!try_file_handler (hsm, hs, rt, target_path)) + return; /* Handler did not find anything return 404 */ start_send_data (hs, HTTP_STATUS_NOT_FOUND); hss_session_disconnect_transport (hs); - - return 0; } static int hss_ts_rx_callback (session_t *ts) { hss_session_t *hs; - u8 *request = 0; + u8 *target_path = 0, *target_query = 0, *data = 0; http_msg_t msg; int rv; hs = hss_session_get (ts->thread_index, ts->opaque); + hs->data = 0; /* Read the http message header */ rv = svm_fifo_dequeue (ts->rx_fifo, sizeof (msg), (u8 *) &msg); @@ -466,26 +465,63 @@ hss_ts_rx_callback (session_t *ts) if (msg.type != HTTP_MSG_REQUEST || (msg.method_type != HTTP_REQ_GET && msg.method_type != HTTP_REQ_POST)) { - hs->data = 0; start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED); - return 0; + goto done; } - /* Read request */ - if (msg.data.len) + if (msg.data.target_form != HTTP_TARGET_ORIGIN_FORM) { - vec_validate (request, msg.data.len - 1); - rv = svm_fifo_dequeue (ts->rx_fifo, msg.data.len, request); - ASSERT (rv == msg.data.len); - /* request must be a proper C-string in addition to a vector */ - vec_add1 (request, 0); + start_send_data (hs, HTTP_STATUS_BAD_REQUEST); + goto done; } - /* Find and send data */ - handle_request (hs, msg.method_type, request); + /* Read target path */ + if (msg.data.target_path_len) + { + vec_validate (target_path, msg.data.target_path_len - 1); + rv = svm_fifo_peek (ts->rx_fifo, msg.data.target_path_offset, + msg.data.target_path_len, target_path); + ASSERT (rv == msg.data.target_path_len); + if (http_validate_abs_path_syntax (target_path, 0)) + { + start_send_data (hs, HTTP_STATUS_BAD_REQUEST); + goto done; + } + /* Target path must be a proper C-string in addition to a vector */ + vec_add1 (target_path, 0); + } - vec_free (request); + /* Read target query */ + if (msg.data.target_query_len) + { + vec_validate (target_query, msg.data.target_query_len - 1); + rv = svm_fifo_peek (ts->rx_fifo, msg.data.target_query_offset, + msg.data.target_query_len, target_query); + ASSERT (rv == msg.data.target_query_len); + if (http_validate_query_syntax (target_query, 0)) + { + start_send_data (hs, HTTP_STATUS_BAD_REQUEST); + goto done; + } + } + + /* Read body */ + if (msg.data.body_len) + { + vec_validate (data, msg.data.body_len - 1); + rv = svm_fifo_peek (ts->rx_fifo, msg.data.body_offset, msg.data.body_len, + data); + ASSERT (rv == msg.data.body_len); + } + /* Find and send data */ + handle_request (hs, msg.method_type, target_path, target_query, data); + +done: + vec_free (target_path); + vec_free (target_query); + vec_free (data); + svm_fifo_dequeue_drop (ts->rx_fifo, msg.data.len); return 0; } |