diff --git a/core/uwsgi.c b/core/uwsgi.c index 5678977f..c54157f4 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -3294,6 +3294,30 @@ void uwsgi_opt_add_string_list(char *opt, char *value, void *list) { uwsgi_string_new_list(ptr, value); } +void uwsgi_opt_add_addr_list(char *opt, char *value, void *list) { + struct uwsgi_string_list **ptr = (struct uwsgi_string_list **) list; + int af = AF_INET; +#ifdef UWSGI_IPV6 + void *ip = uwsgi_malloc(16); + if (strchr(value, ':')) { + af = AF_INET6; + } +#else + void *ip = uwsgi_malloc(4); +#endif + + if (inet_pton(af, value, ip) <= 0) { + uwsgi_log("%s: invalid address\n", opt); + uwsgi_error("uwsgi_opt_add_addr_list()"); + exit(1); + } + + struct uwsgi_string_list *usl = uwsgi_string_new_list(ptr, ip); + usl->custom = af; + usl->custom_ptr = value; +} + + #ifdef UWSGI_PCRE void uwsgi_opt_add_regexp_list(char *opt, char *value, void *list) { struct uwsgi_regexp_list **ptr = (struct uwsgi_regexp_list **) list; diff --git a/plugins/http/http.c b/plugins/http/http.c index 8538fceb..4e826779 100644 --- a/plugins/http/http.c +++ b/plugins/http/http.c @@ -24,6 +24,7 @@ struct uwsgi_http { #ifdef UWSGI_SSL int https_export_cert; #endif + struct uwsgi_string_list *stud_prefix; } uhttp; @@ -134,6 +135,7 @@ struct uwsgi_option http_options[] = { {"http-stats-server", required_argument, 0, "run the http router stats server", uwsgi_opt_set_str, &uhttp.cr.stats_server, 0}, {"http-ss", required_argument, 0, "run the http router stats server", uwsgi_opt_set_str, &uhttp.cr.stats_server, 0}, {"http-harakiri", required_argument, 0, "enable http router harakiri", uwsgi_opt_set_int, &uhttp.cr.harakiri, 0}, + {"http-stud-prefix", required_argument, 0, "expect a stud prefix (1byte family + 4/16 bytes address) on connections from the specified address", uwsgi_opt_add_addr_list, &uhttp.stud_prefix, 0}, {0, 0, 0, 0, 0, 0, 0}, }; @@ -175,6 +177,11 @@ struct http_session { size_t post_buf_len; off_t post_buf_pos; + // 1 (family) + 4/16 (addr) + char stud_prefix[17]; + size_t stud_prefix_remains; + size_t stud_prefix_pos; + }; @@ -1082,6 +1089,31 @@ void hr_session_close(struct corerouter_session *cs) { } } +static ssize_t hr_recv_stud4(struct corerouter_session * cs) { + struct http_session *hs = (struct http_session *) cs; + ssize_t len = read(cs->fd, hs->stud_prefix + hs->stud_prefix_pos, hs->stud_prefix_remains - hs->stud_prefix_pos); + if (len < 0) { + cr_try_again; + uwsgi_error("hr_recv_stud4()"); + return -1; + } + + hs->stud_prefix_pos += len; + + if (hs->stud_prefix_pos == hs->stud_prefix_remains) { + if (hs->stud_prefix[0] != AF_INET) { + uwsgi_log("[uwsgi-http] invalid stud prefix\n"); + return -1; + } + // set the passed ip address + memcpy(&hs->ip_addr, hs->stud_prefix + 1, 4); + uwsgi_cr_hook_read(cs, hr_recv_http); + } + + return len; + +} + #ifdef UWSGI_SSL void hr_session_ssl_close(struct corerouter_session *cs) { hr_session_close(cs); @@ -1112,6 +1144,17 @@ void http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socke cs->modifier1 = uhttp.modifier1; if (sa && sa->sa_family == AF_INET) { hs->ip_addr = ((struct sockaddr_in *) sa)->sin_addr.s_addr; + + struct uwsgi_string_list *usl = uhttp.stud_prefix; + while(usl) { + if (!memcmp(&hs->ip_addr, usl->value, 4)) { + hs->stud_prefix_remains = 5; + uwsgi_cr_hook_read(cs, hr_recv_stud4); + break; + } + usl = usl->next; + } + } hs->rnrn = 0; @@ -1133,7 +1176,9 @@ void http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socke } else { #endif - uwsgi_cr_hook_read(cs, hr_recv_http); + if (!cs->event_hook_read) { + uwsgi_cr_hook_read(cs, hr_recv_http); + } cs->close = hr_session_close; #ifdef UWSGI_SSL } diff --git a/uwsgi.h b/uwsgi.h index 4e5b79a8..e1080058 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -309,6 +309,7 @@ struct uwsgi_string_list { size_t len; uint64_t custom; uint64_t custom2; + void *custom_ptr; struct uwsgi_string_list *next; }; @@ -2996,6 +2997,7 @@ void uwsgi_opt_set_str(char *, char *, void *); void uwsgi_opt_set_logger(char *, char *, void *); void uwsgi_opt_set_str_spaced(char *, char *, void *); void uwsgi_opt_add_string_list(char *, char *, void *); +void uwsgi_opt_add_addr_list(char *, char *, void *); void uwsgi_opt_add_dyn_dict(char *, char *, void *); #ifdef UWSGI_PCRE void uwsgi_opt_pcre_jit(char *, char *, void *);