kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

http.c (59377B)



      1 /*
      2  * Copyright (c) 2013-2022 Joris Vink <joris@coders.se>
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #include <sys/param.h>
     18 #include <sys/types.h>
     19 
     20 #include <sys/socket.h>
     21 #include <netinet/in.h>
     22 
     23 #include <ctype.h>
     24 #include <fcntl.h>
     25 #include <inttypes.h>
     26 #include <float.h>
     27 #include <time.h>
     28 #include <stdio.h>
     29 #include <string.h>
     30 
     31 #include "kore.h"
     32 #include "http.h"
     33 
     34 #if defined(KORE_USE_PYTHON)
     35 #include "python_api.h"
     36 #endif
     37 
     38 #if defined(KORE_USE_PGSQL)
     39 #include "pgsql.h"
     40 #endif
     41 
     42 #if defined(KORE_USE_TASKS)
     43 #include "tasks.h"
     44 #endif
     45 
     46 #if defined(KORE_USE_CURL)
     47 #include "curl.h"
     48 #endif
     49 
     50 static struct {
     51 	const char	*ext;
     52 	const char	*type;
     53 } builtin_media[] = {
     54 	{ "gif",	"image/gif" },
     55 	{ "png",	"image/png" },
     56 	{ "jpeg",	"image/jpeg" },
     57 	{ "jpg",	"image/jpeg" },
     58 	{ "zip",	"application/zip" },
     59 	{ "pdf",	"application/pdf" },
     60 	{ "json",	"application/json" },
     61 	{ "js",		"application/javascript" },
     62 	{ "htm",	"text/html" },
     63 	{ "txt",	"text/plain" },
     64 	{ "css",	"text/css" },
     65 	{ "html",	"text/html" },
     66 	{ NULL,		NULL },
     67 };
     68 
     69 #define HTTP_MAP_LIMIT		127
     70 
     71 /*
     72  * token      = 1*<any CHAR except CTLs or separators>
     73  * separators = "(" | ")" | "<" | ">" | "@"
     74  *            | "," | ";" | ":" | "\" | <">
     75  *            | "/" | "[" | "]" | "?" | "="
     76  *            | "{" | "}" | SP | HT
     77  */
     78 static const char http_token[] = {
     79 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     80 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     81 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     82 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     83 	0x00, '!' , 0x00, '#' , '$' , '%' , '&' , '\'',
     84 	0x00, 0x00, '*' , '+' , 0x00, '-' , '.' , 0x00,
     85 	'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' ,
     86 	'8' , '9' , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     87 	0x00, 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' ,
     88 	'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' ,
     89 	'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' ,
     90 	'X' , 'Y' , 'Z' , 0x00, 0x00, 0x00, '^' , '_' ,
     91 	'`' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' ,
     92 	'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' ,
     93 	'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' ,
     94 	'x' , 'y' , 'z' , 0x00, '|' , 0x00, '~' , 0x00
     95 };
     96 
     97 /*
     98  * field-content  = <the OCTETs making up the field-value
     99  *                   and consisting of either *TEXT or combinations
    100  *                   of token, separators, and quoted-string>
    101  */
    102 static const char http_field_content[] = {
    103 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    104 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    105 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    106 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    107 	' ' , '!' , '"' , '#' , '$' , '%' , '&' , '\'',
    108 	'(' , ')' , '*' , '+' , ',' , '-' , '.' , '/' ,
    109 	'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' ,
    110 	'8' , '9' , ':' , ';' , '<' , '=' , '>' , '?' ,
    111 	'@' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' ,
    112 	'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' ,
    113 	'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' ,
    114 	'X' , 'Y' , 'Z' , '[' , '\\', ']' , '^' , '_' ,
    115 	'`' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' ,
    116 	'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' ,
    117 	'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' ,
    118 	'x' , 'y' , 'z' , '{' , '|' , '}' , '~' , 0x00
    119 };
    120 
    121 /*
    122  * Fixed "pretty" HTTP error HTML page.
    123  */
    124 static const char *pretty_error_fmt =
    125 	"<html>\n<head>\n\t<title>%d %s</title>"
    126 	"</head>\n<body>\n\t"
    127 	"<h1>%d %s</h1>\n"
    128 	"</body>\n</html>\n";
    129 
    130 static int	http_body_recv(struct netbuf *);
    131 static int	http_release_buffer(struct netbuf *);
    132 static void	http_error_response(struct connection *, int);
    133 static int	http_data_convert(void *, void **, void *, int);
    134 static void	http_write_response_cookie(struct http_cookie *);
    135 static int	http_body_update(struct http_request *, const void *, size_t);
    136 static void	http_argument_add(struct http_request *, char *, char *,
    137 		    int, int);
    138 static int	http_check_redirect(struct http_request *,
    139 		    struct kore_domain *);
    140 static void	http_response_normal(struct http_request *,
    141 		    struct connection *, int, const void *, size_t);
    142 static void	multipart_add_field(struct http_request *, struct kore_buf *,
    143 		    char *, const char *, const int);
    144 static void	multipart_file_add(struct http_request *, struct kore_buf *,
    145 		    const char *, const char *, const char *, const int);
    146 static int	multipart_find_data(struct kore_buf *, struct kore_buf *,
    147 		    size_t *, struct http_request *, const void *, size_t);
    148 static int	multipart_parse_headers(struct http_request *,
    149 		    struct kore_buf *, struct kore_buf *,
    150 		    const char *, const int);
    151 
    152 static struct http_request	*http_request_new(struct connection *,
    153 				    const char *, const char *, char *,
    154 				    const char *);
    155 
    156 static struct kore_buf			*header_buf;
    157 static struct kore_buf			*ckhdr_buf;
    158 static char				http_version[64];
    159 static u_int16_t			http_version_len;
    160 static TAILQ_HEAD(, http_request)	http_requests;
    161 static TAILQ_HEAD(, http_request)	http_requests_sleeping;
    162 static LIST_HEAD(, http_media_type)	http_media_types;
    163 static struct kore_pool			http_request_pool;
    164 static struct kore_pool			http_cookie_pool;
    165 static struct kore_pool			http_body_path;
    166 static struct kore_pool			http_rlq_pool;
    167 
    168 struct kore_pool			http_header_pool;
    169 
    170 int		http_pretty_error = 0;
    171 u_int32_t	http_request_count = 0;
    172 u_int32_t	http_request_ms = HTTP_REQUEST_MS;
    173 u_int16_t	http_body_timeout = HTTP_BODY_TIMEOUT;
    174 u_int32_t	http_request_limit = HTTP_REQUEST_LIMIT;
    175 u_int64_t	http_hsts_enable = HTTP_HSTS_ENABLE;
    176 u_int16_t	http_header_max = HTTP_HEADER_MAX_LEN;
    177 u_int16_t	http_keepalive_time = HTTP_KEEPALIVE_TIME;
    178 u_int16_t	http_header_timeout = HTTP_HEADER_TIMEOUT;
    179 
    180 size_t		http_body_max = HTTP_BODY_MAX_LEN;
    181 char		*http_body_disk_path = HTTP_BODY_DISK_PATH;
    182 u_int64_t	http_body_disk_offload = HTTP_BODY_DISK_OFFLOAD;
    183 
    184 void
    185 http_parent_init(void)
    186 {
    187 	LIST_INIT(&http_media_types);
    188 }
    189 
    190 void
    191 http_init(void)
    192 {
    193 	int		prealloc, l, i;
    194 
    195 	TAILQ_INIT(&http_requests);
    196 	TAILQ_INIT(&http_requests_sleeping);
    197 
    198 	header_buf = kore_buf_alloc(HTTP_HEADER_BUFSIZE);
    199 	ckhdr_buf = kore_buf_alloc(HTTP_COOKIE_BUFSIZE);
    200 
    201 	if (!http_version_len) {
    202 		l = snprintf(http_version, sizeof(http_version),
    203 		    "server: kore (%s)\r\n", kore_version);
    204 		if (l == -1 || (size_t)l >= sizeof(http_version))
    205 			fatal("http_init(): http_version buffer too small");
    206 
    207 		http_version_len = l;
    208 	}
    209 
    210 	prealloc = MIN((worker_max_connections / 10), 1000);
    211 	kore_pool_init(&http_request_pool, "http_request_pool",
    212 	    sizeof(struct http_request), http_request_limit);
    213 	kore_pool_init(&http_header_pool, "http_header_pool",
    214 	    sizeof(struct http_header), prealloc * HTTP_REQ_HEADER_MAX);
    215 	kore_pool_init(&http_cookie_pool, "http_cookie_pool",
    216 		sizeof(struct http_cookie), prealloc * HTTP_MAX_COOKIES);
    217 	kore_pool_init(&http_rlq_pool, "http_rlq_pool",
    218 		sizeof(struct http_runlock_queue), http_request_limit);
    219 
    220 	kore_pool_init(&http_body_path,
    221 	    "http_body_path", HTTP_BODY_PATH_MAX, prealloc);
    222 
    223 	for (i = 0; builtin_media[i].ext != NULL; i++) {
    224 		if (!http_media_register(builtin_media[i].ext,
    225 		    builtin_media[i].type)) {
    226 			fatal("duplicate media type for %s",
    227 			    builtin_media[i].ext);
    228 		}
    229 	}
    230 }
    231 
    232 void
    233 http_cleanup(void)
    234 {
    235 	if (header_buf != NULL) {
    236 		kore_buf_free(header_buf);
    237 		header_buf = NULL;
    238 	}
    239 
    240 	if (ckhdr_buf != NULL) {
    241 		kore_buf_free(ckhdr_buf);
    242 		ckhdr_buf = NULL;
    243 	}
    244 
    245 	kore_pool_cleanup(&http_request_pool);
    246 	kore_pool_cleanup(&http_header_pool);
    247 	kore_pool_cleanup(&http_body_path);
    248 }
    249 
    250 void
    251 http_server_version(const char *version)
    252 {
    253 	int		l;
    254 
    255 	l = snprintf(http_version, sizeof(http_version),
    256 	    "server: %s\r\n", version);
    257 	if (l == -1 || (size_t)l >= sizeof(http_version))
    258 		fatal("http_server_version(): http_version buffer too small");
    259 
    260 	http_version_len = l;
    261 }
    262 
    263 int
    264 http_check_timeout(struct connection *c, u_int64_t now)
    265 {
    266 	u_int64_t	d;
    267 
    268 	if (c->http_timeout == 0)
    269 		return (KORE_RESULT_OK);
    270 
    271 	if (now > c->http_start)
    272 		d = now - c->http_start;
    273 	else
    274 		d = 0;
    275 
    276 	if (d >= c->http_timeout) {
    277 		http_error_response(c, HTTP_STATUS_REQUEST_TIMEOUT);
    278 		kore_connection_disconnect(c);
    279 		return (KORE_RESULT_ERROR);
    280 	}
    281 
    282 	return (KORE_RESULT_OK);
    283 }
    284 
    285 void
    286 http_request_sleep(struct http_request *req)
    287 {
    288 	if (!(req->flags & HTTP_REQUEST_SLEEPING)) {
    289 		req->flags |= HTTP_REQUEST_SLEEPING;
    290 		TAILQ_REMOVE(&http_requests, req, list);
    291 		TAILQ_INSERT_TAIL(&http_requests_sleeping, req, list);
    292 	}
    293 }
    294 
    295 void
    296 http_request_wakeup(struct http_request *req)
    297 {
    298 	if (req->flags & HTTP_REQUEST_SLEEPING) {
    299 		req->flags &= ~HTTP_REQUEST_SLEEPING;
    300 		TAILQ_REMOVE(&http_requests_sleeping, req, list);
    301 		TAILQ_INSERT_TAIL(&http_requests, req, list);
    302 	}
    303 }
    304 
    305 void
    306 http_process(void)
    307 {
    308 	u_int64_t			total;
    309 	struct http_request		*req, *next;
    310 
    311 	total = 0;
    312 
    313 	for (req = TAILQ_FIRST(&http_requests); req != NULL; req = next) {
    314 		if (total >= http_request_ms)
    315 			break;
    316 
    317 		next = TAILQ_NEXT(req, list);
    318 		if (req->flags & HTTP_REQUEST_DELETE) {
    319 			http_request_free(req);
    320 			continue;
    321 		}
    322 
    323 		/* Sleeping requests should be in http_requests_sleeping. */
    324 		if (req->flags & HTTP_REQUEST_SLEEPING)
    325 			fatal("http_process: sleeping request on list");
    326 
    327 		if (!(req->flags & HTTP_REQUEST_COMPLETE))
    328 			continue;
    329 
    330 		http_process_request(req);
    331 		total += req->ms;
    332 
    333 		if (req->flags & HTTP_REQUEST_DELETE)
    334 			http_request_free(req);
    335 	}
    336 }
    337 
    338 void
    339 http_process_request(struct http_request *req)
    340 {
    341 	int		r;
    342 
    343 	if (req->flags & HTTP_REQUEST_DELETE || req->rt == NULL)
    344 		return;
    345 
    346 	req->start = kore_time_ms();
    347 	if (req->rt->auth != NULL && !(req->flags & HTTP_REQUEST_AUTHED))
    348 		r = kore_auth_run(req, req->rt->auth);
    349 	else
    350 		r = KORE_RESULT_OK;
    351 
    352 	switch (r) {
    353 	case KORE_RESULT_OK:
    354 		r = kore_runtime_http_request(req->rt->rcall, req);
    355 		break;
    356 	case KORE_RESULT_RETRY:
    357 		break;
    358 	case KORE_RESULT_ERROR:
    359 		/*
    360 		 * Set r to KORE_RESULT_OK so we can properly
    361 		 * flush the result from kore_auth_run().
    362 		 */
    363 		r = KORE_RESULT_OK;
    364 		break;
    365 	default:
    366 		fatal("kore_auth() returned unknown %d", r);
    367 	}
    368 	req->end = kore_time_ms();
    369 	req->ms = req->end - req->start;
    370 	req->total += req->ms;
    371 
    372 	switch (r) {
    373 	case KORE_RESULT_OK:
    374 		r = net_send_flush(req->owner);
    375 		if (r == KORE_RESULT_ERROR)
    376 			kore_connection_disconnect(req->owner);
    377 		break;
    378 	case KORE_RESULT_ERROR:
    379 		kore_connection_disconnect(req->owner);
    380 		break;
    381 	case KORE_RESULT_RETRY:
    382 		return;
    383 	default:
    384 		fatal("A page handler returned an unknown result: %d", r);
    385 	}
    386 
    387 	if (req->rt->dom->accesslog)
    388 		kore_accesslog(req);
    389 
    390 	req->flags |= HTTP_REQUEST_DELETE;
    391 }
    392 
    393 void
    394 http_response_header(struct http_request *req,
    395     const char *header, const char *value)
    396 {
    397 	struct http_header	*hdr;
    398 
    399 	hdr = NULL;
    400 
    401 	TAILQ_FOREACH(hdr, &req->resp_headers, list) {
    402 		if (!strcasecmp(hdr->header, header)) {
    403 			TAILQ_REMOVE(&req->resp_headers, hdr, list);
    404 			kore_free(hdr->header);
    405 			kore_free(hdr->value);
    406 			break;
    407 		}
    408 	}
    409 
    410 	if (hdr == NULL)
    411 		hdr = kore_pool_get(&http_header_pool);
    412 
    413 	hdr->header = kore_strdup(header);
    414 	hdr->value = kore_strdup(value);
    415 
    416 	TAILQ_INSERT_TAIL(&(req->resp_headers), hdr, list);
    417 }
    418 
    419 void
    420 http_request_free(struct http_request *req)
    421 {
    422 #if defined(KORE_USE_TASKS)
    423 	struct kore_task	*t, *nt;
    424 	int			pending_tasks;
    425 #endif
    426 #if defined(KORE_USE_PGSQL)
    427 	struct kore_pgsql	*pgsql;
    428 #endif
    429 #if defined(KORE_USE_CURL)
    430 	struct kore_curl	*client;
    431 #endif
    432 	struct http_file	*f, *fnext;
    433 	struct http_arg		*q, *qnext;
    434 	struct http_header	*hdr, *next;
    435 	struct http_cookie	*ck, *cknext;
    436 
    437 	if (req->rt != NULL && req->rt->on_free != NULL)
    438 		kore_runtime_http_request_free(req->rt->on_free, req);
    439 
    440 	if (req->runlock != NULL) {
    441 		LIST_REMOVE(req->runlock, list);
    442 		req->runlock = NULL;
    443 	}
    444 
    445 #if defined(KORE_USE_TASKS)
    446 	pending_tasks = 0;
    447 	for (t = LIST_FIRST(&(req->tasks)); t != NULL; t = nt) {
    448 		nt = LIST_NEXT(t, rlist);
    449 		if (!kore_task_finished(t)) {
    450 			pending_tasks++;
    451 		} else {
    452 			kore_task_destroy(t);
    453 		}
    454 	}
    455 
    456 	if (pending_tasks)
    457 		return;
    458 #endif
    459 
    460 #if defined(KORE_USE_PYTHON)
    461 	if (req->py_coro != NULL) {
    462 		kore_python_coro_delete(req->py_coro);
    463 		req->py_coro = NULL;
    464 	}
    465 	if (req->py_validator != NULL) {
    466 		kore_python_coro_delete(req->py_validator);
    467 		req->py_validator = NULL;
    468 	}
    469 	Py_XDECREF(req->py_req);
    470 #endif
    471 #if defined(KORE_USE_PGSQL)
    472 	while (!LIST_EMPTY(&(req->pgsqls))) {
    473 		pgsql = LIST_FIRST(&(req->pgsqls));
    474 		kore_pgsql_cleanup(pgsql);
    475 	}
    476 #endif
    477 #if defined(KORE_USE_CURL)
    478 	while (!LIST_EMPTY(&req->chandles)) {
    479 		client = LIST_FIRST(&req->chandles);
    480 		kore_curl_cleanup(client);
    481 	}
    482 #endif
    483 	kore_free(req->headers);
    484 
    485 	req->host = NULL;
    486 	req->path = NULL;
    487 	req->headers = NULL;
    488 
    489 	TAILQ_REMOVE(&http_requests, req, list);
    490 	if (req->owner != NULL)
    491 		TAILQ_REMOVE(&(req->owner->http_requests), req, olist);
    492 
    493 	for (hdr = TAILQ_FIRST(&(req->resp_headers)); hdr != NULL; hdr = next) {
    494 		next = TAILQ_NEXT(hdr, list);
    495 		TAILQ_REMOVE(&(req->resp_headers), hdr, list);
    496 		kore_free(hdr->header);
    497 		kore_free(hdr->value);
    498 		kore_pool_put(&http_header_pool, hdr);
    499 	}
    500 
    501 	for (hdr = TAILQ_FIRST(&(req->req_headers)); hdr != NULL; hdr = next) {
    502 		next = TAILQ_NEXT(hdr, list);
    503 		TAILQ_REMOVE(&(req->req_headers), hdr, list);
    504 		kore_pool_put(&http_header_pool, hdr);
    505 	}
    506 
    507 	for (ck = TAILQ_FIRST(&(req->resp_cookies)); ck != NULL; ck = cknext) {
    508 		cknext = TAILQ_NEXT(ck, list);
    509 		TAILQ_REMOVE(&(req->resp_cookies), ck, list);
    510 		kore_free(ck->name);
    511 		kore_free(ck->value);
    512 		kore_free(ck->path);
    513 		kore_free(ck->domain);
    514 		kore_pool_put(&http_cookie_pool, ck);
    515 	}
    516 
    517 	for (ck = TAILQ_FIRST(&(req->req_cookies)); ck != NULL; ck = cknext) {
    518 		cknext = TAILQ_NEXT(ck, list);
    519 		TAILQ_REMOVE(&(req->req_cookies), ck, list);
    520 		kore_free(ck->name);
    521 		kore_free(ck->value);
    522 		kore_pool_put(&http_cookie_pool, ck);
    523 	}
    524 
    525 	for (q = TAILQ_FIRST(&(req->arguments)); q != NULL; q = qnext) {
    526 		qnext = TAILQ_NEXT(q, list);
    527 		TAILQ_REMOVE(&(req->arguments), q, list);
    528 		kore_free(q->name);
    529 		kore_free(q->s_value);
    530 		kore_free(q);
    531 	}
    532 
    533 	for (f = TAILQ_FIRST(&(req->files)); f != NULL; f = fnext) {
    534 		fnext = TAILQ_NEXT(f, list);
    535 		TAILQ_REMOVE(&(req->files), f, list);
    536 		kore_free(f->filename);
    537 		kore_free(f->name);
    538 		kore_free(f);
    539 	}
    540 
    541 	if (req->http_body != NULL)
    542 		kore_buf_free(req->http_body);
    543 
    544 	if (req->http_body_fd != -1)
    545 		(void)close(req->http_body_fd);
    546 
    547 	if (req->http_body_path != NULL) {
    548 		if (unlink(req->http_body_path) == -1 && errno != ENOENT) {
    549 			kore_log(LOG_NOTICE, "failed to unlink %s: %s",
    550 			    req->http_body_path, errno_s);
    551 		}
    552 		kore_pool_put(&http_body_path, req->http_body_path);
    553 	}
    554 
    555 	if (req->hdlr_extra != NULL &&
    556 	    !(req->flags & HTTP_REQUEST_RETAIN_EXTRA))
    557 		kore_free(req->hdlr_extra);
    558 
    559 	kore_pool_put(&http_request_pool, req);
    560 	http_request_count--;
    561 }
    562 
    563 void
    564 http_serveable(struct http_request *req, const void *data, size_t len,
    565     const char *etag, const char *type)
    566 {
    567 	const char		*match;
    568 
    569 	if (req->method != HTTP_METHOD_GET) {
    570 		http_response_header(req, "allow", "get");
    571 		http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0);
    572 		return;
    573 	}
    574 
    575 	if (http_request_header(req, "if-none-match", &match)) {
    576 		if (!strcmp(match, etag)) {
    577 			http_response(req, HTTP_STATUS_NOT_MODIFIED, NULL, 0);
    578 			return;
    579 		}
    580 	}
    581 
    582 	http_response_header(req, "etag", etag);
    583 	http_response_header(req, "content-type", type);
    584 	http_response(req, HTTP_STATUS_OK, data, len);
    585 }
    586 
    587 void
    588 http_response(struct http_request *req, int code, const void *d, size_t l)
    589 {
    590 	if (req->owner == NULL)
    591 		return;
    592 
    593 	req->status = code;
    594 
    595 	switch (req->owner->proto) {
    596 	case CONN_PROTO_HTTP:
    597 	case CONN_PROTO_WEBSOCKET:
    598 		http_response_normal(req, req->owner, code, d, l);
    599 		break;
    600 	default:
    601 		fatal("%s: bad proto %d", __func__, req->owner->proto);
    602 		/* NOTREACHED. */
    603 	}
    604 }
    605 
    606 void
    607 http_response_close(struct http_request *req, int code, const void *d, size_t l)
    608 {
    609 	if (req->owner == NULL)
    610 		return;
    611 
    612 	req->status = code;
    613 	req->owner->flags |= CONN_CLOSE_EMPTY;
    614 
    615 	switch (req->owner->proto) {
    616 	case CONN_PROTO_HTTP:
    617 	case CONN_PROTO_WEBSOCKET:
    618 		http_response_normal(req, req->owner, code, d, l);
    619 		break;
    620 	default:
    621 		fatal("%s: bad proto %d", __func__, req->owner->proto);
    622 		/* NOTREACHED. */
    623 	}
    624 }
    625 
    626 void
    627 http_response_json(struct http_request *req, int status,
    628     struct kore_json_item *json)
    629 {
    630 	struct kore_buf		*buf;
    631 
    632 	if (req->owner == NULL)
    633 		return;
    634 
    635 	buf = kore_buf_alloc(1024);
    636 	kore_json_item_tobuf(json, buf);
    637 	kore_json_item_free(json);
    638 
    639 	req->status = status;
    640 	http_response_header(req, "content-type", "application/json");
    641 
    642 	switch (req->owner->proto) {
    643 	case CONN_PROTO_HTTP:
    644 		http_response_stream(req, status, buf->data, buf->offset,
    645 		    http_release_buffer, buf);
    646 		break;
    647 	default:
    648 		fatal("%s: bad proto %d", __func__, req->owner->proto);
    649 		/* NOTREACHED. */
    650 	}
    651 }
    652 
    653 void
    654 http_response_stream(struct http_request *req, int status, void *base,
    655     size_t len, int (*cb)(struct netbuf *), void *arg)
    656 {
    657 	struct netbuf		*nb;
    658 
    659 	if (req->owner == NULL)
    660 		return;
    661 
    662 	req->status = status;
    663 
    664 	switch (req->owner->proto) {
    665 	case CONN_PROTO_HTTP:
    666 		http_response_normal(req, req->owner, status, NULL, len);
    667 		break;
    668 	default:
    669 		fatal("%s: bad proto %d", __func__, req->owner->proto);
    670 		/* NOTREACHED. */
    671 	}
    672 
    673 	net_send_stream(req->owner, base, len, cb, &nb);
    674 	nb->extra = arg;
    675 
    676 	if (req->method == HTTP_METHOD_HEAD) {
    677 		nb->s_off = nb->b_len;
    678 		net_remove_netbuf(req->owner, nb);
    679 	}
    680 }
    681 
    682 void
    683 http_response_fileref(struct http_request *req, int status,
    684     struct kore_fileref *ref)
    685 {
    686 	struct tm	*tm;
    687 	time_t		mtime;
    688 	char		tbuf[128];
    689 	const char	*media_type, *modified;
    690 
    691 	if (req->owner == NULL)
    692 		return;
    693 
    694 	media_type = http_media_type(ref->path);
    695 	if (media_type != NULL)
    696 		http_response_header(req, "content-type", media_type);
    697 
    698 	if (http_request_header(req, "if-modified-since", &modified)) {
    699 		mtime = kore_date_to_time(modified);
    700 		if (mtime == ref->mtime_sec) {
    701 			kore_fileref_release(ref);
    702 			http_response(req, HTTP_STATUS_NOT_MODIFIED, NULL, 0);
    703 			return;
    704 		}
    705 	}
    706 
    707 	if ((tm = gmtime(&ref->mtime_sec)) != NULL) {
    708 		if (strftime(tbuf, sizeof(tbuf),
    709 		    "%a, %d %b %Y %H:%M:%S GMT", tm) > 0) {
    710 			http_response_header(req, "last-modified", tbuf);
    711 		}
    712 	}
    713 
    714 	req->status = status;
    715 	switch (req->owner->proto) {
    716 	case CONN_PROTO_HTTP:
    717 		http_response_normal(req, req->owner, status, NULL, ref->size);
    718 		break;
    719 	default:
    720 		fatal("http_response_fd() bad proto %d", req->owner->proto);
    721 		/* NOTREACHED. */
    722 	}
    723 
    724 	if (req->method != HTTP_METHOD_HEAD)
    725 		net_send_fileref(req->owner, ref);
    726 	else
    727 		kore_fileref_release(ref);
    728 }
    729 
    730 int
    731 http_request_header(struct http_request *req, const char *header,
    732     const char **out)
    733 {
    734 	struct http_header	*hdr;
    735 
    736 	TAILQ_FOREACH(hdr, &(req->req_headers), list) {
    737 		if (!strcasecmp(hdr->header, header)) {
    738 			*out = hdr->value;
    739 			return (KORE_RESULT_OK);
    740 		}
    741 	}
    742 
    743 	if (!strcasecmp(header, "host")) {
    744 		*out = req->host;
    745 		return (KORE_RESULT_OK);
    746 	}
    747 
    748 	return (KORE_RESULT_ERROR);
    749 }
    750 
    751 int
    752 http_request_header_get(struct http_request *req, const char *header,
    753     void **out, void *nout, int type)
    754 {
    755 	struct http_header	*hdr;
    756 
    757 	if (type == HTTP_ARG_TYPE_STRING)
    758 		fatal("%s: cannot be called with type string", __func__);
    759 
    760 	TAILQ_FOREACH(hdr, &req->req_headers, list) {
    761 		if (strcasecmp(hdr->header, header))
    762 			continue;
    763 
    764 		if (http_data_convert(hdr->value, out, nout, type))
    765 			return (KORE_RESULT_OK);
    766 
    767 		return (KORE_RESULT_ERROR);
    768 	}
    769 
    770 	return (KORE_RESULT_ERROR);
    771 }
    772 
    773 int
    774 http_request_cookie(struct http_request *req, const char *cookie, char **out)
    775 {
    776 	struct http_cookie	*ck;
    777 
    778 	TAILQ_FOREACH(ck, &(req->req_cookies), list) {
    779 		if (!strcasecmp(ck->name, cookie)) {
    780 			*out = ck->value;
    781 			return (KORE_RESULT_OK);
    782 		}
    783 	}
    784 
    785 	return (KORE_RESULT_ERROR);
    786 }
    787 
    788 int
    789 http_header_recv(struct netbuf *nb)
    790 {
    791 	struct connection	*c;
    792 	size_t			len;
    793 	struct http_header	*hdr;
    794 	struct http_request	*req;
    795 	u_int8_t		*end_headers;
    796 	int			h, i, v, skip, l;
    797 	char			*headers[HTTP_REQ_HEADER_MAX];
    798 	char			*value, *host, *request[4], *hbuf;
    799 
    800 	c = nb->owner;
    801 
    802 	if (nb->s_off < 4)
    803 		return (KORE_RESULT_OK);
    804 
    805 	if (!isalpha(nb->buf[0])) {
    806 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    807 		return (KORE_RESULT_ERROR);
    808 	}
    809 
    810 	skip = 4;
    811 	end_headers = kore_mem_find(nb->buf, nb->s_off, "\r\n\r\n", 4);
    812 	if (end_headers == NULL) {
    813 		end_headers = kore_mem_find(nb->buf, nb->s_off, "\n\n", 2);
    814 		if (end_headers == NULL) {
    815 			if (nb->s_off == http_header_max) {
    816 				http_error_response(c,
    817 				    HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE);
    818 				return (KORE_RESULT_ERROR);
    819 			}
    820 			return (KORE_RESULT_OK);
    821 		}
    822 		skip = 2;
    823 	}
    824 
    825 	*end_headers = '\0';
    826 	end_headers += skip;
    827 	len = end_headers - nb->buf;
    828 	hbuf = (char *)nb->buf;
    829 
    830 	h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX);
    831 	if (h < 2) {
    832 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    833 		return (KORE_RESULT_OK);
    834 	}
    835 
    836 	v = kore_split_string(headers[0], " ", request, 4);
    837 	if (v != 3) {
    838 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    839 		return (KORE_RESULT_OK);
    840 	}
    841 
    842 	skip = 0;
    843 	host = NULL;
    844 	for (i = 0; i < h; i++) {
    845 		if (strncasecmp(headers[i], "host", 4))
    846 			continue;
    847 
    848 		if ((host = http_validate_header(headers[i])) == NULL) {
    849 			http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    850 			return (KORE_RESULT_OK);
    851 		}
    852 
    853 		if (*host == '\0') {
    854 			http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    855 			return (KORE_RESULT_OK);
    856 		}
    857 
    858 		skip = i;
    859 		break;
    860 	}
    861 
    862 	if (host == NULL) {
    863 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    864 		return (KORE_RESULT_OK);
    865 	}
    866 
    867 	req = http_request_new(c, host, request[0], request[1], request[2]);
    868 	if (req == NULL)
    869 		return (KORE_RESULT_OK);
    870 
    871 	/* take full ownership of the buffer. */
    872 	req->headers = nb->buf;
    873 	nb->buf = NULL;
    874 	nb->m_len = 0;
    875 
    876 	for (i = 1; i < h; i++) {
    877 		if (i == skip)
    878 			continue;
    879 
    880 		if ((value = http_validate_header(headers[i])) == NULL) {
    881 			req->flags |= HTTP_REQUEST_DELETE;
    882 			http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    883 			return (KORE_RESULT_OK);
    884 		}
    885 
    886 		if (*value == '\0') {
    887 			req->flags |= HTTP_REQUEST_DELETE;
    888 			http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    889 			return (KORE_RESULT_OK);
    890 		}
    891 
    892 		hdr = kore_pool_get(&http_header_pool);
    893 		hdr->header = headers[i];
    894 		hdr->value = value;
    895 		TAILQ_INSERT_TAIL(&(req->req_headers), hdr, list);
    896 
    897 		if (req->agent == NULL &&
    898 		    !strcasecmp(hdr->header, "user-agent"))
    899 			req->agent = hdr->value;
    900 
    901 		if (req->referer == NULL &&
    902 		    !strcasecmp(hdr->header, "referer"))
    903 			req->referer = hdr->value;
    904 	}
    905 
    906 	if (req->flags & HTTP_REQUEST_EXPECT_BODY) {
    907 		if (http_body_max == 0) {
    908 			req->flags |= HTTP_REQUEST_DELETE;
    909 			http_error_response(req->owner,
    910 			    HTTP_STATUS_METHOD_NOT_ALLOWED);
    911 			return (KORE_RESULT_OK);
    912 		}
    913 
    914 		if (!http_request_header_uint64(req, "content-length",
    915 		    &req->content_length)) {
    916 			if (req->method == HTTP_METHOD_DELETE) {
    917 				req->flags |= HTTP_REQUEST_COMPLETE;
    918 				return (KORE_RESULT_OK);
    919 			}
    920 
    921 			req->flags |= HTTP_REQUEST_DELETE;
    922 			http_error_response(req->owner,
    923 			    HTTP_STATUS_LENGTH_REQUIRED);
    924 			return (KORE_RESULT_OK);
    925 		}
    926 
    927 		if (req->content_length == 0) {
    928 			c->http_timeout = 0;
    929 			req->flags |= HTTP_REQUEST_COMPLETE;
    930 			req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
    931 			return (KORE_RESULT_OK);
    932 		}
    933 
    934 		if (req->content_length > http_body_max) {
    935 			req->flags |= HTTP_REQUEST_DELETE;
    936 			http_error_response(req->owner,
    937 			    HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE);
    938 			return (KORE_RESULT_OK);
    939 		}
    940 
    941 		req->http_body_length = req->content_length;
    942 
    943 		if (http_body_disk_offload > 0 &&
    944 		    req->content_length > http_body_disk_offload) {
    945 			req->http_body_path = kore_pool_get(&http_body_path);
    946 			l = snprintf(req->http_body_path, HTTP_BODY_PATH_MAX,
    947 			    "%s/http_body.XXXXXX", http_body_disk_path);
    948 			if (l == -1 || (size_t)l >= HTTP_BODY_PATH_MAX) {
    949 				req->flags |= HTTP_REQUEST_DELETE;
    950 				http_error_response(req->owner,
    951 				    HTTP_STATUS_INTERNAL_ERROR);
    952 				return (KORE_RESULT_ERROR);
    953 			}
    954 
    955 			req->http_body = NULL;
    956 			req->http_body_fd = mkstemp(req->http_body_path);
    957 			if (req->http_body_fd == -1) {
    958 				req->flags |= HTTP_REQUEST_DELETE;
    959 				http_error_response(req->owner,
    960 				    HTTP_STATUS_INTERNAL_ERROR);
    961 				return (KORE_RESULT_OK);
    962 			}
    963 		} else {
    964 			req->http_body_fd = -1;
    965 			req->http_body = kore_buf_alloc(req->content_length);
    966 		}
    967 
    968 		SHA256Init(&req->hashctx);
    969 		c->http_timeout = http_body_timeout * 1000;
    970 
    971 		if (!http_body_update(req, end_headers, nb->s_off - len)) {
    972 			req->flags |= HTTP_REQUEST_DELETE;
    973 			http_error_response(req->owner,
    974 			    HTTP_STATUS_INTERNAL_ERROR);
    975 			return (KORE_RESULT_OK);
    976 		}
    977 	} else {
    978 		c->http_timeout = 0;
    979 	}
    980 
    981 	if (req->rt->on_headers != NULL) {
    982 		if (!kore_runtime_http_request(req->rt->on_headers, req)) {
    983 			req->flags |= HTTP_REQUEST_DELETE;
    984 			return (KORE_RESULT_OK);
    985 		}
    986 	}
    987 
    988 	return (KORE_RESULT_OK);
    989 }
    990 
    991 int
    992 http_argument_get(struct http_request *req, const char *name,
    993     void **out, void *nout, int type)
    994 {
    995 	struct http_arg		*q;
    996 
    997 	TAILQ_FOREACH(q, &(req->arguments), list) {
    998 		if (strcmp(q->name, name))
    999 			continue;
   1000 
   1001 		if (http_data_convert(q->s_value, out, nout, type))
   1002 			return (KORE_RESULT_OK);
   1003 
   1004 		break;
   1005 	}
   1006 
   1007 	return (KORE_RESULT_ERROR);
   1008 }
   1009 
   1010 int
   1011 http_argument_urldecode(char *arg)
   1012 {
   1013 	u_int8_t	v;
   1014 	int		err;
   1015 	size_t		len;
   1016 	char		*p, *in, h[5];
   1017 
   1018 	p = arg;
   1019 	in = arg;
   1020 	len = strlen(arg);
   1021 
   1022 	while (*p != '\0' && p < (arg + len)) {
   1023 		if (*p == '+')
   1024 			*p = ' ';
   1025 		if (*p != '%') {
   1026 			*in++ = *p++;
   1027 			continue;
   1028 		}
   1029 
   1030 		if ((p + 2) >= (arg + len))
   1031 			return (KORE_RESULT_ERROR);
   1032 
   1033 		if (!isxdigit((unsigned char)*(p + 1)) ||
   1034 		    !isxdigit((unsigned char)*(p + 2))) {
   1035 			*in++ = *p++;
   1036 			continue;
   1037 		}
   1038 
   1039 		h[0] = '0';
   1040 		h[1] = 'x';
   1041 		h[2] = *(p + 1);
   1042 		h[3] = *(p + 2);
   1043 		h[4] = '\0';
   1044 
   1045 		v = kore_strtonum(h, 16, 0x0, 0xff, &err);
   1046 		if (err != KORE_RESULT_OK)
   1047 			return (err);
   1048 
   1049 		if (v <= 0x1f || v == 0x7f)
   1050 			return (KORE_RESULT_ERROR);
   1051 
   1052 		*in++ = (char)v;
   1053 		p += 3;
   1054 	}
   1055 
   1056 	*in = '\0';
   1057 	return (KORE_RESULT_OK);
   1058 }
   1059 
   1060 struct http_file *
   1061 http_file_lookup(struct http_request *req, const char *name)
   1062 {
   1063 	struct http_file	*f;
   1064 
   1065 	TAILQ_FOREACH(f, &(req->files), list) {
   1066 		if (!strcmp(f->name, name))
   1067 			return (f);
   1068 	}
   1069 
   1070 	return (NULL);
   1071 }
   1072 
   1073 ssize_t
   1074 http_file_read(struct http_file *file, void *buf, size_t len)
   1075 {
   1076 	ssize_t		ret;
   1077 	size_t		toread, off;
   1078 
   1079 	if (file->length < file->offset)
   1080 		return (-1);
   1081 	if ((file->offset + len) < file->offset)
   1082 		return (-1);
   1083 	if ((file->position + file->offset) < file->position)
   1084 		return (-1);
   1085 
   1086 	off = file->position + file->offset;
   1087 	toread = MIN(len, (file->length - file->offset));
   1088 	if (toread == 0)
   1089 		return (0);
   1090 
   1091 	if (file->req->http_body_fd != -1) {
   1092 		if (lseek(file->req->http_body_fd, off, SEEK_SET) == -1) {
   1093 			kore_log(LOG_ERR, "http_file_read: lseek(%s): %s",
   1094 			    file->req->http_body_path, errno_s);
   1095 			return (-1);
   1096 		}
   1097 
   1098 		for (;;) {
   1099 			ret = read(file->req->http_body_fd, buf, toread);
   1100 			if (ret == -1) {
   1101 				if (errno == EINTR)
   1102 					continue;
   1103 				kore_log(LOG_ERR, "failed to read %s: %s",
   1104 				    file->req->http_body_path, errno_s);
   1105 				return (-1);
   1106 			}
   1107 			if (ret == 0)
   1108 				return (0);
   1109 			break;
   1110 		}
   1111 	} else if (file->req->http_body != NULL) {
   1112 		if (off > file->req->http_body->length)
   1113 			return (0);
   1114 		memcpy(buf, file->req->http_body->data + off, toread);
   1115 		ret = toread;
   1116 	} else {
   1117 		kore_log(LOG_ERR, "http_file_read: called without body");
   1118 		return (-1);
   1119 	}
   1120 
   1121 	file->offset += (size_t)ret;
   1122 	return (ret);
   1123 }
   1124 
   1125 void
   1126 http_file_rewind(struct http_file *file)
   1127 {
   1128 	file->offset = 0;
   1129 }
   1130 
   1131 void
   1132 http_response_cookie(struct http_request *req, const char *name,
   1133     const char *val, const char *path, time_t expires, u_int32_t maxage,
   1134     struct http_cookie **out)
   1135 {
   1136 	char			*p;
   1137 	struct http_cookie	*ck;
   1138 
   1139 	if (name == NULL || val == NULL)
   1140 		fatal("http_response_cookie: invalid parameters");
   1141 
   1142 	ck = kore_pool_get(&http_cookie_pool);
   1143 
   1144 	ck->maxage = maxage;
   1145 	ck->expires = expires;
   1146 	ck->name = kore_strdup(name);
   1147 	ck->value = kore_strdup(val);
   1148 	ck->domain = kore_strdup(req->host);
   1149 	ck->flags = HTTP_COOKIE_HTTPONLY | HTTP_COOKIE_SECURE;
   1150 
   1151 	if ((p = strrchr(ck->domain, ':')) != NULL)
   1152 		*p = '\0';
   1153 
   1154 	if (path != NULL)
   1155 		ck->path = kore_strdup(path);
   1156 	else
   1157 		ck->path = NULL;
   1158 
   1159 	TAILQ_INSERT_TAIL(&(req->resp_cookies), ck, list);
   1160 
   1161 	if (out != NULL)
   1162 		*out = ck;
   1163 }
   1164 
   1165 void
   1166 http_populate_cookies(struct http_request *req)
   1167 {
   1168 	struct http_cookie	*ck;
   1169 	const char		*hdr;
   1170 	int			 i, v, n;
   1171 	char			*c, *header, *pair[3];
   1172 	char			*cookies[HTTP_MAX_COOKIES];
   1173 
   1174 	if (!http_request_header(req, "cookie", &hdr))
   1175 		return;
   1176 
   1177 	header = kore_strdup(hdr);
   1178 	v = kore_split_string(header, ";", cookies, HTTP_MAX_COOKIES);
   1179 	for (i = 0; i < v; i++) {
   1180 		for (c = cookies[i]; isspace(*(unsigned char *)c); c++)
   1181 			;
   1182 
   1183 		n = kore_split_string(c, "=", pair, 3);
   1184 		if (n != 2)
   1185 			continue;
   1186 
   1187 		ck = kore_pool_get(&http_cookie_pool);
   1188 		ck->name = kore_strdup(pair[0]);
   1189 		ck->value = kore_strdup(pair[1]);
   1190 		TAILQ_INSERT_TAIL(&(req->req_cookies), ck, list);
   1191 	}
   1192 
   1193 	kore_free(header);
   1194 }
   1195 
   1196 void
   1197 http_populate_post(struct http_request *req)
   1198 {
   1199 	ssize_t			ret;
   1200 	int			i, v;
   1201 	struct kore_buf		*body;
   1202 	char			data[BUFSIZ];
   1203 	char			*args[HTTP_MAX_QUERY_ARGS], *val[3], *string;
   1204 
   1205 	if (req->method != HTTP_METHOD_POST)
   1206 		return;
   1207 
   1208 	if (req->http_body != NULL) {
   1209 		body = NULL;
   1210 		req->http_body->offset = req->content_length;
   1211 		string = kore_buf_stringify(req->http_body, NULL);
   1212 		req->http_body_length = 0;
   1213 		req->http_body_offset = 0;
   1214 	} else {
   1215 		body = kore_buf_alloc(128);
   1216 		for (;;) {
   1217 			ret = http_body_read(req, data, sizeof(data));
   1218 			if (ret == -1)
   1219 				goto out;
   1220 			if (ret == 0)
   1221 				break;
   1222 			kore_buf_append(body, data, ret);
   1223 		}
   1224 		string = kore_buf_stringify(body, NULL);
   1225 	}
   1226 
   1227 	v = kore_split_string(string, "&", args, HTTP_MAX_QUERY_ARGS);
   1228 	for (i = 0; i < v; i++) {
   1229 		kore_split_string(args[i], "=", val, 3);
   1230 		if (val[0] != NULL && val[1] != NULL)
   1231 			http_argument_add(req, val[0], val[1], 0, 1);
   1232 	}
   1233 
   1234 out:
   1235 	if (body != NULL)
   1236 		kore_buf_free(body);
   1237 }
   1238 
   1239 void
   1240 http_populate_qs(struct http_request *req)
   1241 {
   1242 	int		i, v;
   1243 	char		*query, *args[HTTP_MAX_QUERY_ARGS], *val[3];
   1244 
   1245 	if (req->query_string == NULL)
   1246 		return;
   1247 
   1248 	query = kore_strdup(req->query_string);
   1249 	v = kore_split_string(query, "&", args, HTTP_MAX_QUERY_ARGS);
   1250 	for (i = 0; i < v; i++) {
   1251 		kore_split_string(args[i], "=", val, 3);
   1252 		if (val[0] != NULL && val[1] != NULL)
   1253 			http_argument_add(req, val[0], val[1], 1, 1);
   1254 	}
   1255 
   1256 	kore_free(query);
   1257 }
   1258 
   1259 void
   1260 http_populate_multipart_form(struct http_request *req)
   1261 {
   1262 	const char		*hdr;
   1263 	int			h, blen;
   1264 	struct kore_buf		in, out;
   1265 	char			*type, *val, *args[3];
   1266 	char			boundary[HTTP_BOUNDARY_MAX];
   1267 
   1268 	if (req->method != HTTP_METHOD_POST)
   1269 		return;
   1270 
   1271 	if (!http_request_header(req, "content-type", &hdr))
   1272 		return;
   1273 
   1274 	kore_buf_init(&in, 128);
   1275 	kore_buf_init(&out, 128);
   1276 
   1277 	type = kore_strdup(hdr);
   1278 	h = kore_split_string(type, ";", args, 3);
   1279 	if (h != 2)
   1280 		goto cleanup;
   1281 
   1282 	if (strcasecmp(args[0], "multipart/form-data"))
   1283 		goto cleanup;
   1284 
   1285 	if ((val = strchr(args[1], '=')) == NULL)
   1286 		goto cleanup;
   1287 
   1288 	val++;
   1289 	blen = snprintf(boundary, sizeof(boundary), "--%s", val);
   1290 	if (blen == -1 || (size_t)blen >= sizeof(boundary))
   1291 		goto cleanup;
   1292 
   1293 	if (!multipart_find_data(&in, NULL, NULL, req, boundary, blen))
   1294 		goto cleanup;
   1295 
   1296 	for (;;) {
   1297 		if (!multipart_find_data(&in, NULL, NULL, req, "\r\n", 2))
   1298 			break;
   1299 		if (in.offset < 4 && req->http_body_length == 0)
   1300 			break;
   1301 		if (!multipart_find_data(&in, &out, NULL, req, "\r\n\r\n", 4))
   1302 			break;
   1303 		if (!multipart_parse_headers(req, &in, &out, boundary, blen))
   1304 			break;
   1305 
   1306 		kore_buf_reset(&out);
   1307 	}
   1308 
   1309 cleanup:
   1310 	kore_free(type);
   1311 	kore_buf_cleanup(&in);
   1312 	kore_buf_cleanup(&out);
   1313 }
   1314 
   1315 int
   1316 http_body_rewind(struct http_request *req)
   1317 {
   1318 	if (req->http_body_fd != -1) {
   1319 		if (lseek(req->http_body_fd, 0, SEEK_SET) == -1) {
   1320 			kore_log(LOG_ERR, "lseek(%s) failed: %s",
   1321 			    req->http_body_path, errno_s);
   1322 			return (KORE_RESULT_ERROR);
   1323 		}
   1324 	} else if (req->http_body != NULL) {
   1325 		kore_buf_reset(req->http_body);
   1326 	}
   1327 
   1328 	req->http_body_offset = 0;
   1329 	req->http_body_length = req->content_length;
   1330 
   1331 	return (KORE_RESULT_OK);
   1332 }
   1333 
   1334 int
   1335 http_body_digest(struct http_request *req, char *out, size_t len)
   1336 {
   1337 	size_t		idx;
   1338 	int		slen;
   1339 
   1340 	if (len != HTTP_BODY_DIGEST_STRLEN) {
   1341 		fatal("http_body_digest: bad len:%zu wanted:%u",
   1342 		    len, HTTP_BODY_DIGEST_STRLEN);
   1343 	}
   1344 
   1345 	if (!(req->flags & HTTP_REQUEST_COMPLETE))
   1346 		return (KORE_RESULT_ERROR);
   1347 
   1348 	for (idx = 0; idx < sizeof(req->http_body_digest); idx++) {
   1349 		slen = snprintf(out + (idx * 2), len - (idx * 2), "%02x",
   1350 		    req->http_body_digest[idx]);
   1351 		if (slen == -1 || (size_t)slen >= len)
   1352 			fatal("failed to create hex string");
   1353 	}
   1354 
   1355 	return (KORE_RESULT_OK);
   1356 }
   1357 
   1358 ssize_t
   1359 http_body_read(struct http_request *req, void *out, size_t len)
   1360 {
   1361 	ssize_t		ret;
   1362 	size_t		toread;
   1363 
   1364 	toread = MIN(req->http_body_length, len);
   1365 	if (toread == 0)
   1366 		return (0);
   1367 
   1368 	if (req->http_body_fd != -1) {
   1369 		for (;;) {
   1370 			ret = read(req->http_body_fd, out, toread);
   1371 			if (ret == -1) {
   1372 				if (errno == EINTR)
   1373 					continue;
   1374 				kore_log(LOG_ERR, "failed to read %s: %s",
   1375 				    req->http_body_path, errno_s);
   1376 				return (-1);
   1377 			}
   1378 			if (ret == 0)
   1379 				return (0);
   1380 			break;
   1381 		}
   1382 	} else if (req->http_body != NULL) {
   1383 		memcpy(out,
   1384 		    (req->http_body->data + req->http_body->offset), toread);
   1385 		req->http_body->offset += toread;
   1386 		ret = toread;
   1387 	} else {
   1388 		kore_log(LOG_ERR, "http_body_read: called without body");
   1389 		return (-1);
   1390 	}
   1391 
   1392 	req->http_body_length -= (size_t)ret;
   1393 	req->http_body_offset += (size_t)ret;
   1394 
   1395 	return (ret);
   1396 }
   1397 
   1398 int
   1399 http_state_run(struct http_state *states, u_int8_t elm,
   1400     struct http_request *req)
   1401 {
   1402 	int		r, done;
   1403 
   1404 	done = 0;
   1405 
   1406 	while (!done) {
   1407 		if (req->fsm_state >= elm) {
   1408 			fatal("http_state_run: fsm_state > elm (%d/%d)",
   1409 			    req->fsm_state, elm);
   1410 		}
   1411 
   1412 		r = states[req->fsm_state].cb(req);
   1413 		switch (r) {
   1414 		case HTTP_STATE_ERROR:
   1415 			return (KORE_RESULT_OK);
   1416 		case HTTP_STATE_RETRY:
   1417 			return (KORE_RESULT_RETRY);
   1418 		case HTTP_STATE_CONTINUE:
   1419 			break;
   1420 		case HTTP_STATE_COMPLETE:
   1421 			done = 1;
   1422 			break;
   1423 		default:
   1424 			fatal("http_state_run: unknown return value %d", r);
   1425 		}
   1426 	}
   1427 
   1428 	req->fsm_state = 0;
   1429 
   1430 	return (KORE_RESULT_OK);
   1431 }
   1432 
   1433 int
   1434 http_state_exists(struct http_request *req)
   1435 {
   1436 	return (req->hdlr_extra != NULL);
   1437 }
   1438 
   1439 void *
   1440 http_state_create(struct http_request *req, size_t len)
   1441 {
   1442 	if (req->hdlr_extra != NULL)
   1443 		fatal("http_state_create: state already exists");
   1444 
   1445 	req->state_len = len;
   1446 	req->hdlr_extra = kore_calloc(1, len);
   1447 
   1448 	return (req->hdlr_extra);
   1449 }
   1450 
   1451 void *
   1452 http_state_get(struct http_request *req)
   1453 {
   1454 	return (req->hdlr_extra);
   1455 }
   1456 
   1457 void
   1458 http_state_cleanup(struct http_request *req)
   1459 {
   1460 	kore_free(req->hdlr_extra);
   1461 	req->hdlr_extra = NULL;
   1462 }
   1463 
   1464 void
   1465 http_start_recv(struct connection *c)
   1466 {
   1467 	c->http_start = kore_time_ms();
   1468 	c->http_timeout = http_header_timeout * 1000;
   1469 	net_recv_reset(c, http_header_max, http_header_recv);
   1470 }
   1471 
   1472 void
   1473 http_runlock_init(struct http_runlock *lock)
   1474 {
   1475 	lock->owner = NULL;
   1476 	LIST_INIT(&lock->queue);
   1477 }
   1478 
   1479 int
   1480 http_runlock_acquire(struct http_runlock *lock, struct http_request *req)
   1481 {
   1482 	if (lock->owner != NULL) {
   1483 		if (req->runlock != NULL)
   1484 			fatal("%s: request already waiting on lock", __func__);
   1485 
   1486 		req->runlock = kore_pool_get(&http_rlq_pool);
   1487 		req->runlock->req = req;
   1488 		LIST_INSERT_HEAD(&lock->queue, req->runlock, list);
   1489 
   1490 		http_request_sleep(req);
   1491 		return (KORE_RESULT_ERROR);
   1492 	}
   1493 
   1494 	lock->owner = req;
   1495 
   1496 	return (KORE_RESULT_OK);
   1497 }
   1498 
   1499 void
   1500 http_runlock_release(struct http_runlock *lock, struct http_request *req)
   1501 {
   1502 	struct http_runlock_queue	*next;
   1503 	struct http_request		*nextreq;
   1504 
   1505 	if (lock->owner != req)
   1506 		fatal("%s: calling request != owner of runlock", __func__);
   1507 
   1508 	lock->owner = NULL;
   1509 
   1510 	if ((next = LIST_FIRST(&lock->queue)) != NULL) {
   1511 		LIST_REMOVE(next, list);
   1512 
   1513 		nextreq = next->req;
   1514 		nextreq->runlock = NULL;
   1515 
   1516 		http_request_wakeup(nextreq);
   1517 		kore_pool_put(&http_rlq_pool, next);
   1518 	}
   1519 }
   1520 
   1521 int
   1522 http_redirect_add(struct kore_domain *dom, const char *path, int status,
   1523     const char *target)
   1524 {
   1525 	struct http_redirect	*rdr;
   1526 
   1527 	rdr = kore_calloc(1, sizeof(*rdr));
   1528 
   1529 	if (regcomp(&(rdr->rctx), path, REG_EXTENDED)) {
   1530 		kore_free(rdr);
   1531 		return (KORE_RESULT_ERROR);
   1532 	}
   1533 
   1534 	rdr->status = status;
   1535 
   1536 	if (target != NULL)
   1537 		rdr->target = kore_strdup(target);
   1538 	else
   1539 		rdr->target = NULL;
   1540 
   1541 	TAILQ_INSERT_TAIL(&dom->redirects, rdr, list);
   1542 
   1543 	return (KORE_RESULT_OK);
   1544 }
   1545 
   1546 const char *
   1547 http_status_text(int status)
   1548 {
   1549 	const char	*r;
   1550 
   1551 	switch (status) {
   1552 	case HTTP_STATUS_CONTINUE:
   1553 		r = "Continue";
   1554 		break;
   1555 	case HTTP_STATUS_SWITCHING_PROTOCOLS:
   1556 		r = "Switching Protocols";
   1557 		break;
   1558 	case HTTP_STATUS_OK:
   1559 		r = "OK";
   1560 		break;
   1561 	case HTTP_STATUS_CREATED:
   1562 		r = "Created";
   1563 		break;
   1564 	case HTTP_STATUS_ACCEPTED:
   1565 		r = "Accepted";
   1566 		break;
   1567 	case HTTP_STATUS_NON_AUTHORITATIVE:
   1568 		r = "Non-Authoritative Information";
   1569 		break;
   1570 	case HTTP_STATUS_NO_CONTENT:
   1571 		r = "No Content";
   1572 		break;
   1573 	case HTTP_STATUS_RESET_CONTENT:
   1574 		r = "Reset Content";
   1575 		break;
   1576 	case HTTP_STATUS_PARTIAL_CONTENT:
   1577 		r = "Partial Content";
   1578 		break;
   1579 	case HTTP_STATUS_MULTIPLE_CHOICES:
   1580 		r = "Multiple Choices";
   1581 		break;
   1582 	case HTTP_STATUS_MOVED_PERMANENTLY:
   1583 		r = "Moved Permanently";
   1584 		break;
   1585 	case HTTP_STATUS_FOUND:
   1586 		r = "Found";
   1587 		break;
   1588 	case HTTP_STATUS_SEE_OTHER:
   1589 		r = "See Other";
   1590 		break;
   1591 	case HTTP_STATUS_NOT_MODIFIED:
   1592 		r = "Not Modified";
   1593 		break;
   1594 	case HTTP_STATUS_USE_PROXY:
   1595 		r = "Use Proxy";
   1596 		break;
   1597 	case HTTP_STATUS_TEMPORARY_REDIRECT:
   1598 		r = "Temporary Redirect";
   1599 		break;
   1600 	case HTTP_STATUS_BAD_REQUEST:
   1601 		r = "Bad Request";
   1602 		break;
   1603 	case HTTP_STATUS_UNAUTHORIZED:
   1604 		r = "Unauthorized";
   1605 		break;
   1606 	case HTTP_STATUS_PAYMENT_REQUIRED:
   1607 		r = "Payment Required";
   1608 		break;
   1609 	case HTTP_STATUS_FORBIDDEN:
   1610 		r = "Forbidden";
   1611 		break;
   1612 	case HTTP_STATUS_NOT_FOUND:
   1613 		r = "Not Found";
   1614 		break;
   1615 	case HTTP_STATUS_METHOD_NOT_ALLOWED:
   1616 		r = "Method Not Allowed";
   1617 		break;
   1618 	case HTTP_STATUS_NOT_ACCEPTABLE:
   1619 		r = "Not Acceptable";
   1620 		break;
   1621 	case HTTP_STATUS_PROXY_AUTH_REQUIRED:
   1622 		r = "Proxy Authentication Required";
   1623 		break;
   1624 	case HTTP_STATUS_REQUEST_TIMEOUT:
   1625 		r = "Request Time-out";
   1626 		break;
   1627 	case HTTP_STATUS_CONFLICT:
   1628 		r = "Conflict";
   1629 		break;
   1630 	case HTTP_STATUS_GONE:
   1631 		r = "Gone";
   1632 		break;
   1633 	case HTTP_STATUS_LENGTH_REQUIRED:
   1634 		r = "Length Required";
   1635 		break;
   1636 	case HTTP_STATUS_PRECONDITION_FAILED:
   1637 		r = "Precondition Failed";
   1638 		break;
   1639 	case HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE:
   1640 		r = "Request Entity Too Large";
   1641 		break;
   1642 	case HTTP_STATUS_REQUEST_URI_TOO_LARGE:
   1643 		r = "Request-URI Too Large";
   1644 		break;
   1645 	case HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE:
   1646 		r = "Unsupported Media Type";
   1647 		break;
   1648 	case HTTP_STATUS_REQUEST_RANGE_INVALID:
   1649 		r = "Requested range not satisfiable";
   1650 		break;
   1651 	case HTTP_STATUS_EXPECTATION_FAILED:
   1652 		r = "Expectation Failed";
   1653 		break;
   1654 	case HTTP_STATUS_MISDIRECTED_REQUEST:
   1655 		r = "Misdirected Request";
   1656 		break;
   1657 	case HTTP_STATUS_INTERNAL_ERROR:
   1658 		r = "Internal Server Error";
   1659 		break;
   1660 	case HTTP_STATUS_NOT_IMPLEMENTED:
   1661 		r = "Not Implemented";
   1662 		break;
   1663 	case HTTP_STATUS_BAD_GATEWAY:
   1664 		r = "Bad Gateway";
   1665 		break;
   1666 	case HTTP_STATUS_SERVICE_UNAVAILABLE:
   1667 		r = "Service Unavailable";
   1668 		break;
   1669 	case HTTP_STATUS_GATEWAY_TIMEOUT:
   1670 		r = "Gateway Time-out";
   1671 		break;
   1672 	case HTTP_STATUS_BAD_VERSION:
   1673 		r = "HTTP Version not supported";
   1674 		break;
   1675 	default:
   1676 		r = "";
   1677 		break;
   1678 	}
   1679 
   1680 	return (r);
   1681 }
   1682 
   1683 const char *
   1684 http_method_text(int method)
   1685 {
   1686 	char		*r;
   1687 
   1688 	switch(method) {
   1689 	case HTTP_METHOD_GET:
   1690 		r = "GET";
   1691 		break;
   1692 	case HTTP_METHOD_POST:
   1693 		r = "POST";
   1694 		break;
   1695 	case HTTP_METHOD_PUT:
   1696 		r = "PUT";
   1697 		break;
   1698 	case HTTP_METHOD_DELETE:
   1699 		r = "DELETE";
   1700 		break;
   1701 	case HTTP_METHOD_HEAD:
   1702 		r = "HEAD";
   1703 		break;
   1704 	case HTTP_METHOD_OPTIONS:
   1705 		r = "OPTIONS";
   1706 		break;
   1707 	case HTTP_METHOD_PATCH:
   1708 		r = "PATCH";
   1709 		break;
   1710 	default:
   1711 		r = "";
   1712 		break;
   1713 	}
   1714 
   1715 	return (r);
   1716 }
   1717 
   1718 int
   1719 http_method_value(const char *method)
   1720 {
   1721 	if (!strcasecmp(method, "GET"))
   1722 		return (HTTP_METHOD_GET);
   1723 
   1724 	if (!strcasecmp(method, "POST"))
   1725 		return (HTTP_METHOD_POST);
   1726 
   1727 	if (!strcasecmp(method, "PUT"))
   1728 		return (HTTP_METHOD_PUT);
   1729 
   1730 	if (!strcasecmp(method, "DELETE"))
   1731 		return (HTTP_METHOD_DELETE);
   1732 
   1733 	if (!strcasecmp(method, "HEAD"))
   1734 		return (HTTP_METHOD_HEAD);
   1735 
   1736 	if (!strcasecmp(method, "OPTIONS"))
   1737 		return (HTTP_METHOD_OPTIONS);
   1738 
   1739 	if (!strcasecmp(method, "PATCH"))
   1740 		return (HTTP_METHOD_PATCH);
   1741 
   1742 	return (0);
   1743 }
   1744 
   1745 int
   1746 http_media_register(const char *ext, const char *type)
   1747 {
   1748 	struct http_media_type	*media;
   1749 
   1750 	LIST_FOREACH(media, &http_media_types, list) {
   1751 		if (!strcasecmp(media->ext, ext))
   1752 			return (KORE_RESULT_ERROR);
   1753 	}
   1754 
   1755 	media = kore_calloc(1, sizeof(*media));
   1756 	media->ext = kore_strdup(ext);
   1757 	media->type = kore_strdup(type);
   1758 
   1759 	LIST_INSERT_HEAD(&http_media_types, media, list);
   1760 
   1761 	return (KORE_RESULT_OK);
   1762 }
   1763 
   1764 const char *
   1765 http_media_type(const char *path)
   1766 {
   1767 	const char		*p;
   1768 	struct http_media_type	*media;
   1769 
   1770 	if ((p = strrchr(path, '.')) == NULL)
   1771 		return (NULL);
   1772 
   1773 	p++;
   1774 	if (*p == '\0')
   1775 		return (NULL);
   1776 
   1777 	LIST_FOREACH(media, &http_media_types, list) {
   1778 		if (!strcasecmp(media->ext, p))
   1779 			return (media->type);
   1780 	}
   1781 
   1782 	return (NULL);
   1783 }
   1784 
   1785 char *
   1786 http_validate_header(char *header)
   1787 {
   1788 	u_int8_t	idx;
   1789 	char		*p, *value;
   1790 
   1791 	for (p = header; *p != '\0'; p++) {
   1792 		idx = *p;
   1793 		if (idx > HTTP_MAP_LIMIT)
   1794 			return (NULL);
   1795 
   1796 		if (*p == ':') {
   1797 			*(p)++ = '\0';
   1798 			break;
   1799 		}
   1800 
   1801 		if (http_token[idx] == 0x00)
   1802 			return (NULL);
   1803 	}
   1804 
   1805 	while (isspace(*(unsigned char *)p))
   1806 		p++;
   1807 
   1808 	if (*p == '\0')
   1809 		return (NULL);
   1810 
   1811 	value = p;
   1812 	while (*p != '\0') {
   1813 		idx = *p;
   1814 		if (idx > HTTP_MAP_LIMIT)
   1815 			return (NULL);
   1816 		if (http_field_content[idx] == 0x00)
   1817 			return (NULL);
   1818 		p++;
   1819 	}
   1820 
   1821 	return (value);
   1822 }
   1823 
   1824 static int
   1825 http_release_buffer(struct netbuf *nb)
   1826 {
   1827 	kore_buf_free(nb->extra);
   1828 
   1829 	return (KORE_RESULT_OK);
   1830 }
   1831 
   1832 static int
   1833 http_check_redirect(struct http_request *req, struct kore_domain *dom)
   1834 {
   1835 	int			idx;
   1836 	struct http_redirect	*rdr;
   1837 	const char		*uri;
   1838 	char			key[4];
   1839 	struct kore_buf		location;
   1840 
   1841 	TAILQ_FOREACH(rdr, &dom->redirects, list) {
   1842 		if (!regexec(&(rdr->rctx), req->path,
   1843 		    HTTP_CAPTURE_GROUPS, req->cgroups, 0))
   1844 			break;
   1845 	}
   1846 
   1847 	if (rdr == NULL)
   1848 		return (KORE_RESULT_ERROR);
   1849 
   1850 	uri = NULL;
   1851 	kore_buf_init(&location, 128);
   1852 
   1853 	if (rdr->target) {
   1854 		kore_buf_appendf(&location, "%s", rdr->target);
   1855 
   1856 		if (req->query_string != NULL) {
   1857 			kore_buf_replace_string(&location, "$qs",
   1858 			    req->query_string, strlen(req->query_string));
   1859 		}
   1860 
   1861 		/* Starts at 1 to skip the full path. */
   1862 		for (idx = 1; idx < HTTP_CAPTURE_GROUPS - 1; idx++) {
   1863 			if (req->cgroups[idx].rm_so == -1 ||
   1864 			    req->cgroups[idx].rm_eo == -1)
   1865 				break;
   1866 
   1867 			(void)snprintf(key, sizeof(key), "$%d", idx);
   1868 
   1869 			kore_buf_replace_string(&location, key,
   1870 			    req->path + req->cgroups[idx].rm_so,
   1871 			    req->cgroups[idx].rm_eo - req->cgroups[idx].rm_so);
   1872 		}
   1873 
   1874 		uri = kore_buf_stringify(&location, NULL);
   1875 	}
   1876 
   1877 	if (uri)
   1878 		http_response_header(req, "location", uri);
   1879 
   1880 	http_response(req, rdr->status, NULL, 0);
   1881 	kore_buf_cleanup(&location);
   1882 
   1883 	if (dom->accesslog)
   1884 		kore_accesslog(req);
   1885 
   1886 	return (KORE_RESULT_OK);
   1887 }
   1888 
   1889 static struct http_request *
   1890 http_request_new(struct connection *c, const char *host,
   1891     const char *method, char *path, const char *version)
   1892 {
   1893 	struct kore_domain		*dom;
   1894 	struct http_request		*req;
   1895 	size_t				qsoff;
   1896 	char				*p, *hp;
   1897 	int				m, flags, exists;
   1898 
   1899 	if (http_request_count >= http_request_limit) {
   1900 		http_error_response(c, HTTP_STATUS_SERVICE_UNAVAILABLE);
   1901 		return (NULL);
   1902 	}
   1903 
   1904 	if (strlen(host) >= KORE_DOMAINNAME_LEN - 1) {
   1905 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
   1906 		return (NULL);
   1907 	}
   1908 
   1909 	if (strlen(path) >= HTTP_URI_LEN - 1) {
   1910 		http_error_response(c, HTTP_STATUS_REQUEST_URI_TOO_LARGE);
   1911 		return (NULL);
   1912 	}
   1913 
   1914 	if (strcasecmp(version, "http/1.1")) {
   1915 		if (strcasecmp(version, "http/1.0")) {
   1916 			http_error_response(c, HTTP_STATUS_BAD_VERSION);
   1917 			return (NULL);
   1918 		}
   1919 
   1920 		flags = HTTP_VERSION_1_0;
   1921 	} else {
   1922 		flags = HTTP_VERSION_1_1;
   1923 	}
   1924 
   1925 	if ((p = strchr(path, '?')) != NULL) {
   1926 		qsoff = p - path;
   1927 	} else {
   1928 		qsoff = 0;
   1929 	}
   1930 
   1931 	hp = NULL;
   1932 
   1933 	switch (c->family) {
   1934 	case AF_INET6:
   1935 		if (*host == '[') {
   1936 			if ((hp = strrchr(host, ']')) == NULL) {
   1937 				http_error_response(c, HTTP_STATUS_BAD_REQUEST);
   1938 				return (NULL);
   1939 			}
   1940 			hp++;
   1941 			if (*hp == ':')
   1942 				*hp = '\0';
   1943 			else
   1944 				hp = NULL;
   1945 		}
   1946 		break;
   1947 	default:
   1948 		if ((hp = strrchr(host, ':')) != NULL)
   1949 			*hp = '\0';
   1950 		break;
   1951 	}
   1952 
   1953 	if (c->owner->server->tls && c->tls_sni != NULL) {
   1954 		if (strcasecmp(c->tls_sni, host)) {
   1955 			http_error_response(c, HTTP_STATUS_MISDIRECTED_REQUEST);
   1956 			return (NULL);
   1957 		}
   1958 	}
   1959 
   1960 	if ((dom = kore_domain_lookup(c->owner->server, host)) == NULL) {
   1961 		http_error_response(c, HTTP_STATUS_NOT_FOUND);
   1962 		return (NULL);
   1963 	}
   1964 
   1965 	if (dom->cafile != NULL && c->tls_cert == NULL) {
   1966 		http_error_response(c, HTTP_STATUS_FORBIDDEN);
   1967 		return (NULL);
   1968 	}
   1969 
   1970 	if (hp != NULL)
   1971 		*hp = ':';
   1972 
   1973 	if (!strcasecmp(method, "get")) {
   1974 		m = HTTP_METHOD_GET;
   1975 		flags |= HTTP_REQUEST_COMPLETE;
   1976 	} else if (!strcasecmp(method, "delete")) {
   1977 		m = HTTP_METHOD_DELETE;
   1978 		flags |= HTTP_REQUEST_EXPECT_BODY;
   1979 	} else if (!strcasecmp(method, "post")) {
   1980 		m = HTTP_METHOD_POST;
   1981 		flags |= HTTP_REQUEST_EXPECT_BODY;
   1982 	} else if (!strcasecmp(method, "put")) {
   1983 		m = HTTP_METHOD_PUT;
   1984 		flags |= HTTP_REQUEST_EXPECT_BODY;
   1985 	} else if (!strcasecmp(method, "head")) {
   1986 		m = HTTP_METHOD_HEAD;
   1987 		flags |= HTTP_REQUEST_COMPLETE;
   1988 	} else if (!strcasecmp(method, "options")) {
   1989 		m = HTTP_METHOD_OPTIONS;
   1990 		flags |= HTTP_REQUEST_COMPLETE;
   1991 	} else if (!strcasecmp(method, "patch")) {
   1992 		m = HTTP_METHOD_PATCH;
   1993 		flags |= HTTP_REQUEST_EXPECT_BODY;
   1994 	} else {
   1995 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
   1996 		return (NULL);
   1997 	}
   1998 
   1999 	if (flags & HTTP_VERSION_1_0) {
   2000 		if (m != HTTP_METHOD_GET && m != HTTP_METHOD_POST &&
   2001 		    m != HTTP_METHOD_HEAD) {
   2002 			http_error_response(c, HTTP_STATUS_METHOD_NOT_ALLOWED);
   2003 			return (NULL);
   2004 		}
   2005 	}
   2006 
   2007 	req = kore_pool_get(&http_request_pool);
   2008 
   2009 	req->end = 0;
   2010 	req->total = 0;
   2011 	req->start = 0;
   2012 	req->owner = c;
   2013 	req->status = 0;
   2014 	req->method = m;
   2015 	req->agent = NULL;
   2016 	req->referer = NULL;
   2017 	req->runlock = NULL;
   2018 	req->flags = flags;
   2019 	req->fsm_state = 0;
   2020 	req->http_body = NULL;
   2021 	req->http_body_fd = -1;
   2022 	req->hdlr_extra = NULL;
   2023 	req->content_length = 0;
   2024 	req->query_string = NULL;
   2025 	req->http_body_length = 0;
   2026 	req->http_body_offset = 0;
   2027 	req->http_body_path = NULL;
   2028 
   2029 	req->host = host;
   2030 	req->path = path;
   2031 
   2032 #if defined(KORE_USE_PYTHON)
   2033 	req->py_req = NULL;
   2034 	req->py_coro = NULL;
   2035 	req->py_rqnext = NULL;
   2036 	req->py_validator = NULL;
   2037 #endif
   2038 
   2039 	if (qsoff > 0) {
   2040 		req->query_string = path + qsoff;
   2041 		*(req->query_string)++ = '\0';
   2042 	} else {
   2043 		req->query_string = NULL;
   2044 	}
   2045 
   2046 	/* Checked further down below if we need to 404. */
   2047 	exists = kore_route_lookup(req, dom, m, &req->rt);
   2048 
   2049 	TAILQ_INIT(&(req->resp_headers));
   2050 	TAILQ_INIT(&(req->req_headers));
   2051 	TAILQ_INIT(&(req->resp_cookies));
   2052 	TAILQ_INIT(&(req->req_cookies));
   2053 	TAILQ_INIT(&(req->arguments));
   2054 	TAILQ_INIT(&(req->files));
   2055 
   2056 #if defined(KORE_USE_TASKS)
   2057 	LIST_INIT(&(req->tasks));
   2058 #endif
   2059 
   2060 #if defined(KORE_USE_PGSQL)
   2061 	LIST_INIT(&(req->pgsqls));
   2062 #endif
   2063 
   2064 	http_request_count++;
   2065 	TAILQ_INSERT_HEAD(&http_requests, req, list);
   2066 	TAILQ_INSERT_TAIL(&(c->http_requests), req, olist);
   2067 
   2068 	if (http_check_redirect(req, dom)) {
   2069 		http_request_free(req);
   2070 		return (NULL);
   2071 	}
   2072 
   2073 	if (exists == 0) {
   2074 		http_request_free(req);
   2075 		http_error_response(c, HTTP_STATUS_NOT_FOUND);
   2076 		return (NULL);
   2077 	}
   2078 
   2079 	if (req->rt == NULL) {
   2080 		http_request_free(req);
   2081 		http_error_response(c, HTTP_STATUS_METHOD_NOT_ALLOWED);
   2082 		return (NULL);
   2083 	}
   2084 
   2085 	return (req);
   2086 }
   2087 
   2088 static int
   2089 multipart_find_data(struct kore_buf *in, struct kore_buf *out,
   2090     size_t *olen, struct http_request *req, const void *needle, size_t len)
   2091 {
   2092 	ssize_t			ret;
   2093 	size_t			left;
   2094 	u_int8_t		*p, first, data[4096];
   2095 
   2096 	if (olen != NULL)
   2097 		*olen = 0;
   2098 
   2099 	first = *(const u_int8_t *)needle;
   2100 	for (;;) {
   2101 		if (in->offset < len) {
   2102 			ret = http_body_read(req, data, sizeof(data));
   2103 			if (ret == -1)
   2104 				return (KORE_RESULT_ERROR);
   2105 			if (ret == 0)
   2106 				return (KORE_RESULT_ERROR);
   2107 
   2108 			kore_buf_append(in, data, ret);
   2109 			continue;
   2110 		}
   2111 
   2112 		p = kore_mem_find(in->data, in->offset, &first, 1);
   2113 		if (p == NULL) {
   2114 			if (out != NULL)
   2115 				kore_buf_append(out, in->data, in->offset);
   2116 			if (olen != NULL)
   2117 				*olen += in->offset;
   2118 			kore_buf_reset(in);
   2119 			continue;
   2120 		}
   2121 
   2122 		left = in->offset - (p - in->data);
   2123 		if (left < len) {
   2124 			if (out != NULL)
   2125 				kore_buf_append(out, in->data, (p - in->data));
   2126 			if (olen != NULL)
   2127 				*olen += (p - in->data);
   2128 			memmove(in->data, p, left);
   2129 			in->offset = left;
   2130 			continue;
   2131 		}
   2132 
   2133 		if (!memcmp(p, needle, len)) {
   2134 			if (out != NULL)
   2135 				kore_buf_append(out, in->data, p - in->data);
   2136 			if (olen != NULL)
   2137 				*olen += (p - in->data);
   2138 
   2139 			in->offset = left - len;
   2140 			if (in->offset > 0)
   2141 				memmove(in->data, p + len, in->offset);
   2142 			return (KORE_RESULT_OK);
   2143 		}
   2144 
   2145 		if (out != NULL)
   2146 			kore_buf_append(out, in->data, (p - in->data) + 1);
   2147 		if (olen != NULL)
   2148 			*olen += (p - in->data) + 1;
   2149 
   2150 		in->offset = left - 1;
   2151 		if (in->offset > 0)
   2152 			memmove(in->data, p + 1, in->offset);
   2153 	}
   2154 
   2155 	return (KORE_RESULT_ERROR);
   2156 }
   2157 
   2158 static int
   2159 multipart_parse_headers(struct http_request *req, struct kore_buf *in,
   2160     struct kore_buf *hbuf, const char *boundary, const int blen)
   2161 {
   2162 	int		h, c, i;
   2163 	char		*headers[5], *args[5], *opt[5];
   2164 	char		*d, *val, *name, *fname, *string;
   2165 
   2166 	string = kore_buf_stringify(hbuf, NULL);
   2167 	h = kore_split_string(string, "\r\n", headers, 5);
   2168 	for (i = 0; i < h; i++) {
   2169 		c = kore_split_string(headers[i], ":", args, 5);
   2170 		if (c != 2)
   2171 			continue;
   2172 
   2173 		/* Ignore other headers for now. */
   2174 		if (strcasecmp(args[0], "content-disposition"))
   2175 			continue;
   2176 
   2177 		for (d = args[1]; isspace(*(unsigned char *)d); d++)
   2178 			;
   2179 
   2180 		c = kore_split_string(d, ";", opt, 5);
   2181 		if (c < 2)
   2182 			continue;
   2183 
   2184 		if (strcasecmp(opt[0], "form-data"))
   2185 			continue;
   2186 
   2187 		if ((val = strchr(opt[1], '=')) == NULL)
   2188 			continue;
   2189 		if (strlen(val) < 3)
   2190 			continue;
   2191 
   2192 		val++;
   2193 		kore_strip_chars(val, '"', &name);
   2194 
   2195 		if (opt[2] == NULL) {
   2196 			multipart_add_field(req, in, name, boundary, blen);
   2197 			kore_free(name);
   2198 			continue;
   2199 		}
   2200 
   2201 		for (d = opt[2]; isspace(*(unsigned char *)d); d++)
   2202 			;
   2203 
   2204 		if (!strncasecmp(d, "filename=", 9)) {
   2205 			if ((val = strchr(d, '=')) == NULL) {
   2206 				kore_free(name);
   2207 				continue;
   2208 			}
   2209 
   2210 			val++;
   2211 			kore_strip_chars(val, '"', &fname);
   2212 			if (strlen(fname) > 0) {
   2213 				multipart_file_add(req,
   2214 				    in, name, fname, boundary, blen);
   2215 			}
   2216 			kore_free(fname);
   2217 		}
   2218 
   2219 		kore_free(name);
   2220 	}
   2221 
   2222 	return (KORE_RESULT_OK);
   2223 }
   2224 
   2225 static void
   2226 multipart_add_field(struct http_request *req, struct kore_buf *in,
   2227     char *name, const char *boundary, const int blen)
   2228 {
   2229 	struct kore_buf		*data;
   2230 	char			*string;
   2231 
   2232 	data = kore_buf_alloc(128);
   2233 
   2234 	if (!multipart_find_data(in, data, NULL, req, boundary, blen)) {
   2235 		kore_buf_free(data);
   2236 		return;
   2237 	}
   2238 
   2239 	if (data->offset < 3) {
   2240 		kore_buf_free(data);
   2241 		return;
   2242 	}
   2243 
   2244 	data->offset -= 2;
   2245 	string = kore_buf_stringify(data, NULL);
   2246 	http_argument_add(req, name, string, 0, 0);
   2247 	kore_buf_free(data);
   2248 }
   2249 
   2250 static void
   2251 multipart_file_add(struct http_request *req, struct kore_buf *in,
   2252     const char *name, const char *fname, const char *boundary, const int blen)
   2253 {
   2254 	struct http_file	*f;
   2255 	size_t			position, len;
   2256 
   2257 	position = req->http_body_offset - in->offset;
   2258 	if (!multipart_find_data(in, NULL, &len, req, boundary, blen))
   2259 		return;
   2260 
   2261 	if (len < 3)
   2262 		return;
   2263 	len -= 2;
   2264 
   2265 	f = kore_malloc(sizeof(struct http_file));
   2266 	f->req = req;
   2267 	f->offset = 0;
   2268 	f->length = len;
   2269 	f->position = position;
   2270 	f->name = kore_strdup(name);
   2271 	f->filename = kore_strdup(fname);
   2272 
   2273 	TAILQ_INSERT_TAIL(&(req->files), f, list);
   2274 }
   2275 
   2276 static void
   2277 http_argument_add(struct http_request *req, char *name, char *value, int qs,
   2278     int decode)
   2279 {
   2280 	struct http_arg			*q;
   2281 	struct kore_route_params	*p;
   2282 
   2283 	if (decode) {
   2284 		if (!http_argument_urldecode(name))
   2285 			return;
   2286 	}
   2287 
   2288 	TAILQ_FOREACH(p, &req->rt->params, list) {
   2289 		if (qs == 1 && !(p->flags & KORE_PARAMS_QUERY_STRING))
   2290 			continue;
   2291 		if (qs == 0 && (p->flags & KORE_PARAMS_QUERY_STRING))
   2292 			continue;
   2293 
   2294 		if (p->method != req->method)
   2295 			continue;
   2296 
   2297 		if (strcmp(p->name, name))
   2298 			continue;
   2299 
   2300 		if (decode) {
   2301 			if (!http_argument_urldecode(value))
   2302 				return;
   2303 		}
   2304 
   2305 		if (!kore_validator_check(req, p->validator, value))
   2306 			break;
   2307 
   2308 		q = kore_malloc(sizeof(struct http_arg));
   2309 		q->name = kore_strdup(name);
   2310 		q->s_value = kore_strdup(value);
   2311 		TAILQ_INSERT_TAIL(&(req->arguments), q, list);
   2312 		break;
   2313 	}
   2314 }
   2315 
   2316 static int
   2317 http_body_recv(struct netbuf *nb)
   2318 {
   2319 	struct http_request	*req = (struct http_request *)nb->extra;
   2320 
   2321 	return (http_body_update(req, nb->buf, nb->s_off));
   2322 }
   2323 
   2324 static int
   2325 http_body_update(struct http_request *req, const void *data, size_t len)
   2326 {
   2327 	ssize_t			ret;
   2328 	u_int64_t		bytes_left;
   2329 
   2330 	SHA256Update(&req->hashctx, data, len);
   2331 
   2332 	if (req->http_body_fd != -1) {
   2333 		ret = write(req->http_body_fd, data, len);
   2334 		if (ret == -1 || (size_t)ret != len) {
   2335 			req->flags |= HTTP_REQUEST_DELETE;
   2336 			http_error_response(req->owner,
   2337 			    HTTP_STATUS_INTERNAL_ERROR);
   2338 			return (KORE_RESULT_ERROR);
   2339 		}
   2340 	} else if (req->http_body != NULL) {
   2341 		kore_buf_append(req->http_body, data, len);
   2342 	} else {
   2343 		req->flags |= HTTP_REQUEST_DELETE;
   2344 		http_error_response(req->owner,
   2345 		    HTTP_STATUS_INTERNAL_ERROR);
   2346 		return (KORE_RESULT_ERROR);
   2347 	}
   2348 
   2349 	req->content_length -= len;
   2350 
   2351 	if (req->content_length == 0) {
   2352 		req->owner->http_timeout = 0;
   2353 		req->owner->rnb->extra = NULL;
   2354 		http_request_wakeup(req);
   2355 		req->flags |= HTTP_REQUEST_COMPLETE;
   2356 		req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
   2357 		req->content_length = req->http_body_length;
   2358 		if (!http_body_rewind(req)) {
   2359 			req->flags |= HTTP_REQUEST_DELETE;
   2360 			http_error_response(req->owner,
   2361 			    HTTP_STATUS_INTERNAL_ERROR);
   2362 			return (KORE_RESULT_ERROR);
   2363 		}
   2364 		SHA256Final(req->http_body_digest, &req->hashctx);
   2365 	} else {
   2366 		bytes_left = req->content_length;
   2367 		net_recv_reset(req->owner,
   2368 		    MIN(bytes_left, NETBUF_SEND_PAYLOAD_MAX),
   2369 		    http_body_recv);
   2370 		req->owner->rnb->extra = req;
   2371 	}
   2372 
   2373 	if (req->rt->on_body_chunk != NULL && len > 0) {
   2374 		kore_runtime_http_body_chunk(req->rt->on_body_chunk,
   2375 		    req, data, len);
   2376 	}
   2377 
   2378 	return (KORE_RESULT_OK);
   2379 }
   2380 
   2381 static void
   2382 http_error_response(struct connection *c, int status)
   2383 {
   2384 	c->flags |= CONN_CLOSE_EMPTY;
   2385 
   2386 	switch (c->proto) {
   2387 	case CONN_PROTO_HTTP:
   2388 		http_response_normal(NULL, c, status, NULL, 0);
   2389 		break;
   2390 	default:
   2391 		fatal("http_error_response() bad proto %d", c->proto);
   2392 		/* NOTREACHED. */
   2393 	}
   2394 
   2395 	if (!net_send_flush(c))
   2396 		kore_connection_disconnect(c);
   2397 }
   2398 
   2399 static void
   2400 http_response_normal(struct http_request *req, struct connection *c,
   2401     int status, const void *d, size_t len)
   2402 {
   2403 	struct kore_buf		buf;
   2404 	struct http_cookie	*ck;
   2405 	struct http_header	*hdr;
   2406 	char			version;
   2407 	const char		*conn, *text;
   2408 	int			connection_close, send_body;
   2409 
   2410 	send_body = 1;
   2411 	text = http_status_text(status);
   2412 
   2413 	kore_buf_reset(header_buf);
   2414 
   2415 	if (req != NULL) {
   2416 		if (req->flags & HTTP_VERSION_1_0)
   2417 			version = '0';
   2418 		else
   2419 			version = '1';
   2420 	} else {
   2421 		version = '1';
   2422 	}
   2423 
   2424 	kore_buf_appendf(header_buf, "HTTP/1.%c %d %s\r\n",
   2425 	    version, status, text);
   2426 
   2427 	if (status == 100) {
   2428 		kore_buf_append(header_buf, "\r\n", 2);
   2429 		net_send_queue(c, header_buf->data, header_buf->offset);
   2430 		return;
   2431 	}
   2432 
   2433 	kore_buf_append(header_buf, http_version, http_version_len);
   2434 
   2435 	if ((c->flags & CONN_CLOSE_EMPTY) ||
   2436 	    (req != NULL && (req->flags & HTTP_VERSION_1_0))) {
   2437 		connection_close = 1;
   2438 	} else {
   2439 		connection_close = 0;
   2440 	}
   2441 
   2442 	if (connection_close == 0 && req != NULL) {
   2443 		if (http_request_header(req, "connection", &conn)) {
   2444 			if ((*conn == 'c' || *conn == 'C') &&
   2445 			    !strcasecmp(conn, "close")) {
   2446 				connection_close = 1;
   2447 			}
   2448 		}
   2449 	}
   2450 
   2451 	kore_buf_init(&buf, 1024);
   2452 
   2453 	/* Note that req CAN be NULL. */
   2454 	if (req == NULL || req->owner->proto != CONN_PROTO_WEBSOCKET) {
   2455 		if (http_keepalive_time && connection_close == 0) {
   2456 			kore_buf_appendf(header_buf,
   2457 			    "connection: keep-alive\r\n");
   2458 			kore_buf_appendf(header_buf,
   2459 			    "keep-alive: timeout=%d\r\n", http_keepalive_time);
   2460 		} else {
   2461 			c->flags |= CONN_CLOSE_EMPTY;
   2462 			kore_buf_appendf(header_buf, "connection: close\r\n");
   2463 		}
   2464 	}
   2465 
   2466 	if (c->tls && http_hsts_enable) {
   2467 		kore_buf_appendf(header_buf, "strict-transport-security: ");
   2468 		kore_buf_appendf(header_buf,
   2469 		    "max-age=%" PRIu64 "; includeSubDomains\r\n",
   2470 		    http_hsts_enable);
   2471 	}
   2472 
   2473 	if (http_pretty_error && d == NULL && status >= 400) {
   2474 		kore_buf_appendf(&buf, pretty_error_fmt,
   2475 		    status, text, status, text);
   2476 
   2477 		d = buf.data;
   2478 		len = buf.offset;
   2479 	}
   2480 
   2481 	if (req != NULL) {
   2482 		TAILQ_FOREACH(ck, &(req->resp_cookies), list)
   2483 			http_write_response_cookie(ck);
   2484 
   2485 		TAILQ_FOREACH(hdr, &(req->resp_headers), list) {
   2486 			kore_buf_appendf(header_buf, "%s: %s\r\n",
   2487 			    hdr->header, hdr->value);
   2488 		}
   2489 
   2490 		if (status != 204 && status >= 200 &&
   2491 		    !(req->flags & HTTP_REQUEST_NO_CONTENT_LENGTH)) {
   2492 			kore_buf_appendf(header_buf,
   2493 			    "content-length: %zu\r\n", len);
   2494 		}
   2495 	} else {
   2496 		if (status != 204 && status >= 200) {
   2497 			kore_buf_appendf(header_buf,
   2498 			    "content-length: %zu\r\n", len);
   2499 		}
   2500 	}
   2501 
   2502 	kore_buf_append(header_buf, "\r\n", 2);
   2503 	net_send_queue(c, header_buf->data, header_buf->offset);
   2504 
   2505 	if (req != NULL && req->method == HTTP_METHOD_HEAD)
   2506 		send_body = 0;
   2507 
   2508 	if (d != NULL && send_body)
   2509 		net_send_queue(c, d, len);
   2510 
   2511 	if (!(c->flags & CONN_CLOSE_EMPTY) && !(c->flags & CONN_IS_BUSY))
   2512 		http_start_recv(c);
   2513 
   2514 	if (req != NULL)
   2515 		req->content_length = len;
   2516 
   2517 	kore_buf_cleanup(&buf);
   2518 }
   2519 
   2520 static void
   2521 http_write_response_cookie(struct http_cookie *ck)
   2522 {
   2523 	struct tm		tm;
   2524 	char			expires[HTTP_DATE_MAXSIZE];
   2525 
   2526 	kore_buf_reset(ckhdr_buf);
   2527 	kore_buf_appendf(ckhdr_buf, "%s=%s", ck->name, ck->value);
   2528 
   2529 	if (ck->path != NULL)
   2530 		kore_buf_appendf(ckhdr_buf, "; Path=%s", ck->path);
   2531 	if (ck->domain != NULL)
   2532 		kore_buf_appendf(ckhdr_buf, "; Domain=%s", ck->domain);
   2533 
   2534 	if (ck->expires > 0) {
   2535 		if (gmtime_r(&ck->expires, &tm) == NULL) {
   2536 			kore_log(LOG_ERR, "gmtime_r(): %s", errno_s);
   2537 			return;
   2538 		}
   2539 
   2540 		if (strftime(expires, sizeof(expires),
   2541 		    "%a, %d %b %y %H:%M:%S GMT", &tm) == 0) {
   2542 			kore_log(LOG_ERR, "strftime(): %s", errno_s);
   2543 			return;
   2544 		}
   2545 
   2546 		kore_buf_appendf(ckhdr_buf, "; Expires=%s", expires);
   2547 	}
   2548 
   2549 	if (ck->maxage > 0)
   2550 		kore_buf_appendf(ckhdr_buf, "; Max-Age=%u", ck->maxage);
   2551 
   2552 	if (ck->flags & HTTP_COOKIE_HTTPONLY)
   2553 		kore_buf_appendf(ckhdr_buf, "; HttpOnly");
   2554 	if (ck->flags & HTTP_COOKIE_SECURE)
   2555 		kore_buf_appendf(ckhdr_buf, "; Secure");
   2556 
   2557 	kore_buf_appendf(header_buf, "set-cookie: %s\r\n",
   2558 	    kore_buf_stringify(ckhdr_buf, NULL));
   2559 }
   2560 
   2561 static int
   2562 http_data_convert(void *data, void **out, void *nout, int type)
   2563 {
   2564 	switch (type) {
   2565 	case HTTP_ARG_TYPE_RAW:
   2566 	case HTTP_ARG_TYPE_STRING:
   2567 		*out = data;
   2568 		return (KORE_RESULT_OK);
   2569 	case HTTP_ARG_TYPE_BYTE:
   2570 		COPY_ARG_TYPE(*(u_int8_t *)data, u_int8_t);
   2571 		return (KORE_RESULT_OK);
   2572 	case HTTP_ARG_TYPE_INT16:
   2573 		COPY_AS_INTTYPE(SHRT_MIN, SHRT_MAX, int16_t);
   2574 		return (KORE_RESULT_OK);
   2575 	case HTTP_ARG_TYPE_UINT16:
   2576 		COPY_AS_INTTYPE(0, USHRT_MAX, u_int16_t);
   2577 		return (KORE_RESULT_OK);
   2578 	case HTTP_ARG_TYPE_INT32:
   2579 		COPY_AS_INTTYPE(INT_MIN, INT_MAX, int32_t);
   2580 		return (KORE_RESULT_OK);
   2581 	case HTTP_ARG_TYPE_UINT32:
   2582 		COPY_AS_INTTYPE(0, UINT_MAX, u_int32_t);
   2583 		return (KORE_RESULT_OK);
   2584 	case HTTP_ARG_TYPE_INT64:
   2585 		COPY_AS_INTTYPE_64(int64_t, 1);
   2586 		return (KORE_RESULT_OK);
   2587 	case HTTP_ARG_TYPE_UINT64:
   2588 		COPY_AS_INTTYPE_64(u_int64_t, 0);
   2589 		return (KORE_RESULT_OK);
   2590 	case HTTP_ARG_TYPE_FLOAT:
   2591 		COPY_ARG_DOUBLE(-FLT_MAX, FLT_MAX, float);
   2592 		return (KORE_RESULT_OK);
   2593 	case HTTP_ARG_TYPE_DOUBLE:
   2594 		COPY_ARG_DOUBLE(-DBL_MAX, DBL_MAX, double);
   2595 		return (KORE_RESULT_OK);
   2596 	default:
   2597 		break;
   2598 	}
   2599 
   2600 	return (KORE_RESULT_ERROR);
   2601 }