kore

Kore is a web application platform for writing scalable, concurrent web based processes in C or Python.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

http.c (59581B)



      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, int url)
   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 (url) {
   1050 			if (v <= 0x1f || v == 0x7f)
   1051 				return (KORE_RESULT_ERROR);
   1052 		} else {
   1053 			if ((v <= 0x1f || v == 0x7f) &&
   1054 			    (v != '\n' && v != '\r' && v != '\t'))
   1055 				return (KORE_RESULT_ERROR);
   1056 		}
   1057 
   1058 		*in++ = (char)v;
   1059 		p += 3;
   1060 	}
   1061 
   1062 	*in = '\0';
   1063 	return (KORE_RESULT_OK);
   1064 }
   1065 
   1066 struct http_file *
   1067 http_file_lookup(struct http_request *req, const char *name)
   1068 {
   1069 	struct http_file	*f;
   1070 
   1071 	TAILQ_FOREACH(f, &(req->files), list) {
   1072 		if (!strcmp(f->name, name))
   1073 			return (f);
   1074 	}
   1075 
   1076 	return (NULL);
   1077 }
   1078 
   1079 ssize_t
   1080 http_file_read(struct http_file *file, void *buf, size_t len)
   1081 {
   1082 	ssize_t		ret;
   1083 	size_t		toread, off;
   1084 
   1085 	if (file->length < file->offset)
   1086 		return (-1);
   1087 	if ((file->offset + len) < file->offset)
   1088 		return (-1);
   1089 	if ((file->position + file->offset) < file->position)
   1090 		return (-1);
   1091 
   1092 	off = file->position + file->offset;
   1093 	toread = MIN(len, (file->length - file->offset));
   1094 	if (toread == 0)
   1095 		return (0);
   1096 
   1097 	if (file->req->http_body_fd != -1) {
   1098 		if (lseek(file->req->http_body_fd, off, SEEK_SET) == -1) {
   1099 			kore_log(LOG_ERR, "http_file_read: lseek(%s): %s",
   1100 			    file->req->http_body_path, errno_s);
   1101 			return (-1);
   1102 		}
   1103 
   1104 		for (;;) {
   1105 			ret = read(file->req->http_body_fd, buf, toread);
   1106 			if (ret == -1) {
   1107 				if (errno == EINTR)
   1108 					continue;
   1109 				kore_log(LOG_ERR, "failed to read %s: %s",
   1110 				    file->req->http_body_path, errno_s);
   1111 				return (-1);
   1112 			}
   1113 			if (ret == 0)
   1114 				return (0);
   1115 			break;
   1116 		}
   1117 	} else if (file->req->http_body != NULL) {
   1118 		if (off > file->req->http_body->length)
   1119 			return (0);
   1120 		memcpy(buf, file->req->http_body->data + off, toread);
   1121 		ret = toread;
   1122 	} else {
   1123 		kore_log(LOG_ERR, "http_file_read: called without body");
   1124 		return (-1);
   1125 	}
   1126 
   1127 	file->offset += (size_t)ret;
   1128 	return (ret);
   1129 }
   1130 
   1131 void
   1132 http_file_rewind(struct http_file *file)
   1133 {
   1134 	file->offset = 0;
   1135 }
   1136 
   1137 void
   1138 http_response_cookie(struct http_request *req, const char *name,
   1139     const char *val, const char *path, time_t expires, u_int32_t maxage,
   1140     struct http_cookie **out)
   1141 {
   1142 	char			*p;
   1143 	struct http_cookie	*ck;
   1144 
   1145 	if (name == NULL || val == NULL)
   1146 		fatal("http_response_cookie: invalid parameters");
   1147 
   1148 	ck = kore_pool_get(&http_cookie_pool);
   1149 
   1150 	ck->maxage = maxage;
   1151 	ck->expires = expires;
   1152 	ck->name = kore_strdup(name);
   1153 	ck->value = kore_strdup(val);
   1154 	ck->domain = kore_strdup(req->host);
   1155 	ck->flags = HTTP_COOKIE_HTTPONLY | HTTP_COOKIE_SECURE;
   1156 
   1157 	if ((p = strrchr(ck->domain, ':')) != NULL)
   1158 		*p = '\0';
   1159 
   1160 	if (path != NULL)
   1161 		ck->path = kore_strdup(path);
   1162 	else
   1163 		ck->path = NULL;
   1164 
   1165 	TAILQ_INSERT_TAIL(&(req->resp_cookies), ck, list);
   1166 
   1167 	if (out != NULL)
   1168 		*out = ck;
   1169 }
   1170 
   1171 void
   1172 http_populate_cookies(struct http_request *req)
   1173 {
   1174 	struct http_cookie	*ck;
   1175 	const char		*hdr;
   1176 	int			 i, v, n;
   1177 	char			*c, *header, *pair[3];
   1178 	char			*cookies[HTTP_MAX_COOKIES];
   1179 
   1180 	if (!http_request_header(req, "cookie", &hdr))
   1181 		return;
   1182 
   1183 	header = kore_strdup(hdr);
   1184 	v = kore_split_string(header, ";", cookies, HTTP_MAX_COOKIES);
   1185 	for (i = 0; i < v; i++) {
   1186 		for (c = cookies[i]; isspace(*(unsigned char *)c); c++)
   1187 			;
   1188 
   1189 		n = kore_split_string(c, "=", pair, 3);
   1190 		if (n != 2)
   1191 			continue;
   1192 
   1193 		ck = kore_pool_get(&http_cookie_pool);
   1194 		ck->name = kore_strdup(pair[0]);
   1195 		ck->value = kore_strdup(pair[1]);
   1196 		TAILQ_INSERT_TAIL(&(req->req_cookies), ck, list);
   1197 	}
   1198 
   1199 	kore_free(header);
   1200 }
   1201 
   1202 void
   1203 http_populate_post(struct http_request *req)
   1204 {
   1205 	ssize_t			ret;
   1206 	int			i, v;
   1207 	struct kore_buf		*body;
   1208 	char			data[BUFSIZ];
   1209 	char			*args[HTTP_MAX_QUERY_ARGS], *val[3], *string;
   1210 
   1211 	if (req->method != HTTP_METHOD_POST)
   1212 		return;
   1213 
   1214 	if (req->http_body != NULL) {
   1215 		body = NULL;
   1216 		req->http_body->offset = req->content_length;
   1217 		string = kore_buf_stringify(req->http_body, NULL);
   1218 		req->http_body_length = 0;
   1219 		req->http_body_offset = 0;
   1220 	} else {
   1221 		body = kore_buf_alloc(128);
   1222 		for (;;) {
   1223 			ret = http_body_read(req, data, sizeof(data));
   1224 			if (ret == -1)
   1225 				goto out;
   1226 			if (ret == 0)
   1227 				break;
   1228 			kore_buf_append(body, data, ret);
   1229 		}
   1230 		string = kore_buf_stringify(body, NULL);
   1231 	}
   1232 
   1233 	v = kore_split_string(string, "&", args, HTTP_MAX_QUERY_ARGS);
   1234 	for (i = 0; i < v; i++) {
   1235 		kore_split_string(args[i], "=", val, 3);
   1236 		if (val[0] != NULL && val[1] != NULL)
   1237 			http_argument_add(req, val[0], val[1], 0, 1);
   1238 	}
   1239 
   1240 out:
   1241 	if (body != NULL)
   1242 		kore_buf_free(body);
   1243 }
   1244 
   1245 void
   1246 http_populate_qs(struct http_request *req)
   1247 {
   1248 	int		i, v;
   1249 	char		*query, *args[HTTP_MAX_QUERY_ARGS], *val[3];
   1250 
   1251 	if (req->query_string == NULL)
   1252 		return;
   1253 
   1254 	query = kore_strdup(req->query_string);
   1255 	v = kore_split_string(query, "&", args, HTTP_MAX_QUERY_ARGS);
   1256 	for (i = 0; i < v; i++) {
   1257 		kore_split_string(args[i], "=", val, 3);
   1258 		if (val[0] != NULL && val[1] != NULL)
   1259 			http_argument_add(req, val[0], val[1], 1, 1);
   1260 	}
   1261 
   1262 	kore_free(query);
   1263 }
   1264 
   1265 void
   1266 http_populate_multipart_form(struct http_request *req)
   1267 {
   1268 	const char		*hdr;
   1269 	int			h, blen;
   1270 	struct kore_buf		in, out;
   1271 	char			*type, *val, *args[3];
   1272 	char			boundary[HTTP_BOUNDARY_MAX];
   1273 
   1274 	if (req->method != HTTP_METHOD_POST)
   1275 		return;
   1276 
   1277 	if (!http_request_header(req, "content-type", &hdr))
   1278 		return;
   1279 
   1280 	kore_buf_init(&in, 128);
   1281 	kore_buf_init(&out, 128);
   1282 
   1283 	type = kore_strdup(hdr);
   1284 	h = kore_split_string(type, ";", args, 3);
   1285 	if (h != 2)
   1286 		goto cleanup;
   1287 
   1288 	if (strcasecmp(args[0], "multipart/form-data"))
   1289 		goto cleanup;
   1290 
   1291 	if ((val = strchr(args[1], '=')) == NULL)
   1292 		goto cleanup;
   1293 
   1294 	val++;
   1295 	blen = snprintf(boundary, sizeof(boundary), "--%s", val);
   1296 	if (blen == -1 || (size_t)blen >= sizeof(boundary))
   1297 		goto cleanup;
   1298 
   1299 	if (!multipart_find_data(&in, NULL, NULL, req, boundary, blen))
   1300 		goto cleanup;
   1301 
   1302 	for (;;) {
   1303 		if (!multipart_find_data(&in, NULL, NULL, req, "\r\n", 2))
   1304 			break;
   1305 		if (in.offset < 4 && req->http_body_length == 0)
   1306 			break;
   1307 		if (!multipart_find_data(&in, &out, NULL, req, "\r\n\r\n", 4))
   1308 			break;
   1309 		if (!multipart_parse_headers(req, &in, &out, boundary, blen))
   1310 			break;
   1311 
   1312 		kore_buf_reset(&out);
   1313 	}
   1314 
   1315 cleanup:
   1316 	kore_free(type);
   1317 	kore_buf_cleanup(&in);
   1318 	kore_buf_cleanup(&out);
   1319 }
   1320 
   1321 int
   1322 http_body_rewind(struct http_request *req)
   1323 {
   1324 	if (req->http_body_fd != -1) {
   1325 		if (lseek(req->http_body_fd, 0, SEEK_SET) == -1) {
   1326 			kore_log(LOG_ERR, "lseek(%s) failed: %s",
   1327 			    req->http_body_path, errno_s);
   1328 			return (KORE_RESULT_ERROR);
   1329 		}
   1330 	} else if (req->http_body != NULL) {
   1331 		kore_buf_reset(req->http_body);
   1332 	}
   1333 
   1334 	req->http_body_offset = 0;
   1335 	req->http_body_length = req->content_length;
   1336 
   1337 	return (KORE_RESULT_OK);
   1338 }
   1339 
   1340 int
   1341 http_body_digest(struct http_request *req, char *out, size_t len)
   1342 {
   1343 	size_t		idx;
   1344 	int		slen;
   1345 
   1346 	if (len != HTTP_BODY_DIGEST_STRLEN) {
   1347 		fatal("http_body_digest: bad len:%zu wanted:%u",
   1348 		    len, HTTP_BODY_DIGEST_STRLEN);
   1349 	}
   1350 
   1351 	if (!(req->flags & HTTP_REQUEST_COMPLETE))
   1352 		return (KORE_RESULT_ERROR);
   1353 
   1354 	for (idx = 0; idx < sizeof(req->http_body_digest); idx++) {
   1355 		slen = snprintf(out + (idx * 2), len - (idx * 2), "%02x",
   1356 		    req->http_body_digest[idx]);
   1357 		if (slen == -1 || (size_t)slen >= len)
   1358 			fatal("failed to create hex string");
   1359 	}
   1360 
   1361 	return (KORE_RESULT_OK);
   1362 }
   1363 
   1364 ssize_t
   1365 http_body_read(struct http_request *req, void *out, size_t len)
   1366 {
   1367 	ssize_t		ret;
   1368 	size_t		toread;
   1369 
   1370 	toread = MIN(req->http_body_length, len);
   1371 	if (toread == 0)
   1372 		return (0);
   1373 
   1374 	if (req->http_body_fd != -1) {
   1375 		for (;;) {
   1376 			ret = read(req->http_body_fd, out, toread);
   1377 			if (ret == -1) {
   1378 				if (errno == EINTR)
   1379 					continue;
   1380 				kore_log(LOG_ERR, "failed to read %s: %s",
   1381 				    req->http_body_path, errno_s);
   1382 				return (-1);
   1383 			}
   1384 			if (ret == 0)
   1385 				return (0);
   1386 			break;
   1387 		}
   1388 	} else if (req->http_body != NULL) {
   1389 		memcpy(out,
   1390 		    (req->http_body->data + req->http_body->offset), toread);
   1391 		req->http_body->offset += toread;
   1392 		ret = toread;
   1393 	} else {
   1394 		kore_log(LOG_ERR, "http_body_read: called without body");
   1395 		return (-1);
   1396 	}
   1397 
   1398 	req->http_body_length -= (size_t)ret;
   1399 	req->http_body_offset += (size_t)ret;
   1400 
   1401 	return (ret);
   1402 }
   1403 
   1404 int
   1405 http_state_run(struct http_state *states, u_int8_t elm,
   1406     struct http_request *req)
   1407 {
   1408 	int		r, done;
   1409 
   1410 	done = 0;
   1411 
   1412 	while (!done) {
   1413 		if (req->fsm_state >= elm) {
   1414 			fatal("http_state_run: fsm_state > elm (%d/%d)",
   1415 			    req->fsm_state, elm);
   1416 		}
   1417 
   1418 		r = states[req->fsm_state].cb(req);
   1419 		switch (r) {
   1420 		case HTTP_STATE_ERROR:
   1421 			return (KORE_RESULT_OK);
   1422 		case HTTP_STATE_RETRY:
   1423 			return (KORE_RESULT_RETRY);
   1424 		case HTTP_STATE_CONTINUE:
   1425 			break;
   1426 		case HTTP_STATE_COMPLETE:
   1427 			done = 1;
   1428 			break;
   1429 		default:
   1430 			fatal("http_state_run: unknown return value %d", r);
   1431 		}
   1432 	}
   1433 
   1434 	req->fsm_state = 0;
   1435 
   1436 	return (KORE_RESULT_OK);
   1437 }
   1438 
   1439 int
   1440 http_state_exists(struct http_request *req)
   1441 {
   1442 	return (req->hdlr_extra != NULL);
   1443 }
   1444 
   1445 void *
   1446 http_state_create(struct http_request *req, size_t len)
   1447 {
   1448 	if (req->hdlr_extra != NULL)
   1449 		fatal("http_state_create: state already exists");
   1450 
   1451 	req->state_len = len;
   1452 	req->hdlr_extra = kore_calloc(1, len);
   1453 
   1454 	return (req->hdlr_extra);
   1455 }
   1456 
   1457 void *
   1458 http_state_get(struct http_request *req)
   1459 {
   1460 	return (req->hdlr_extra);
   1461 }
   1462 
   1463 void
   1464 http_state_cleanup(struct http_request *req)
   1465 {
   1466 	kore_free(req->hdlr_extra);
   1467 	req->hdlr_extra = NULL;
   1468 }
   1469 
   1470 void
   1471 http_start_recv(struct connection *c)
   1472 {
   1473 	c->http_start = kore_time_ms();
   1474 	c->http_timeout = http_header_timeout * 1000;
   1475 	net_recv_reset(c, http_header_max, http_header_recv);
   1476 }
   1477 
   1478 void
   1479 http_runlock_init(struct http_runlock *lock)
   1480 {
   1481 	lock->owner = NULL;
   1482 	LIST_INIT(&lock->queue);
   1483 }
   1484 
   1485 int
   1486 http_runlock_acquire(struct http_runlock *lock, struct http_request *req)
   1487 {
   1488 	if (lock->owner != NULL) {
   1489 		if (req->runlock != NULL)
   1490 			fatal("%s: request already waiting on lock", __func__);
   1491 
   1492 		req->runlock = kore_pool_get(&http_rlq_pool);
   1493 		req->runlock->req = req;
   1494 		LIST_INSERT_HEAD(&lock->queue, req->runlock, list);
   1495 
   1496 		http_request_sleep(req);
   1497 		return (KORE_RESULT_ERROR);
   1498 	}
   1499 
   1500 	lock->owner = req;
   1501 
   1502 	return (KORE_RESULT_OK);
   1503 }
   1504 
   1505 void
   1506 http_runlock_release(struct http_runlock *lock, struct http_request *req)
   1507 {
   1508 	struct http_runlock_queue	*next;
   1509 	struct http_request		*nextreq;
   1510 
   1511 	if (lock->owner != req)
   1512 		fatal("%s: calling request != owner of runlock", __func__);
   1513 
   1514 	lock->owner = NULL;
   1515 
   1516 	if ((next = LIST_FIRST(&lock->queue)) != NULL) {
   1517 		LIST_REMOVE(next, list);
   1518 
   1519 		nextreq = next->req;
   1520 		nextreq->runlock = NULL;
   1521 
   1522 		http_request_wakeup(nextreq);
   1523 		kore_pool_put(&http_rlq_pool, next);
   1524 	}
   1525 }
   1526 
   1527 int
   1528 http_redirect_add(struct kore_domain *dom, const char *path, int status,
   1529     const char *target)
   1530 {
   1531 	struct http_redirect	*rdr;
   1532 
   1533 	rdr = kore_calloc(1, sizeof(*rdr));
   1534 
   1535 	if (regcomp(&(rdr->rctx), path, REG_EXTENDED)) {
   1536 		kore_free(rdr);
   1537 		return (KORE_RESULT_ERROR);
   1538 	}
   1539 
   1540 	rdr->status = status;
   1541 
   1542 	if (target != NULL)
   1543 		rdr->target = kore_strdup(target);
   1544 	else
   1545 		rdr->target = NULL;
   1546 
   1547 	TAILQ_INSERT_TAIL(&dom->redirects, rdr, list);
   1548 
   1549 	return (KORE_RESULT_OK);
   1550 }
   1551 
   1552 const char *
   1553 http_status_text(int status)
   1554 {
   1555 	const char	*r;
   1556 
   1557 	switch (status) {
   1558 	case HTTP_STATUS_CONTINUE:
   1559 		r = "Continue";
   1560 		break;
   1561 	case HTTP_STATUS_SWITCHING_PROTOCOLS:
   1562 		r = "Switching Protocols";
   1563 		break;
   1564 	case HTTP_STATUS_OK:
   1565 		r = "OK";
   1566 		break;
   1567 	case HTTP_STATUS_CREATED:
   1568 		r = "Created";
   1569 		break;
   1570 	case HTTP_STATUS_ACCEPTED:
   1571 		r = "Accepted";
   1572 		break;
   1573 	case HTTP_STATUS_NON_AUTHORITATIVE:
   1574 		r = "Non-Authoritative Information";
   1575 		break;
   1576 	case HTTP_STATUS_NO_CONTENT:
   1577 		r = "No Content";
   1578 		break;
   1579 	case HTTP_STATUS_RESET_CONTENT:
   1580 		r = "Reset Content";
   1581 		break;
   1582 	case HTTP_STATUS_PARTIAL_CONTENT:
   1583 		r = "Partial Content";
   1584 		break;
   1585 	case HTTP_STATUS_MULTIPLE_CHOICES:
   1586 		r = "Multiple Choices";
   1587 		break;
   1588 	case HTTP_STATUS_MOVED_PERMANENTLY:
   1589 		r = "Moved Permanently";
   1590 		break;
   1591 	case HTTP_STATUS_FOUND:
   1592 		r = "Found";
   1593 		break;
   1594 	case HTTP_STATUS_SEE_OTHER:
   1595 		r = "See Other";
   1596 		break;
   1597 	case HTTP_STATUS_NOT_MODIFIED:
   1598 		r = "Not Modified";
   1599 		break;
   1600 	case HTTP_STATUS_USE_PROXY:
   1601 		r = "Use Proxy";
   1602 		break;
   1603 	case HTTP_STATUS_TEMPORARY_REDIRECT:
   1604 		r = "Temporary Redirect";
   1605 		break;
   1606 	case HTTP_STATUS_BAD_REQUEST:
   1607 		r = "Bad Request";
   1608 		break;
   1609 	case HTTP_STATUS_UNAUTHORIZED:
   1610 		r = "Unauthorized";
   1611 		break;
   1612 	case HTTP_STATUS_PAYMENT_REQUIRED:
   1613 		r = "Payment Required";
   1614 		break;
   1615 	case HTTP_STATUS_FORBIDDEN:
   1616 		r = "Forbidden";
   1617 		break;
   1618 	case HTTP_STATUS_NOT_FOUND:
   1619 		r = "Not Found";
   1620 		break;
   1621 	case HTTP_STATUS_METHOD_NOT_ALLOWED:
   1622 		r = "Method Not Allowed";
   1623 		break;
   1624 	case HTTP_STATUS_NOT_ACCEPTABLE:
   1625 		r = "Not Acceptable";
   1626 		break;
   1627 	case HTTP_STATUS_PROXY_AUTH_REQUIRED:
   1628 		r = "Proxy Authentication Required";
   1629 		break;
   1630 	case HTTP_STATUS_REQUEST_TIMEOUT:
   1631 		r = "Request Time-out";
   1632 		break;
   1633 	case HTTP_STATUS_CONFLICT:
   1634 		r = "Conflict";
   1635 		break;
   1636 	case HTTP_STATUS_GONE:
   1637 		r = "Gone";
   1638 		break;
   1639 	case HTTP_STATUS_LENGTH_REQUIRED:
   1640 		r = "Length Required";
   1641 		break;
   1642 	case HTTP_STATUS_PRECONDITION_FAILED:
   1643 		r = "Precondition Failed";
   1644 		break;
   1645 	case HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE:
   1646 		r = "Request Entity Too Large";
   1647 		break;
   1648 	case HTTP_STATUS_REQUEST_URI_TOO_LARGE:
   1649 		r = "Request-URI Too Large";
   1650 		break;
   1651 	case HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE:
   1652 		r = "Unsupported Media Type";
   1653 		break;
   1654 	case HTTP_STATUS_REQUEST_RANGE_INVALID:
   1655 		r = "Requested range not satisfiable";
   1656 		break;
   1657 	case HTTP_STATUS_EXPECTATION_FAILED:
   1658 		r = "Expectation Failed";
   1659 		break;
   1660 	case HTTP_STATUS_MISDIRECTED_REQUEST:
   1661 		r = "Misdirected Request";
   1662 		break;
   1663 	case HTTP_STATUS_INTERNAL_ERROR:
   1664 		r = "Internal Server Error";
   1665 		break;
   1666 	case HTTP_STATUS_NOT_IMPLEMENTED:
   1667 		r = "Not Implemented";
   1668 		break;
   1669 	case HTTP_STATUS_BAD_GATEWAY:
   1670 		r = "Bad Gateway";
   1671 		break;
   1672 	case HTTP_STATUS_SERVICE_UNAVAILABLE:
   1673 		r = "Service Unavailable";
   1674 		break;
   1675 	case HTTP_STATUS_GATEWAY_TIMEOUT:
   1676 		r = "Gateway Time-out";
   1677 		break;
   1678 	case HTTP_STATUS_BAD_VERSION:
   1679 		r = "HTTP Version not supported";
   1680 		break;
   1681 	default:
   1682 		r = "";
   1683 		break;
   1684 	}
   1685 
   1686 	return (r);
   1687 }
   1688 
   1689 const char *
   1690 http_method_text(int method)
   1691 {
   1692 	char		*r;
   1693 
   1694 	switch(method) {
   1695 	case HTTP_METHOD_GET:
   1696 		r = "GET";
   1697 		break;
   1698 	case HTTP_METHOD_POST:
   1699 		r = "POST";
   1700 		break;
   1701 	case HTTP_METHOD_PUT:
   1702 		r = "PUT";
   1703 		break;
   1704 	case HTTP_METHOD_DELETE:
   1705 		r = "DELETE";
   1706 		break;
   1707 	case HTTP_METHOD_HEAD:
   1708 		r = "HEAD";
   1709 		break;
   1710 	case HTTP_METHOD_OPTIONS:
   1711 		r = "OPTIONS";
   1712 		break;
   1713 	case HTTP_METHOD_PATCH:
   1714 		r = "PATCH";
   1715 		break;
   1716 	default:
   1717 		r = "";
   1718 		break;
   1719 	}
   1720 
   1721 	return (r);
   1722 }
   1723 
   1724 int
   1725 http_method_value(const char *method)
   1726 {
   1727 	if (!strcasecmp(method, "GET"))
   1728 		return (HTTP_METHOD_GET);
   1729 
   1730 	if (!strcasecmp(method, "POST"))
   1731 		return (HTTP_METHOD_POST);
   1732 
   1733 	if (!strcasecmp(method, "PUT"))
   1734 		return (HTTP_METHOD_PUT);
   1735 
   1736 	if (!strcasecmp(method, "DELETE"))
   1737 		return (HTTP_METHOD_DELETE);
   1738 
   1739 	if (!strcasecmp(method, "HEAD"))
   1740 		return (HTTP_METHOD_HEAD);
   1741 
   1742 	if (!strcasecmp(method, "OPTIONS"))
   1743 		return (HTTP_METHOD_OPTIONS);
   1744 
   1745 	if (!strcasecmp(method, "PATCH"))
   1746 		return (HTTP_METHOD_PATCH);
   1747 
   1748 	return (0);
   1749 }
   1750 
   1751 int
   1752 http_media_register(const char *ext, const char *type)
   1753 {
   1754 	struct http_media_type	*media;
   1755 
   1756 	LIST_FOREACH(media, &http_media_types, list) {
   1757 		if (!strcasecmp(media->ext, ext))
   1758 			return (KORE_RESULT_ERROR);
   1759 	}
   1760 
   1761 	media = kore_calloc(1, sizeof(*media));
   1762 	media->ext = kore_strdup(ext);
   1763 	media->type = kore_strdup(type);
   1764 
   1765 	LIST_INSERT_HEAD(&http_media_types, media, list);
   1766 
   1767 	return (KORE_RESULT_OK);
   1768 }
   1769 
   1770 const char *
   1771 http_media_type(const char *path)
   1772 {
   1773 	const char		*p;
   1774 	struct http_media_type	*media;
   1775 
   1776 	if ((p = strrchr(path, '.')) == NULL)
   1777 		return (NULL);
   1778 
   1779 	p++;
   1780 	if (*p == '\0')
   1781 		return (NULL);
   1782 
   1783 	LIST_FOREACH(media, &http_media_types, list) {
   1784 		if (!strcasecmp(media->ext, p))
   1785 			return (media->type);
   1786 	}
   1787 
   1788 	return (NULL);
   1789 }
   1790 
   1791 char *
   1792 http_validate_header(char *header)
   1793 {
   1794 	u_int8_t	idx;
   1795 	char		*p, *value;
   1796 
   1797 	for (p = header; *p != '\0'; p++) {
   1798 		idx = *p;
   1799 		if (idx > HTTP_MAP_LIMIT)
   1800 			return (NULL);
   1801 
   1802 		if (*p == ':') {
   1803 			*(p)++ = '\0';
   1804 			break;
   1805 		}
   1806 
   1807 		if (*p >= 'A' && *p <= 'Z')
   1808 			*p += 32;
   1809 
   1810 		if (http_token[idx] == 0x00)
   1811 			return (NULL);
   1812 	}
   1813 
   1814 	while (isspace(*(unsigned char *)p))
   1815 		p++;
   1816 
   1817 	if (*p == '\0')
   1818 		return (NULL);
   1819 
   1820 	value = p;
   1821 	while (*p != '\0') {
   1822 		idx = *p;
   1823 		if (idx > HTTP_MAP_LIMIT)
   1824 			return (NULL);
   1825 		if (http_field_content[idx] == 0x00)
   1826 			return (NULL);
   1827 		p++;
   1828 	}
   1829 
   1830 	return (value);
   1831 }
   1832 
   1833 static int
   1834 http_release_buffer(struct netbuf *nb)
   1835 {
   1836 	kore_buf_free(nb->extra);
   1837 
   1838 	return (KORE_RESULT_OK);
   1839 }
   1840 
   1841 static int
   1842 http_check_redirect(struct http_request *req, struct kore_domain *dom)
   1843 {
   1844 	int			idx;
   1845 	struct http_redirect	*rdr;
   1846 	const char		*uri;
   1847 	char			key[4];
   1848 	struct kore_buf		location;
   1849 
   1850 	TAILQ_FOREACH(rdr, &dom->redirects, list) {
   1851 		if (!regexec(&(rdr->rctx), req->path,
   1852 		    HTTP_CAPTURE_GROUPS, req->cgroups, 0))
   1853 			break;
   1854 	}
   1855 
   1856 	if (rdr == NULL)
   1857 		return (KORE_RESULT_ERROR);
   1858 
   1859 	uri = NULL;
   1860 	kore_buf_init(&location, 128);
   1861 
   1862 	if (rdr->target) {
   1863 		kore_buf_appendf(&location, "%s", rdr->target);
   1864 
   1865 		if (req->query_string != NULL) {
   1866 			kore_buf_replace_string(&location, "$qs",
   1867 			    req->query_string, strlen(req->query_string));
   1868 		}
   1869 
   1870 		/* Starts at 1 to skip the full path. */
   1871 		for (idx = 1; idx < HTTP_CAPTURE_GROUPS - 1; idx++) {
   1872 			if (req->cgroups[idx].rm_so == -1 ||
   1873 			    req->cgroups[idx].rm_eo == -1)
   1874 				break;
   1875 
   1876 			(void)snprintf(key, sizeof(key), "$%d", idx);
   1877 
   1878 			kore_buf_replace_string(&location, key,
   1879 			    req->path + req->cgroups[idx].rm_so,
   1880 			    req->cgroups[idx].rm_eo - req->cgroups[idx].rm_so);
   1881 		}
   1882 
   1883 		uri = kore_buf_stringify(&location, NULL);
   1884 	}
   1885 
   1886 	if (uri)
   1887 		http_response_header(req, "location", uri);
   1888 
   1889 	http_response(req, rdr->status, NULL, 0);
   1890 	kore_buf_cleanup(&location);
   1891 
   1892 	if (dom->accesslog)
   1893 		kore_accesslog(req);
   1894 
   1895 	return (KORE_RESULT_OK);
   1896 }
   1897 
   1898 static struct http_request *
   1899 http_request_new(struct connection *c, const char *host,
   1900     const char *method, char *path, const char *version)
   1901 {
   1902 	struct kore_domain		*dom;
   1903 	struct http_request		*req;
   1904 	size_t				qsoff;
   1905 	char				*p, *hp;
   1906 	int				m, flags, exists;
   1907 
   1908 	if (http_request_count >= http_request_limit) {
   1909 		http_error_response(c, HTTP_STATUS_SERVICE_UNAVAILABLE);
   1910 		return (NULL);
   1911 	}
   1912 
   1913 	if (strlen(host) >= KORE_DOMAINNAME_LEN - 1) {
   1914 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
   1915 		return (NULL);
   1916 	}
   1917 
   1918 	if (strlen(path) >= HTTP_URI_LEN - 1) {
   1919 		http_error_response(c, HTTP_STATUS_REQUEST_URI_TOO_LARGE);
   1920 		return (NULL);
   1921 	}
   1922 
   1923 	if (strcasecmp(version, "http/1.1")) {
   1924 		if (strcasecmp(version, "http/1.0")) {
   1925 			http_error_response(c, HTTP_STATUS_BAD_VERSION);
   1926 			return (NULL);
   1927 		}
   1928 
   1929 		flags = HTTP_VERSION_1_0;
   1930 	} else {
   1931 		flags = HTTP_VERSION_1_1;
   1932 	}
   1933 
   1934 	if ((p = strchr(path, '?')) != NULL) {
   1935 		qsoff = p - path;
   1936 	} else {
   1937 		qsoff = 0;
   1938 	}
   1939 
   1940 	hp = NULL;
   1941 
   1942 	switch (c->family) {
   1943 	case AF_INET6:
   1944 		if (*host == '[') {
   1945 			if ((hp = strrchr(host, ']')) == NULL) {
   1946 				http_error_response(c, HTTP_STATUS_BAD_REQUEST);
   1947 				return (NULL);
   1948 			}
   1949 			hp++;
   1950 			if (*hp == ':')
   1951 				*hp = '\0';
   1952 			else
   1953 				hp = NULL;
   1954 		}
   1955 		break;
   1956 	default:
   1957 		if ((hp = strrchr(host, ':')) != NULL)
   1958 			*hp = '\0';
   1959 		break;
   1960 	}
   1961 
   1962 	if (c->owner->server->tls && c->tls_sni != NULL) {
   1963 		if (strcasecmp(c->tls_sni, host)) {
   1964 			http_error_response(c, HTTP_STATUS_MISDIRECTED_REQUEST);
   1965 			return (NULL);
   1966 		}
   1967 	}
   1968 
   1969 	if ((dom = kore_domain_lookup(c->owner->server, host)) == NULL) {
   1970 		http_error_response(c, HTTP_STATUS_NOT_FOUND);
   1971 		return (NULL);
   1972 	}
   1973 
   1974 	if (dom->cafile != NULL && c->tls_cert == NULL) {
   1975 		http_error_response(c, HTTP_STATUS_FORBIDDEN);
   1976 		return (NULL);
   1977 	}
   1978 
   1979 	if (hp != NULL)
   1980 		*hp = ':';
   1981 
   1982 	if (!strcasecmp(method, "get")) {
   1983 		m = HTTP_METHOD_GET;
   1984 		flags |= HTTP_REQUEST_COMPLETE;
   1985 	} else if (!strcasecmp(method, "delete")) {
   1986 		m = HTTP_METHOD_DELETE;
   1987 		flags |= HTTP_REQUEST_EXPECT_BODY;
   1988 	} else if (!strcasecmp(method, "post")) {
   1989 		m = HTTP_METHOD_POST;
   1990 		flags |= HTTP_REQUEST_EXPECT_BODY;
   1991 	} else if (!strcasecmp(method, "put")) {
   1992 		m = HTTP_METHOD_PUT;
   1993 		flags |= HTTP_REQUEST_EXPECT_BODY;
   1994 	} else if (!strcasecmp(method, "head")) {
   1995 		m = HTTP_METHOD_HEAD;
   1996 		flags |= HTTP_REQUEST_COMPLETE;
   1997 	} else if (!strcasecmp(method, "options")) {
   1998 		m = HTTP_METHOD_OPTIONS;
   1999 		flags |= HTTP_REQUEST_COMPLETE;
   2000 	} else if (!strcasecmp(method, "patch")) {
   2001 		m = HTTP_METHOD_PATCH;
   2002 		flags |= HTTP_REQUEST_EXPECT_BODY;
   2003 	} else {
   2004 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
   2005 		return (NULL);
   2006 	}
   2007 
   2008 	if (flags & HTTP_VERSION_1_0) {
   2009 		if (m != HTTP_METHOD_GET && m != HTTP_METHOD_POST &&
   2010 		    m != HTTP_METHOD_HEAD) {
   2011 			http_error_response(c, HTTP_STATUS_METHOD_NOT_ALLOWED);
   2012 			return (NULL);
   2013 		}
   2014 	}
   2015 
   2016 	req = kore_pool_get(&http_request_pool);
   2017 
   2018 	req->end = 0;
   2019 	req->total = 0;
   2020 	req->start = 0;
   2021 	req->owner = c;
   2022 	req->status = 0;
   2023 	req->method = m;
   2024 	req->agent = NULL;
   2025 	req->referer = NULL;
   2026 	req->runlock = NULL;
   2027 	req->flags = flags;
   2028 	req->fsm_state = 0;
   2029 	req->http_body = NULL;
   2030 	req->http_body_fd = -1;
   2031 	req->hdlr_extra = NULL;
   2032 	req->content_length = 0;
   2033 	req->query_string = NULL;
   2034 	req->http_body_length = 0;
   2035 	req->http_body_offset = 0;
   2036 	req->http_body_path = NULL;
   2037 
   2038 	req->host = host;
   2039 	req->path = path;
   2040 
   2041 #if defined(KORE_USE_PYTHON)
   2042 	req->py_req = NULL;
   2043 	req->py_coro = NULL;
   2044 	req->py_rqnext = NULL;
   2045 	req->py_validator = NULL;
   2046 #endif
   2047 
   2048 	if (qsoff > 0) {
   2049 		req->query_string = path + qsoff;
   2050 		*(req->query_string)++ = '\0';
   2051 	} else {
   2052 		req->query_string = NULL;
   2053 	}
   2054 
   2055 	/* Checked further down below if we need to 404. */
   2056 	exists = kore_route_lookup(req, dom, m, &req->rt);
   2057 
   2058 	TAILQ_INIT(&(req->resp_headers));
   2059 	TAILQ_INIT(&(req->req_headers));
   2060 	TAILQ_INIT(&(req->resp_cookies));
   2061 	TAILQ_INIT(&(req->req_cookies));
   2062 	TAILQ_INIT(&(req->arguments));
   2063 	TAILQ_INIT(&(req->files));
   2064 
   2065 #if defined(KORE_USE_TASKS)
   2066 	LIST_INIT(&(req->tasks));
   2067 #endif
   2068 
   2069 #if defined(KORE_USE_PGSQL)
   2070 	LIST_INIT(&(req->pgsqls));
   2071 #endif
   2072 
   2073 	http_request_count++;
   2074 	TAILQ_INSERT_HEAD(&http_requests, req, list);
   2075 	TAILQ_INSERT_TAIL(&(c->http_requests), req, olist);
   2076 
   2077 	if (http_check_redirect(req, dom)) {
   2078 		http_request_free(req);
   2079 		return (NULL);
   2080 	}
   2081 
   2082 	if (exists == 0) {
   2083 		http_request_free(req);
   2084 		http_error_response(c, HTTP_STATUS_NOT_FOUND);
   2085 		return (NULL);
   2086 	}
   2087 
   2088 	if (req->rt == NULL) {
   2089 		http_request_free(req);
   2090 		http_error_response(c, HTTP_STATUS_METHOD_NOT_ALLOWED);
   2091 		return (NULL);
   2092 	}
   2093 
   2094 	return (req);
   2095 }
   2096 
   2097 static int
   2098 multipart_find_data(struct kore_buf *in, struct kore_buf *out,
   2099     size_t *olen, struct http_request *req, const void *needle, size_t len)
   2100 {
   2101 	ssize_t			ret;
   2102 	size_t			left;
   2103 	u_int8_t		*p, first, data[4096];
   2104 
   2105 	if (olen != NULL)
   2106 		*olen = 0;
   2107 
   2108 	first = *(const u_int8_t *)needle;
   2109 	for (;;) {
   2110 		if (in->offset < len) {
   2111 			ret = http_body_read(req, data, sizeof(data));
   2112 			if (ret == -1)
   2113 				return (KORE_RESULT_ERROR);
   2114 			if (ret == 0)
   2115 				return (KORE_RESULT_ERROR);
   2116 
   2117 			kore_buf_append(in, data, ret);
   2118 			continue;
   2119 		}
   2120 
   2121 		p = kore_mem_find(in->data, in->offset, &first, 1);
   2122 		if (p == NULL) {
   2123 			if (out != NULL)
   2124 				kore_buf_append(out, in->data, in->offset);
   2125 			if (olen != NULL)
   2126 				*olen += in->offset;
   2127 			kore_buf_reset(in);
   2128 			continue;
   2129 		}
   2130 
   2131 		left = in->offset - (p - in->data);
   2132 		if (left < len) {
   2133 			if (out != NULL)
   2134 				kore_buf_append(out, in->data, (p - in->data));
   2135 			if (olen != NULL)
   2136 				*olen += (p - in->data);
   2137 			memmove(in->data, p, left);
   2138 			in->offset = left;
   2139 			continue;
   2140 		}
   2141 
   2142 		if (!memcmp(p, needle, len)) {
   2143 			if (out != NULL)
   2144 				kore_buf_append(out, in->data, p - in->data);
   2145 			if (olen != NULL)
   2146 				*olen += (p - in->data);
   2147 
   2148 			in->offset = left - len;
   2149 			if (in->offset > 0)
   2150 				memmove(in->data, p + len, in->offset);
   2151 			return (KORE_RESULT_OK);
   2152 		}
   2153 
   2154 		if (out != NULL)
   2155 			kore_buf_append(out, in->data, (p - in->data) + 1);
   2156 		if (olen != NULL)
   2157 			*olen += (p - in->data) + 1;
   2158 
   2159 		in->offset = left - 1;
   2160 		if (in->offset > 0)
   2161 			memmove(in->data, p + 1, in->offset);
   2162 	}
   2163 
   2164 	return (KORE_RESULT_ERROR);
   2165 }
   2166 
   2167 static int
   2168 multipart_parse_headers(struct http_request *req, struct kore_buf *in,
   2169     struct kore_buf *hbuf, const char *boundary, const int blen)
   2170 {
   2171 	int		h, c, i;
   2172 	char		*headers[5], *args[5], *opt[5];
   2173 	char		*d, *val, *name, *fname, *string;
   2174 
   2175 	string = kore_buf_stringify(hbuf, NULL);
   2176 	h = kore_split_string(string, "\r\n", headers, 5);
   2177 	for (i = 0; i < h; i++) {
   2178 		c = kore_split_string(headers[i], ":", args, 5);
   2179 		if (c != 2)
   2180 			continue;
   2181 
   2182 		/* Ignore other headers for now. */
   2183 		if (strcasecmp(args[0], "content-disposition"))
   2184 			continue;
   2185 
   2186 		for (d = args[1]; isspace(*(unsigned char *)d); d++)
   2187 			;
   2188 
   2189 		c = kore_split_string(d, ";", opt, 5);
   2190 		if (c < 2)
   2191 			continue;
   2192 
   2193 		if (strcasecmp(opt[0], "form-data"))
   2194 			continue;
   2195 
   2196 		if ((val = strchr(opt[1], '=')) == NULL)
   2197 			continue;
   2198 		if (strlen(val) < 3)
   2199 			continue;
   2200 
   2201 		val++;
   2202 		kore_strip_chars(val, '"', &name);
   2203 
   2204 		if (opt[2] == NULL) {
   2205 			multipart_add_field(req, in, name, boundary, blen);
   2206 			kore_free(name);
   2207 			continue;
   2208 		}
   2209 
   2210 		for (d = opt[2]; isspace(*(unsigned char *)d); d++)
   2211 			;
   2212 
   2213 		if (!strncasecmp(d, "filename=", 9)) {
   2214 			if ((val = strchr(d, '=')) == NULL) {
   2215 				kore_free(name);
   2216 				continue;
   2217 			}
   2218 
   2219 			val++;
   2220 			kore_strip_chars(val, '"', &fname);
   2221 			if (strlen(fname) > 0) {
   2222 				multipart_file_add(req,
   2223 				    in, name, fname, boundary, blen);
   2224 			}
   2225 			kore_free(fname);
   2226 		}
   2227 
   2228 		kore_free(name);
   2229 	}
   2230 
   2231 	return (KORE_RESULT_OK);
   2232 }
   2233 
   2234 static void
   2235 multipart_add_field(struct http_request *req, struct kore_buf *in,
   2236     char *name, const char *boundary, const int blen)
   2237 {
   2238 	struct kore_buf		*data;
   2239 	char			*string;
   2240 
   2241 	data = kore_buf_alloc(128);
   2242 
   2243 	if (!multipart_find_data(in, data, NULL, req, boundary, blen)) {
   2244 		kore_buf_free(data);
   2245 		return;
   2246 	}
   2247 
   2248 	if (data->offset < 3) {
   2249 		kore_buf_free(data);
   2250 		return;
   2251 	}
   2252 
   2253 	data->offset -= 2;
   2254 	string = kore_buf_stringify(data, NULL);
   2255 	http_argument_add(req, name, string, 0, 0);
   2256 	kore_buf_free(data);
   2257 }
   2258 
   2259 static void
   2260 multipart_file_add(struct http_request *req, struct kore_buf *in,
   2261     const char *name, const char *fname, const char *boundary, const int blen)
   2262 {
   2263 	struct http_file	*f;
   2264 	size_t			position, len;
   2265 
   2266 	position = req->http_body_offset - in->offset;
   2267 	if (!multipart_find_data(in, NULL, &len, req, boundary, blen))
   2268 		return;
   2269 
   2270 	if (len < 3)
   2271 		return;
   2272 	len -= 2;
   2273 
   2274 	f = kore_malloc(sizeof(struct http_file));
   2275 	f->req = req;
   2276 	f->offset = 0;
   2277 	f->length = len;
   2278 	f->position = position;
   2279 	f->name = kore_strdup(name);
   2280 	f->filename = kore_strdup(fname);
   2281 
   2282 	TAILQ_INSERT_TAIL(&(req->files), f, list);
   2283 }
   2284 
   2285 static void
   2286 http_argument_add(struct http_request *req, char *name, char *value, int qs,
   2287     int decode)
   2288 {
   2289 	struct http_arg			*q;
   2290 	struct kore_route_params	*p;
   2291 
   2292 	if (decode) {
   2293 		if (!http_argument_urldecode(name, qs))
   2294 			return;
   2295 	}
   2296 
   2297 	TAILQ_FOREACH(p, &req->rt->params, list) {
   2298 		if (qs == 1 && !(p->flags & KORE_PARAMS_QUERY_STRING))
   2299 			continue;
   2300 		if (qs == 0 && (p->flags & KORE_PARAMS_QUERY_STRING))
   2301 			continue;
   2302 
   2303 		if (p->method != req->method)
   2304 			continue;
   2305 
   2306 		if (strcmp(p->name, name))
   2307 			continue;
   2308 
   2309 		if (decode) {
   2310 			if (!http_argument_urldecode(value, qs))
   2311 				return;
   2312 		}
   2313 
   2314 		if (!kore_validator_check(req, p->validator, value))
   2315 			break;
   2316 
   2317 		q = kore_malloc(sizeof(struct http_arg));
   2318 		q->name = kore_strdup(name);
   2319 		q->s_value = kore_strdup(value);
   2320 		TAILQ_INSERT_TAIL(&(req->arguments), q, list);
   2321 		break;
   2322 	}
   2323 }
   2324 
   2325 static int
   2326 http_body_recv(struct netbuf *nb)
   2327 {
   2328 	struct http_request	*req = (struct http_request *)nb->extra;
   2329 
   2330 	return (http_body_update(req, nb->buf, nb->s_off));
   2331 }
   2332 
   2333 static int
   2334 http_body_update(struct http_request *req, const void *data, size_t len)
   2335 {
   2336 	ssize_t			ret;
   2337 	u_int64_t		bytes_left;
   2338 
   2339 	SHA256Update(&req->hashctx, data, len);
   2340 
   2341 	if (req->http_body_fd != -1) {
   2342 		ret = write(req->http_body_fd, data, len);
   2343 		if (ret == -1 || (size_t)ret != len) {
   2344 			req->flags |= HTTP_REQUEST_DELETE;
   2345 			http_error_response(req->owner,
   2346 			    HTTP_STATUS_INTERNAL_ERROR);
   2347 			return (KORE_RESULT_ERROR);
   2348 		}
   2349 	} else if (req->http_body != NULL) {
   2350 		kore_buf_append(req->http_body, data, len);
   2351 	} else {
   2352 		req->flags |= HTTP_REQUEST_DELETE;
   2353 		http_error_response(req->owner,
   2354 		    HTTP_STATUS_INTERNAL_ERROR);
   2355 		return (KORE_RESULT_ERROR);
   2356 	}
   2357 
   2358 	req->content_length -= len;
   2359 
   2360 	if (req->content_length == 0) {
   2361 		req->owner->http_timeout = 0;
   2362 		req->owner->rnb->extra = NULL;
   2363 		http_request_wakeup(req);
   2364 		req->flags |= HTTP_REQUEST_COMPLETE;
   2365 		req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
   2366 		req->content_length = req->http_body_length;
   2367 		if (!http_body_rewind(req)) {
   2368 			req->flags |= HTTP_REQUEST_DELETE;
   2369 			http_error_response(req->owner,
   2370 			    HTTP_STATUS_INTERNAL_ERROR);
   2371 			return (KORE_RESULT_ERROR);
   2372 		}
   2373 		SHA256Final(req->http_body_digest, &req->hashctx);
   2374 	} else {
   2375 		bytes_left = req->content_length;
   2376 		net_recv_reset(req->owner,
   2377 		    MIN(bytes_left, NETBUF_SEND_PAYLOAD_MAX),
   2378 		    http_body_recv);
   2379 		req->owner->rnb->extra = req;
   2380 	}
   2381 
   2382 	if (req->rt->on_body_chunk != NULL && len > 0) {
   2383 		kore_runtime_http_body_chunk(req->rt->on_body_chunk,
   2384 		    req, data, len);
   2385 	}
   2386 
   2387 	return (KORE_RESULT_OK);
   2388 }
   2389 
   2390 static void
   2391 http_error_response(struct connection *c, int status)
   2392 {
   2393 	c->flags |= CONN_CLOSE_EMPTY;
   2394 
   2395 	switch (c->proto) {
   2396 	case CONN_PROTO_HTTP:
   2397 		http_response_normal(NULL, c, status, NULL, 0);
   2398 		break;
   2399 	default:
   2400 		fatal("http_error_response() bad proto %d", c->proto);
   2401 		/* NOTREACHED. */
   2402 	}
   2403 
   2404 	if (!net_send_flush(c))
   2405 		kore_connection_disconnect(c);
   2406 }
   2407 
   2408 static void
   2409 http_response_normal(struct http_request *req, struct connection *c,
   2410     int status, const void *d, size_t len)
   2411 {
   2412 	struct kore_buf		buf;
   2413 	struct http_cookie	*ck;
   2414 	struct http_header	*hdr;
   2415 	char			version;
   2416 	const char		*conn, *text;
   2417 	int			connection_close, send_body;
   2418 
   2419 	send_body = 1;
   2420 	text = http_status_text(status);
   2421 
   2422 	kore_buf_reset(header_buf);
   2423 
   2424 	if (req != NULL) {
   2425 		if (req->flags & HTTP_VERSION_1_0)
   2426 			version = '0';
   2427 		else
   2428 			version = '1';
   2429 	} else {
   2430 		version = '1';
   2431 	}
   2432 
   2433 	kore_buf_appendf(header_buf, "HTTP/1.%c %d %s\r\n",
   2434 	    version, status, text);
   2435 
   2436 	if (status == 100) {
   2437 		kore_buf_append(header_buf, "\r\n", 2);
   2438 		net_send_queue(c, header_buf->data, header_buf->offset);
   2439 		return;
   2440 	}
   2441 
   2442 	kore_buf_append(header_buf, http_version, http_version_len);
   2443 
   2444 	if ((c->flags & CONN_CLOSE_EMPTY) ||
   2445 	    (req != NULL && (req->flags & HTTP_VERSION_1_0))) {
   2446 		connection_close = 1;
   2447 	} else {
   2448 		connection_close = 0;
   2449 	}
   2450 
   2451 	if (connection_close == 0 && req != NULL) {
   2452 		if (http_request_header(req, "connection", &conn)) {
   2453 			if ((*conn == 'c' || *conn == 'C') &&
   2454 			    !strcasecmp(conn, "close")) {
   2455 				connection_close = 1;
   2456 			}
   2457 		}
   2458 	}
   2459 
   2460 	kore_buf_init(&buf, 1024);
   2461 
   2462 	/* Note that req CAN be NULL. */
   2463 	if (req == NULL || req->owner->proto != CONN_PROTO_WEBSOCKET) {
   2464 		if (http_keepalive_time && connection_close == 0) {
   2465 			kore_buf_appendf(header_buf,
   2466 			    "connection: keep-alive\r\n");
   2467 			kore_buf_appendf(header_buf,
   2468 			    "keep-alive: timeout=%d\r\n", http_keepalive_time);
   2469 		} else {
   2470 			c->flags |= CONN_CLOSE_EMPTY;
   2471 			kore_buf_appendf(header_buf, "connection: close\r\n");
   2472 		}
   2473 	}
   2474 
   2475 	if (c->tls && http_hsts_enable) {
   2476 		kore_buf_appendf(header_buf, "strict-transport-security: ");
   2477 		kore_buf_appendf(header_buf,
   2478 		    "max-age=%" PRIu64 "; includeSubDomains\r\n",
   2479 		    http_hsts_enable);
   2480 	}
   2481 
   2482 	if (http_pretty_error && d == NULL && status >= 400) {
   2483 		kore_buf_appendf(&buf, pretty_error_fmt,
   2484 		    status, text, status, text);
   2485 
   2486 		d = buf.data;
   2487 		len = buf.offset;
   2488 	}
   2489 
   2490 	if (req != NULL) {
   2491 		TAILQ_FOREACH(ck, &(req->resp_cookies), list)
   2492 			http_write_response_cookie(ck);
   2493 
   2494 		TAILQ_FOREACH(hdr, &(req->resp_headers), list) {
   2495 			kore_buf_appendf(header_buf, "%s: %s\r\n",
   2496 			    hdr->header, hdr->value);
   2497 		}
   2498 
   2499 		if (status != 204 && status >= 200 &&
   2500 		    !(req->flags & HTTP_REQUEST_NO_CONTENT_LENGTH)) {
   2501 			kore_buf_appendf(header_buf,
   2502 			    "content-length: %zu\r\n", len);
   2503 		}
   2504 	} else {
   2505 		if (status != 204 && status >= 200) {
   2506 			kore_buf_appendf(header_buf,
   2507 			    "content-length: %zu\r\n", len);
   2508 		}
   2509 	}
   2510 
   2511 	kore_buf_append(header_buf, "\r\n", 2);
   2512 	net_send_queue(c, header_buf->data, header_buf->offset);
   2513 
   2514 	if (req != NULL && req->method == HTTP_METHOD_HEAD)
   2515 		send_body = 0;
   2516 
   2517 	if (d != NULL && send_body)
   2518 		net_send_queue(c, d, len);
   2519 
   2520 	if (!(c->flags & CONN_CLOSE_EMPTY) && !(c->flags & CONN_IS_BUSY))
   2521 		http_start_recv(c);
   2522 
   2523 	if (req != NULL)
   2524 		req->content_length = len;
   2525 
   2526 	kore_buf_cleanup(&buf);
   2527 }
   2528 
   2529 static void
   2530 http_write_response_cookie(struct http_cookie *ck)
   2531 {
   2532 	struct tm		tm;
   2533 	char			expires[HTTP_DATE_MAXSIZE];
   2534 
   2535 	kore_buf_reset(ckhdr_buf);
   2536 	kore_buf_appendf(ckhdr_buf, "%s=%s", ck->name, ck->value);
   2537 
   2538 	if (ck->path != NULL)
   2539 		kore_buf_appendf(ckhdr_buf, "; Path=%s", ck->path);
   2540 	if (ck->domain != NULL)
   2541 		kore_buf_appendf(ckhdr_buf, "; Domain=%s", ck->domain);
   2542 
   2543 	if (ck->expires > 0) {
   2544 		if (gmtime_r(&ck->expires, &tm) == NULL) {
   2545 			kore_log(LOG_ERR, "gmtime_r(): %s", errno_s);
   2546 			return;
   2547 		}
   2548 
   2549 		if (strftime(expires, sizeof(expires),
   2550 		    "%a, %d %b %y %H:%M:%S GMT", &tm) == 0) {
   2551 			kore_log(LOG_ERR, "strftime(): %s", errno_s);
   2552 			return;
   2553 		}
   2554 
   2555 		kore_buf_appendf(ckhdr_buf, "; Expires=%s", expires);
   2556 	}
   2557 
   2558 	if (ck->maxage > 0)
   2559 		kore_buf_appendf(ckhdr_buf, "; Max-Age=%u", ck->maxage);
   2560 
   2561 	if (ck->flags & HTTP_COOKIE_HTTPONLY)
   2562 		kore_buf_appendf(ckhdr_buf, "; HttpOnly");
   2563 	if (ck->flags & HTTP_COOKIE_SECURE)
   2564 		kore_buf_appendf(ckhdr_buf, "; Secure");
   2565 
   2566 	kore_buf_appendf(header_buf, "set-cookie: %s\r\n",
   2567 	    kore_buf_stringify(ckhdr_buf, NULL));
   2568 }
   2569 
   2570 static int
   2571 http_data_convert(void *data, void **out, void *nout, int type)
   2572 {
   2573 	switch (type) {
   2574 	case HTTP_ARG_TYPE_RAW:
   2575 	case HTTP_ARG_TYPE_STRING:
   2576 		*out = data;
   2577 		return (KORE_RESULT_OK);
   2578 	case HTTP_ARG_TYPE_BYTE:
   2579 		COPY_ARG_TYPE(*(u_int8_t *)data, u_int8_t);
   2580 		return (KORE_RESULT_OK);
   2581 	case HTTP_ARG_TYPE_INT16:
   2582 		COPY_AS_INTTYPE(SHRT_MIN, SHRT_MAX, int16_t);
   2583 		return (KORE_RESULT_OK);
   2584 	case HTTP_ARG_TYPE_UINT16:
   2585 		COPY_AS_INTTYPE(0, USHRT_MAX, u_int16_t);
   2586 		return (KORE_RESULT_OK);
   2587 	case HTTP_ARG_TYPE_INT32:
   2588 		COPY_AS_INTTYPE(INT_MIN, INT_MAX, int32_t);
   2589 		return (KORE_RESULT_OK);
   2590 	case HTTP_ARG_TYPE_UINT32:
   2591 		COPY_AS_INTTYPE(0, UINT_MAX, u_int32_t);
   2592 		return (KORE_RESULT_OK);
   2593 	case HTTP_ARG_TYPE_INT64:
   2594 		COPY_AS_INTTYPE_64(int64_t, 1);
   2595 		return (KORE_RESULT_OK);
   2596 	case HTTP_ARG_TYPE_UINT64:
   2597 		COPY_AS_INTTYPE_64(u_int64_t, 0);
   2598 		return (KORE_RESULT_OK);
   2599 	case HTTP_ARG_TYPE_FLOAT:
   2600 		COPY_ARG_DOUBLE(-FLT_MAX, FLT_MAX, float);
   2601 		return (KORE_RESULT_OK);
   2602 	case HTTP_ARG_TYPE_DOUBLE:
   2603 		COPY_ARG_DOUBLE(-DBL_MAX, DBL_MAX, double);
   2604 		return (KORE_RESULT_OK);
   2605 	default:
   2606 		break;
   2607 	}
   2608 
   2609 	return (KORE_RESULT_ERROR);
   2610 }