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 (59797B)



      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 
     30 #include "kore.h"
     31 #include "http.h"
     32 
     33 #if defined(KORE_USE_PYTHON)
     34 #include "python_api.h"
     35 #endif
     36 
     37 #if defined(KORE_USE_PGSQL)
     38 #include "pgsql.h"
     39 #endif
     40 
     41 #if defined(KORE_USE_TASKS)
     42 #include "tasks.h"
     43 #endif
     44 
     45 #if defined(KORE_USE_CURL)
     46 #include "curl.h"
     47 #endif
     48 
     49 static struct {
     50 	const char	*ext;
     51 	const char	*type;
     52 } builtin_media[] = {
     53 	{ "gif",	"image/gif" },
     54 	{ "png",	"image/png" },
     55 	{ "jpeg",	"image/jpeg" },
     56 	{ "jpg",	"image/jpeg" },
     57 	{ "zip",	"application/zip" },
     58 	{ "pdf",	"application/pdf" },
     59 	{ "json",	"application/json" },
     60 	{ "js",		"application/javascript" },
     61 	{ "htm",	"text/html" },
     62 	{ "txt",	"text/plain" },
     63 	{ "css",	"text/css" },
     64 	{ "html",	"text/html" },
     65 	{ NULL,		NULL },
     66 };
     67 
     68 #define HTTP_MAP_LIMIT		127
     69 
     70 /*
     71  * token      = 1*<any CHAR except CTLs or separators>
     72  * separators = "(" | ")" | "<" | ">" | "@"
     73  *            | "," | ";" | ":" | "\" | <">
     74  *            | "/" | "[" | "]" | "?" | "="
     75  *            | "{" | "}" | SP | HT
     76  */
     77 static const char http_token[] = {
     78 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     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, '#' , '$' , '%' , '&' , '\'',
     83 	0x00, 0x00, '*' , '+' , 0x00, '-' , '.' , 0x00,
     84 	'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' ,
     85 	'8' , '9' , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     86 	0x00, 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' ,
     87 	'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' ,
     88 	'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' ,
     89 	'X' , 'Y' , 'Z' , 0x00, 0x00, 0x00, '^' , '_' ,
     90 	'`' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' ,
     91 	'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' ,
     92 	'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' ,
     93 	'x' , 'y' , 'z' , 0x00, '|' , 0x00, '~' , 0x00
     94 };
     95 
     96 /*
     97  * field-content  = <the OCTETs making up the field-value
     98  *                   and consisting of either *TEXT or combinations
     99  *                   of token, separators, and quoted-string>
    100  */
    101 static const char http_field_content[] = {
    102 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    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 	' ' , '!' , '"' , '#' , '$' , '%' , '&' , '\'',
    107 	'(' , ')' , '*' , '+' , ',' , '-' , '.' , '/' ,
    108 	'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' ,
    109 	'8' , '9' , ':' , ';' , '<' , '=' , '>' , '?' ,
    110 	'@' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' ,
    111 	'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' ,
    112 	'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' ,
    113 	'X' , 'Y' , 'Z' , '[' , '\\', ']' , '^' , '_' ,
    114 	'`' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' ,
    115 	'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' ,
    116 	'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' ,
    117 	'x' , 'y' , 'z' , '{' , '|' , '}' , '~' , 0x00
    118 };
    119 
    120 /*
    121  * Fixed "pretty" HTTP error HTML page.
    122  */
    123 static const char *pretty_error_fmt =
    124 	"<html>\n<head>\n\t<title>%d %s</title>"
    125 	"</head>\n<body>\n\t"
    126 	"<h1>%d %s</h1>\n"
    127 	"</body>\n</html>\n";
    128 
    129 static int	http_body_recv(struct netbuf *);
    130 static int	http_release_buffer(struct netbuf *);
    131 static void	http_error_response(struct connection *, int);
    132 static int	http_data_convert(void *, void **, void *, int);
    133 static void	http_write_response_cookie(struct http_cookie *);
    134 static int	http_body_update(struct http_request *, const void *, size_t);
    135 static void	http_argument_add(struct http_request *, char *, char *,
    136 		    int, int);
    137 static int	http_check_redirect(struct http_request *,
    138 		    struct kore_domain *);
    139 static void	http_response_normal(struct http_request *,
    140 		    struct connection *, int, const void *, size_t);
    141 static void	multipart_add_field(struct http_request *, struct kore_buf *,
    142 		    char *, const char *, const int);
    143 static void	multipart_file_add(struct http_request *, struct kore_buf *,
    144 		    const char *, const char *, const char *, const int);
    145 static int	multipart_find_data(struct kore_buf *, struct kore_buf *,
    146 		    size_t *, struct http_request *, const void *, size_t);
    147 static int	multipart_parse_headers(struct http_request *,
    148 		    struct kore_buf *, struct kore_buf *,
    149 		    const char *, const int);
    150 
    151 static struct http_request	*http_request_new(struct connection *,
    152 				    const char *, const char *, char *,
    153 				    const char *);
    154 
    155 static struct kore_buf			*header_buf;
    156 static struct kore_buf			*ckhdr_buf;
    157 static char				http_version[64];
    158 static u_int16_t			http_version_len;
    159 static TAILQ_HEAD(, http_request)	http_requests;
    160 static TAILQ_HEAD(, http_request)	http_requests_sleeping;
    161 static LIST_HEAD(, http_media_type)	http_media_types;
    162 static struct kore_pool			http_request_pool;
    163 static struct kore_pool			http_cookie_pool;
    164 static struct kore_pool			http_body_path;
    165 static struct kore_pool			http_rlq_pool;
    166 
    167 struct kore_pool			http_header_pool;
    168 
    169 int		http_pretty_error = 0;
    170 u_int32_t	http_request_count = 0;
    171 u_int32_t	http_request_ms = HTTP_REQUEST_MS;
    172 u_int16_t	http_body_timeout = HTTP_BODY_TIMEOUT;
    173 u_int32_t	http_request_limit = HTTP_REQUEST_LIMIT;
    174 u_int64_t	http_hsts_enable = HTTP_HSTS_ENABLE;
    175 u_int16_t	http_header_max = HTTP_HEADER_MAX_LEN;
    176 u_int16_t	http_keepalive_time = HTTP_KEEPALIVE_TIME;
    177 u_int16_t	http_header_timeout = HTTP_HEADER_TIMEOUT;
    178 
    179 size_t		http_body_max = HTTP_BODY_MAX_LEN;
    180 char		*http_body_disk_path = HTTP_BODY_DISK_PATH;
    181 u_int64_t	http_body_disk_offload = HTTP_BODY_DISK_OFFLOAD;
    182 
    183 void
    184 http_parent_init(void)
    185 {
    186 	LIST_INIT(&http_media_types);
    187 }
    188 
    189 void
    190 http_init(void)
    191 {
    192 	int		prealloc, l, i;
    193 
    194 	TAILQ_INIT(&http_requests);
    195 	TAILQ_INIT(&http_requests_sleeping);
    196 
    197 	header_buf = kore_buf_alloc(HTTP_HEADER_BUFSIZE);
    198 	ckhdr_buf = kore_buf_alloc(HTTP_COOKIE_BUFSIZE);
    199 
    200 	if (!http_version_len) {
    201 		l = snprintf(http_version, sizeof(http_version),
    202 		    "server: kore (%s)\r\n", kore_version);
    203 		if (l == -1 || (size_t)l >= sizeof(http_version))
    204 			fatal("http_init(): http_version buffer too small");
    205 
    206 		http_version_len = l;
    207 	}
    208 
    209 	prealloc = MIN((worker_max_connections / 10), 1000);
    210 	kore_pool_init(&http_request_pool, "http_request_pool",
    211 	    sizeof(struct http_request), http_request_limit);
    212 	kore_pool_init(&http_header_pool, "http_header_pool",
    213 	    sizeof(struct http_header), prealloc * HTTP_REQ_HEADER_MAX);
    214 	kore_pool_init(&http_cookie_pool, "http_cookie_pool",
    215 		sizeof(struct http_cookie), prealloc * HTTP_MAX_COOKIES);
    216 	kore_pool_init(&http_rlq_pool, "http_rlq_pool",
    217 		sizeof(struct http_runlock_queue), http_request_limit);
    218 
    219 	kore_pool_init(&http_body_path,
    220 	    "http_body_path", HTTP_BODY_PATH_MAX, prealloc);
    221 
    222 	for (i = 0; builtin_media[i].ext != NULL; i++) {
    223 		if (!http_media_register(builtin_media[i].ext,
    224 		    builtin_media[i].type)) {
    225 			fatal("duplicate media type for %s",
    226 			    builtin_media[i].ext);
    227 		}
    228 	}
    229 }
    230 
    231 void
    232 http_cleanup(void)
    233 {
    234 	if (header_buf != NULL) {
    235 		kore_buf_free(header_buf);
    236 		header_buf = NULL;
    237 	}
    238 
    239 	if (ckhdr_buf != NULL) {
    240 		kore_buf_free(ckhdr_buf);
    241 		ckhdr_buf = NULL;
    242 	}
    243 
    244 	kore_pool_cleanup(&http_request_pool);
    245 	kore_pool_cleanup(&http_header_pool);
    246 	kore_pool_cleanup(&http_body_path);
    247 }
    248 
    249 void
    250 http_server_version(const char *version)
    251 {
    252 	int		l;
    253 
    254 	l = snprintf(http_version, sizeof(http_version),
    255 	    "server: %s\r\n", version);
    256 	if (l == -1 || (size_t)l >= sizeof(http_version))
    257 		fatal("http_server_version(): http_version buffer too small");
    258 
    259 	http_version_len = l;
    260 }
    261 
    262 int
    263 http_check_timeout(struct connection *c, u_int64_t now)
    264 {
    265 	u_int64_t	d;
    266 
    267 	if (c->http_timeout == 0)
    268 		return (KORE_RESULT_OK);
    269 
    270 	if (now > c->http_start)
    271 		d = now - c->http_start;
    272 	else
    273 		d = 0;
    274 
    275 	if (d >= c->http_timeout) {
    276 		http_error_response(c, HTTP_STATUS_REQUEST_TIMEOUT);
    277 		kore_connection_disconnect(c);
    278 		return (KORE_RESULT_ERROR);
    279 	}
    280 
    281 	return (KORE_RESULT_OK);
    282 }
    283 
    284 void
    285 http_request_sleep(struct http_request *req)
    286 {
    287 	if (!(req->flags & HTTP_REQUEST_SLEEPING)) {
    288 		req->flags |= HTTP_REQUEST_SLEEPING;
    289 		TAILQ_REMOVE(&http_requests, req, list);
    290 		TAILQ_INSERT_TAIL(&http_requests_sleeping, req, list);
    291 	}
    292 }
    293 
    294 void
    295 http_request_wakeup(struct http_request *req)
    296 {
    297 	if (req->flags & HTTP_REQUEST_SLEEPING) {
    298 		req->flags &= ~HTTP_REQUEST_SLEEPING;
    299 		TAILQ_REMOVE(&http_requests_sleeping, req, list);
    300 		TAILQ_INSERT_TAIL(&http_requests, req, list);
    301 	}
    302 }
    303 
    304 void
    305 http_process(void)
    306 {
    307 	u_int64_t			total;
    308 	struct http_request		*req, *next;
    309 
    310 	total = 0;
    311 
    312 	for (req = TAILQ_FIRST(&http_requests); req != NULL; req = next) {
    313 		if (total >= http_request_ms)
    314 			break;
    315 
    316 		next = TAILQ_NEXT(req, list);
    317 		if (req->flags & HTTP_REQUEST_DELETE) {
    318 			http_request_free(req);
    319 			continue;
    320 		}
    321 
    322 		/* Sleeping requests should be in http_requests_sleeping. */
    323 		if (req->flags & HTTP_REQUEST_SLEEPING)
    324 			fatal("http_process: sleeping request on list");
    325 
    326 		if (!(req->flags & HTTP_REQUEST_COMPLETE))
    327 			continue;
    328 
    329 		http_process_request(req);
    330 		total += req->ms;
    331 
    332 		if (req->flags & HTTP_REQUEST_DELETE)
    333 			http_request_free(req);
    334 	}
    335 }
    336 
    337 void
    338 http_process_request(struct http_request *req)
    339 {
    340 	int		r;
    341 
    342 	if (req->flags & HTTP_REQUEST_DELETE || req->rt == NULL)
    343 		return;
    344 
    345 	req->start = kore_time_ms();
    346 	if (req->rt->auth != NULL && !(req->flags & HTTP_REQUEST_AUTHED))
    347 		r = kore_auth_run(req, req->rt->auth);
    348 	else
    349 		r = KORE_RESULT_OK;
    350 
    351 	switch (r) {
    352 	case KORE_RESULT_OK:
    353 		r = kore_runtime_http_request(req->rt->rcall, req);
    354 		break;
    355 	case KORE_RESULT_RETRY:
    356 		break;
    357 	case KORE_RESULT_ERROR:
    358 		/*
    359 		 * Set r to KORE_RESULT_OK so we can properly
    360 		 * flush the result from kore_auth_run().
    361 		 */
    362 		r = KORE_RESULT_OK;
    363 		break;
    364 	default:
    365 		fatal("kore_auth() returned unknown %d", r);
    366 	}
    367 	req->end = kore_time_ms();
    368 	req->ms = req->end - req->start;
    369 	req->total += req->ms;
    370 
    371 	switch (r) {
    372 	case KORE_RESULT_OK:
    373 		r = net_send_flush(req->owner);
    374 		if (r == KORE_RESULT_ERROR)
    375 			kore_connection_disconnect(req->owner);
    376 		break;
    377 	case KORE_RESULT_ERROR:
    378 		kore_connection_disconnect(req->owner);
    379 		break;
    380 	case KORE_RESULT_RETRY:
    381 		return;
    382 	default:
    383 		fatal("A page handler returned an unknown result: %d", r);
    384 	}
    385 
    386 	if (req->rt->dom->accesslog)
    387 		kore_accesslog(req);
    388 
    389 	req->flags |= HTTP_REQUEST_DELETE;
    390 }
    391 
    392 void
    393 http_response_header(struct http_request *req,
    394     const char *header, const char *value)
    395 {
    396 	struct http_header	*hdr;
    397 
    398 	hdr = NULL;
    399 
    400 	TAILQ_FOREACH(hdr, &req->resp_headers, list) {
    401 		if (!strcasecmp(hdr->header, header)) {
    402 			TAILQ_REMOVE(&req->resp_headers, hdr, list);
    403 			kore_free(hdr->header);
    404 			kore_free(hdr->value);
    405 			break;
    406 		}
    407 	}
    408 
    409 	if (hdr == NULL)
    410 		hdr = kore_pool_get(&http_header_pool);
    411 
    412 	hdr->header = kore_strdup(header);
    413 	hdr->value = kore_strdup(value);
    414 
    415 	TAILQ_INSERT_TAIL(&(req->resp_headers), hdr, list);
    416 }
    417 
    418 void
    419 http_request_free(struct http_request *req)
    420 {
    421 #if defined(KORE_USE_TASKS)
    422 	struct kore_task	*t, *nt;
    423 	int			pending_tasks;
    424 #endif
    425 #if defined(KORE_USE_PGSQL)
    426 	struct kore_pgsql	*pgsql;
    427 #endif
    428 #if defined(KORE_USE_CURL)
    429 	struct kore_curl	*client;
    430 #endif
    431 	struct http_file	*f, *fnext;
    432 	struct http_arg		*q, *qnext;
    433 	struct http_header	*hdr, *next;
    434 	struct http_cookie	*ck, *cknext;
    435 
    436 	if (req->rt != NULL && req->rt->on_free != NULL)
    437 		kore_runtime_http_request_free(req->rt->on_free, req);
    438 
    439 	if (req->runlock != NULL) {
    440 		LIST_REMOVE(req->runlock, list);
    441 		req->runlock = NULL;
    442 	}
    443 
    444 #if defined(KORE_USE_TASKS)
    445 	pending_tasks = 0;
    446 	for (t = LIST_FIRST(&(req->tasks)); t != NULL; t = nt) {
    447 		nt = LIST_NEXT(t, rlist);
    448 		if (!kore_task_finished(t)) {
    449 			pending_tasks++;
    450 		} else {
    451 			kore_task_destroy(t);
    452 		}
    453 	}
    454 
    455 	if (pending_tasks)
    456 		return;
    457 #endif
    458 
    459 #if defined(KORE_USE_PYTHON)
    460 	if (req->py_coro != NULL) {
    461 		kore_python_coro_delete(req->py_coro);
    462 		req->py_coro = NULL;
    463 	}
    464 	if (req->py_validator != NULL) {
    465 		kore_python_coro_delete(req->py_validator);
    466 		req->py_validator = NULL;
    467 	}
    468 	Py_XDECREF(req->py_req);
    469 #endif
    470 #if defined(KORE_USE_PGSQL)
    471 	while (!LIST_EMPTY(&(req->pgsqls))) {
    472 		pgsql = LIST_FIRST(&(req->pgsqls));
    473 		kore_pgsql_cleanup(pgsql);
    474 	}
    475 #endif
    476 #if defined(KORE_USE_CURL)
    477 	while (!LIST_EMPTY(&req->chandles)) {
    478 		client = LIST_FIRST(&req->chandles);
    479 		kore_curl_cleanup(client);
    480 	}
    481 #endif
    482 	kore_free(req->headers);
    483 
    484 	req->host = NULL;
    485 	req->path = NULL;
    486 	req->headers = NULL;
    487 
    488 	TAILQ_REMOVE(&http_requests, req, list);
    489 	if (req->owner != NULL)
    490 		TAILQ_REMOVE(&(req->owner->http_requests), req, olist);
    491 
    492 	for (hdr = TAILQ_FIRST(&(req->resp_headers)); hdr != NULL; hdr = next) {
    493 		next = TAILQ_NEXT(hdr, list);
    494 		TAILQ_REMOVE(&(req->resp_headers), hdr, list);
    495 		kore_free(hdr->header);
    496 		kore_free(hdr->value);
    497 		kore_pool_put(&http_header_pool, hdr);
    498 	}
    499 
    500 	for (hdr = TAILQ_FIRST(&(req->req_headers)); hdr != NULL; hdr = next) {
    501 		next = TAILQ_NEXT(hdr, list);
    502 		TAILQ_REMOVE(&(req->req_headers), hdr, list);
    503 		kore_pool_put(&http_header_pool, hdr);
    504 	}
    505 
    506 	for (ck = TAILQ_FIRST(&(req->resp_cookies)); ck != NULL; ck = cknext) {
    507 		cknext = TAILQ_NEXT(ck, list);
    508 		TAILQ_REMOVE(&(req->resp_cookies), ck, list);
    509 		kore_free(ck->name);
    510 		kore_free(ck->value);
    511 		kore_free(ck->path);
    512 		kore_free(ck->domain);
    513 		kore_pool_put(&http_cookie_pool, ck);
    514 	}
    515 
    516 	for (ck = TAILQ_FIRST(&(req->req_cookies)); ck != NULL; ck = cknext) {
    517 		cknext = TAILQ_NEXT(ck, list);
    518 		TAILQ_REMOVE(&(req->req_cookies), ck, list);
    519 		kore_free(ck->name);
    520 		kore_free(ck->value);
    521 		kore_pool_put(&http_cookie_pool, ck);
    522 	}
    523 
    524 	for (q = TAILQ_FIRST(&(req->arguments)); q != NULL; q = qnext) {
    525 		qnext = TAILQ_NEXT(q, list);
    526 		TAILQ_REMOVE(&(req->arguments), q, list);
    527 		kore_free(q->name);
    528 		kore_free(q->s_value);
    529 		kore_free(q);
    530 	}
    531 
    532 	for (f = TAILQ_FIRST(&(req->files)); f != NULL; f = fnext) {
    533 		fnext = TAILQ_NEXT(f, list);
    534 		TAILQ_REMOVE(&(req->files), f, list);
    535 		kore_free(f->filename);
    536 		kore_free(f->name);
    537 		kore_free(f);
    538 	}
    539 
    540 	if (req->http_body != NULL)
    541 		kore_buf_free(req->http_body);
    542 
    543 	if (req->http_body_fd != -1)
    544 		(void)close(req->http_body_fd);
    545 
    546 	if (req->http_body_path != NULL) {
    547 		if (unlink(req->http_body_path) == -1 && errno != ENOENT) {
    548 			kore_log(LOG_NOTICE, "failed to unlink %s: %s",
    549 			    req->http_body_path, errno_s);
    550 		}
    551 		kore_pool_put(&http_body_path, req->http_body_path);
    552 	}
    553 
    554 	if (req->hdlr_extra != NULL &&
    555 	    !(req->flags & HTTP_REQUEST_RETAIN_EXTRA))
    556 		kore_free(req->hdlr_extra);
    557 
    558 	kore_pool_put(&http_request_pool, req);
    559 	http_request_count--;
    560 }
    561 
    562 void
    563 http_serveable(struct http_request *req, const void *data, size_t len,
    564     const char *etag, const char *type)
    565 {
    566 	const char		*match;
    567 
    568 	if (req->method != HTTP_METHOD_GET) {
    569 		http_response_header(req, "allow", "get");
    570 		http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0);
    571 		return;
    572 	}
    573 
    574 	if (http_request_header(req, "if-none-match", &match)) {
    575 		if (!strcmp(match, etag)) {
    576 			http_response(req, HTTP_STATUS_NOT_MODIFIED, NULL, 0);
    577 			return;
    578 		}
    579 	}
    580 
    581 	http_response_header(req, "etag", etag);
    582 	http_response_header(req, "content-type", type);
    583 	http_response(req, HTTP_STATUS_OK, data, len);
    584 }
    585 
    586 void
    587 http_response(struct http_request *req, int code, const void *d, size_t l)
    588 {
    589 	if (req->owner == NULL)
    590 		return;
    591 
    592 	req->status = code;
    593 
    594 	switch (req->owner->proto) {
    595 	case CONN_PROTO_HTTP:
    596 	case CONN_PROTO_WEBSOCKET:
    597 		http_response_normal(req, req->owner, code, d, l);
    598 		break;
    599 	default:
    600 		fatal("%s: bad proto %d", __func__, req->owner->proto);
    601 		/* NOTREACHED. */
    602 	}
    603 }
    604 
    605 void
    606 http_response_close(struct http_request *req, int code, const void *d, size_t l)
    607 {
    608 	if (req->owner == NULL)
    609 		return;
    610 
    611 	req->status = code;
    612 	req->owner->flags |= CONN_CLOSE_EMPTY;
    613 
    614 	switch (req->owner->proto) {
    615 	case CONN_PROTO_HTTP:
    616 	case CONN_PROTO_WEBSOCKET:
    617 		http_response_normal(req, req->owner, code, d, l);
    618 		break;
    619 	default:
    620 		fatal("%s: bad proto %d", __func__, req->owner->proto);
    621 		/* NOTREACHED. */
    622 	}
    623 }
    624 
    625 void
    626 http_response_json(struct http_request *req, int status,
    627     struct kore_json_item *json)
    628 {
    629 	struct kore_buf		*buf;
    630 
    631 	if (req->owner == NULL)
    632 		return;
    633 
    634 	buf = kore_buf_alloc(1024);
    635 	kore_json_item_tobuf(json, buf);
    636 	kore_json_item_free(json);
    637 
    638 	req->status = status;
    639 	http_response_header(req, "content-type", "application/json");
    640 
    641 	switch (req->owner->proto) {
    642 	case CONN_PROTO_HTTP:
    643 		http_response_stream(req, status, buf->data, buf->offset,
    644 		    http_release_buffer, buf);
    645 		break;
    646 	default:
    647 		fatal("%s: bad proto %d", __func__, req->owner->proto);
    648 		/* NOTREACHED. */
    649 	}
    650 }
    651 
    652 void
    653 http_response_stream(struct http_request *req, int status, void *base,
    654     size_t len, int (*cb)(struct netbuf *), void *arg)
    655 {
    656 	struct netbuf		*nb;
    657 
    658 	if (req->owner == NULL)
    659 		return;
    660 
    661 	req->status = status;
    662 
    663 	switch (req->owner->proto) {
    664 	case CONN_PROTO_HTTP:
    665 		http_response_normal(req, req->owner, status, NULL, len);
    666 		break;
    667 	default:
    668 		fatal("%s: bad proto %d", __func__, req->owner->proto);
    669 		/* NOTREACHED. */
    670 	}
    671 
    672 	net_send_stream(req->owner, base, len, cb, &nb);
    673 	nb->extra = arg;
    674 
    675 	if (req->method == HTTP_METHOD_HEAD) {
    676 		nb->s_off = nb->b_len;
    677 		net_remove_netbuf(req->owner, nb);
    678 	}
    679 }
    680 
    681 void
    682 http_response_fileref(struct http_request *req, int status,
    683     struct kore_fileref *ref)
    684 {
    685 	struct tm	*tm;
    686 	time_t		mtime;
    687 	char		tbuf[128];
    688 	const char	*media_type, *modified;
    689 
    690 	if (req->owner == NULL)
    691 		return;
    692 
    693 	media_type = http_media_type(ref->path);
    694 	if (media_type != NULL)
    695 		http_response_header(req, "content-type", media_type);
    696 
    697 	if (http_request_header(req, "if-modified-since", &modified)) {
    698 		mtime = kore_date_to_time(modified);
    699 		if (mtime == ref->mtime_sec) {
    700 			kore_fileref_release(ref);
    701 			http_response(req, HTTP_STATUS_NOT_MODIFIED, NULL, 0);
    702 			return;
    703 		}
    704 	}
    705 
    706 	if ((tm = gmtime(&ref->mtime_sec)) != NULL) {
    707 		if (strftime(tbuf, sizeof(tbuf),
    708 		    "%a, %d %b %Y %H:%M:%S GMT", tm) > 0) {
    709 			http_response_header(req, "last-modified", tbuf);
    710 		}
    711 	}
    712 
    713 	req->status = status;
    714 	switch (req->owner->proto) {
    715 	case CONN_PROTO_HTTP:
    716 		http_response_normal(req, req->owner, status, NULL, ref->size);
    717 		break;
    718 	default:
    719 		fatal("http_response_fd() bad proto %d", req->owner->proto);
    720 		/* NOTREACHED. */
    721 	}
    722 
    723 	if (req->method != HTTP_METHOD_HEAD)
    724 		net_send_fileref(req->owner, ref);
    725 	else
    726 		kore_fileref_release(ref);
    727 }
    728 
    729 int
    730 http_request_header(struct http_request *req, const char *header,
    731     const char **out)
    732 {
    733 	struct http_header	*hdr;
    734 
    735 	TAILQ_FOREACH(hdr, &(req->req_headers), list) {
    736 		if (!strcasecmp(hdr->header, header)) {
    737 			*out = hdr->value;
    738 			return (KORE_RESULT_OK);
    739 		}
    740 	}
    741 
    742 	if (!strcasecmp(header, "host")) {
    743 		*out = req->host;
    744 		return (KORE_RESULT_OK);
    745 	}
    746 
    747 	return (KORE_RESULT_ERROR);
    748 }
    749 
    750 int
    751 http_request_header_get(struct http_request *req, const char *header,
    752     void **out, void *nout, int type)
    753 {
    754 	struct http_header	*hdr;
    755 
    756 	if (type == HTTP_ARG_TYPE_STRING)
    757 		fatal("%s: cannot be called with type string", __func__);
    758 
    759 	TAILQ_FOREACH(hdr, &req->req_headers, list) {
    760 		if (strcasecmp(hdr->header, header))
    761 			continue;
    762 
    763 		if (http_data_convert(hdr->value, out, nout, type))
    764 			return (KORE_RESULT_OK);
    765 
    766 		return (KORE_RESULT_ERROR);
    767 	}
    768 
    769 	return (KORE_RESULT_ERROR);
    770 }
    771 
    772 int
    773 http_request_cookie(struct http_request *req, const char *cookie, char **out)
    774 {
    775 	struct http_cookie	*ck;
    776 
    777 	TAILQ_FOREACH(ck, &(req->req_cookies), list) {
    778 		if (!strcasecmp(ck->name, cookie)) {
    779 			*out = ck->value;
    780 			return (KORE_RESULT_OK);
    781 		}
    782 	}
    783 
    784 	return (KORE_RESULT_ERROR);
    785 }
    786 
    787 int
    788 http_header_recv(struct netbuf *nb)
    789 {
    790 	struct connection	*c;
    791 	size_t			len;
    792 	struct http_header	*hdr;
    793 	struct http_request	*req;
    794 	u_int8_t		*end_headers;
    795 	int			h, i, v, skip, l;
    796 	char			*headers[HTTP_REQ_HEADER_MAX];
    797 	char			*value, *host, *request[4], *hbuf;
    798 
    799 	c = nb->owner;
    800 
    801 	if (nb->s_off < 4)
    802 		return (KORE_RESULT_OK);
    803 
    804 	if (!isalpha(nb->buf[0])) {
    805 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    806 		return (KORE_RESULT_ERROR);
    807 	}
    808 
    809 	skip = 4;
    810 	end_headers = kore_mem_find(nb->buf, nb->s_off, "\r\n\r\n", 4);
    811 	if (end_headers == NULL) {
    812 		end_headers = kore_mem_find(nb->buf, nb->s_off, "\n\n", 2);
    813 		if (end_headers == NULL) {
    814 			if (nb->s_off == http_header_max) {
    815 				http_error_response(c,
    816 				    HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE);
    817 				return (KORE_RESULT_ERROR);
    818 			}
    819 			return (KORE_RESULT_OK);
    820 		}
    821 		skip = 2;
    822 	}
    823 
    824 	*end_headers = '\0';
    825 	end_headers += skip;
    826 	len = end_headers - nb->buf;
    827 	hbuf = (char *)nb->buf;
    828 
    829 	h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX);
    830 	if (h < 2) {
    831 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    832 		return (KORE_RESULT_OK);
    833 	}
    834 
    835 	v = kore_split_string(headers[0], " ", request, 4);
    836 	if (v != 3) {
    837 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    838 		return (KORE_RESULT_OK);
    839 	}
    840 
    841 	skip = 0;
    842 	host = NULL;
    843 	for (i = 0; i < h; i++) {
    844 		if (strncasecmp(headers[i], "host", 4))
    845 			continue;
    846 
    847 		if ((host = http_validate_header(headers[i])) == NULL) {
    848 			http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    849 			return (KORE_RESULT_OK);
    850 		}
    851 
    852 		if (*host == '\0') {
    853 			http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    854 			return (KORE_RESULT_OK);
    855 		}
    856 
    857 		skip = i;
    858 		break;
    859 	}
    860 
    861 	if (host == NULL) {
    862 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    863 		return (KORE_RESULT_OK);
    864 	}
    865 
    866 	req = http_request_new(c, host, request[0], request[1], request[2]);
    867 	if (req == NULL)
    868 		return (KORE_RESULT_OK);
    869 
    870 	/* take full ownership of the buffer. */
    871 	req->headers = nb->buf;
    872 	nb->buf = NULL;
    873 	nb->m_len = 0;
    874 
    875 	for (i = 1; i < h; i++) {
    876 		if (i == skip)
    877 			continue;
    878 
    879 		if ((value = http_validate_header(headers[i])) == NULL) {
    880 			req->flags |= HTTP_REQUEST_DELETE;
    881 			http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    882 			return (KORE_RESULT_OK);
    883 		}
    884 
    885 		if (*value == '\0') {
    886 			req->flags |= HTTP_REQUEST_DELETE;
    887 			http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    888 			return (KORE_RESULT_OK);
    889 		}
    890 
    891 		hdr = kore_pool_get(&http_header_pool);
    892 		hdr->header = headers[i];
    893 		hdr->value = value;
    894 		TAILQ_INSERT_TAIL(&(req->req_headers), hdr, list);
    895 
    896 		if (req->agent == NULL &&
    897 		    !strcasecmp(hdr->header, "user-agent"))
    898 			req->agent = hdr->value;
    899 
    900 		if (req->referer == NULL &&
    901 		    !strcasecmp(hdr->header, "referer"))
    902 			req->referer = hdr->value;
    903 	}
    904 
    905 	if (req->flags & HTTP_REQUEST_EXPECT_BODY) {
    906 		if (http_body_max == 0) {
    907 			req->flags |= HTTP_REQUEST_DELETE;
    908 			http_error_response(req->owner,
    909 			    HTTP_STATUS_METHOD_NOT_ALLOWED);
    910 			return (KORE_RESULT_OK);
    911 		}
    912 
    913 		if (!http_request_header_uint64(req, "content-length",
    914 		    &req->content_length)) {
    915 			if (req->method == HTTP_METHOD_DELETE) {
    916 				req->flags |= HTTP_REQUEST_COMPLETE;
    917 				return (KORE_RESULT_OK);
    918 			}
    919 
    920 			req->flags |= HTTP_REQUEST_DELETE;
    921 			http_error_response(req->owner,
    922 			    HTTP_STATUS_LENGTH_REQUIRED);
    923 			return (KORE_RESULT_OK);
    924 		}
    925 
    926 		if (req->content_length == 0) {
    927 			c->http_timeout = 0;
    928 			req->flags |= HTTP_REQUEST_COMPLETE;
    929 			req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
    930 			return (KORE_RESULT_OK);
    931 		}
    932 
    933 		if (req->content_length > http_body_max) {
    934 			req->flags |= HTTP_REQUEST_DELETE;
    935 			http_error_response(req->owner,
    936 			    HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE);
    937 			return (KORE_RESULT_OK);
    938 		}
    939 
    940 		req->http_body_length = req->content_length;
    941 
    942 		if (req->rt->on_body_chunk == NULL &&
    943 		    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 if (req->rt->on_body_chunk == NULL) {
    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->rt->on_body_chunk != NULL) {
   2342 		if (kore_runtime_http_body_chunk(req->rt->on_body_chunk,
   2343 		    req, data, len) != KORE_RESULT_OK) {
   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_fd != -1) {
   2350 		ret = write(req->http_body_fd, data, len);
   2351 		if (ret == -1 || (size_t)ret != len) {
   2352 			req->flags |= HTTP_REQUEST_DELETE;
   2353 			http_error_response(req->owner,
   2354 			    HTTP_STATUS_INTERNAL_ERROR);
   2355 			return (KORE_RESULT_ERROR);
   2356 		}
   2357 	} else if (req->http_body != NULL) {
   2358 		kore_buf_append(req->http_body, data, len);
   2359 	} else {
   2360 		req->flags |= HTTP_REQUEST_DELETE;
   2361 		http_error_response(req->owner,
   2362 		    HTTP_STATUS_INTERNAL_ERROR);
   2363 		return (KORE_RESULT_ERROR);
   2364 	}
   2365 
   2366 	req->content_length -= len;
   2367 
   2368 	if (req->content_length == 0) {
   2369 		req->owner->http_timeout = 0;
   2370 		req->owner->rnb->extra = NULL;
   2371 		http_request_wakeup(req);
   2372 		req->flags |= HTTP_REQUEST_COMPLETE;
   2373 		req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
   2374 		req->content_length = req->http_body_length;
   2375 		if (!http_body_rewind(req)) {
   2376 			req->flags |= HTTP_REQUEST_DELETE;
   2377 			http_error_response(req->owner,
   2378 			    HTTP_STATUS_INTERNAL_ERROR);
   2379 			return (KORE_RESULT_ERROR);
   2380 		}
   2381 		SHA256Final(req->http_body_digest, &req->hashctx);
   2382 	} else {
   2383 		bytes_left = req->content_length;
   2384 		net_recv_reset(req->owner,
   2385 		    MIN(bytes_left, NETBUF_SEND_PAYLOAD_MAX),
   2386 		    http_body_recv);
   2387 		req->owner->rnb->extra = req;
   2388 	}
   2389 
   2390 	return (KORE_RESULT_OK);
   2391 }
   2392 
   2393 static void
   2394 http_error_response(struct connection *c, int status)
   2395 {
   2396 	c->flags |= CONN_CLOSE_EMPTY;
   2397 
   2398 	switch (c->proto) {
   2399 	case CONN_PROTO_HTTP:
   2400 		http_response_normal(NULL, c, status, NULL, 0);
   2401 		break;
   2402 	default:
   2403 		fatal("http_error_response() bad proto %d", c->proto);
   2404 		/* NOTREACHED. */
   2405 	}
   2406 
   2407 	if (!net_send_flush(c))
   2408 		kore_connection_disconnect(c);
   2409 }
   2410 
   2411 static void
   2412 http_response_normal(struct http_request *req, struct connection *c,
   2413     int status, const void *d, size_t len)
   2414 {
   2415 	struct kore_buf		buf;
   2416 	struct http_cookie	*ck;
   2417 	struct http_header	*hdr;
   2418 	char			version;
   2419 	const char		*conn, *text;
   2420 	int			connection_close, send_body;
   2421 
   2422 	send_body = 1;
   2423 	text = http_status_text(status);
   2424 
   2425 	kore_buf_reset(header_buf);
   2426 
   2427 	if (req != NULL) {
   2428 		if (req->flags & HTTP_VERSION_1_0)
   2429 			version = '0';
   2430 		else
   2431 			version = '1';
   2432 	} else {
   2433 		version = '1';
   2434 	}
   2435 
   2436 	kore_buf_appendf(header_buf, "HTTP/1.%c %d %s\r\n",
   2437 	    version, status, text);
   2438 
   2439 	if (status == 100) {
   2440 		kore_buf_append(header_buf, "\r\n", 2);
   2441 		net_send_queue(c, header_buf->data, header_buf->offset);
   2442 		return;
   2443 	}
   2444 
   2445 	kore_buf_append(header_buf, http_version, http_version_len);
   2446 
   2447 	if ((c->flags & CONN_CLOSE_EMPTY) ||
   2448 	    (req != NULL && (req->flags & HTTP_VERSION_1_0))) {
   2449 		connection_close = 1;
   2450 	} else {
   2451 		connection_close = 0;
   2452 	}
   2453 
   2454 	if (connection_close == 0 && req != NULL) {
   2455 		if (http_request_header(req, "connection", &conn)) {
   2456 			if ((*conn == 'c' || *conn == 'C') &&
   2457 			    !strcasecmp(conn, "close")) {
   2458 				connection_close = 1;
   2459 			}
   2460 		}
   2461 	}
   2462 
   2463 	kore_buf_init(&buf, 1024);
   2464 
   2465 	/* Note that req CAN be NULL. */
   2466 	if (req == NULL || req->owner->proto != CONN_PROTO_WEBSOCKET) {
   2467 		if (http_keepalive_time && connection_close == 0) {
   2468 			kore_buf_appendf(header_buf,
   2469 			    "connection: keep-alive\r\n");
   2470 			kore_buf_appendf(header_buf,
   2471 			    "keep-alive: timeout=%d\r\n", http_keepalive_time);
   2472 		} else {
   2473 			c->flags |= CONN_CLOSE_EMPTY;
   2474 			kore_buf_appendf(header_buf, "connection: close\r\n");
   2475 		}
   2476 	}
   2477 
   2478 	if (c->tls && http_hsts_enable) {
   2479 		kore_buf_appendf(header_buf, "strict-transport-security: ");
   2480 		kore_buf_appendf(header_buf,
   2481 		    "max-age=%" PRIu64 "; includeSubDomains\r\n",
   2482 		    http_hsts_enable);
   2483 	}
   2484 
   2485 	if (http_pretty_error && d == NULL && status >= 400) {
   2486 		kore_buf_appendf(&buf, pretty_error_fmt,
   2487 		    status, text, status, text);
   2488 
   2489 		d = buf.data;
   2490 		len = buf.offset;
   2491 	}
   2492 
   2493 	if (req != NULL) {
   2494 		TAILQ_FOREACH(ck, &(req->resp_cookies), list)
   2495 			http_write_response_cookie(ck);
   2496 
   2497 		TAILQ_FOREACH(hdr, &(req->resp_headers), list) {
   2498 			kore_buf_appendf(header_buf, "%s: %s\r\n",
   2499 			    hdr->header, hdr->value);
   2500 		}
   2501 
   2502 		if (status != 204 && status >= 200 &&
   2503 		    !(req->flags & HTTP_REQUEST_NO_CONTENT_LENGTH)) {
   2504 			kore_buf_appendf(header_buf,
   2505 			    "content-length: %zu\r\n", len);
   2506 		}
   2507 	} else {
   2508 		if (status != 204 && status >= 200) {
   2509 			kore_buf_appendf(header_buf,
   2510 			    "content-length: %zu\r\n", len);
   2511 		}
   2512 	}
   2513 
   2514 	kore_buf_append(header_buf, "\r\n", 2);
   2515 	net_send_queue(c, header_buf->data, header_buf->offset);
   2516 
   2517 	if (req != NULL && req->method == HTTP_METHOD_HEAD)
   2518 		send_body = 0;
   2519 
   2520 	if (d != NULL && send_body)
   2521 		net_send_queue(c, d, len);
   2522 
   2523 	if (!(c->flags & CONN_CLOSE_EMPTY) && !(c->flags & CONN_IS_BUSY))
   2524 		http_start_recv(c);
   2525 
   2526 	if (req != NULL)
   2527 		req->content_length = len;
   2528 
   2529 	kore_buf_cleanup(&buf);
   2530 }
   2531 
   2532 static void
   2533 http_write_response_cookie(struct http_cookie *ck)
   2534 {
   2535 	struct tm		tm;
   2536 	char			expires[HTTP_DATE_MAXSIZE];
   2537 
   2538 	kore_buf_reset(ckhdr_buf);
   2539 	kore_buf_appendf(ckhdr_buf, "%s=%s", ck->name, ck->value);
   2540 
   2541 	if (ck->path != NULL)
   2542 		kore_buf_appendf(ckhdr_buf, "; Path=%s", ck->path);
   2543 	if (ck->domain != NULL)
   2544 		kore_buf_appendf(ckhdr_buf, "; Domain=%s", ck->domain);
   2545 
   2546 	if (ck->expires > 0) {
   2547 		if (gmtime_r(&ck->expires, &tm) == NULL) {
   2548 			kore_log(LOG_ERR, "gmtime_r(): %s", errno_s);
   2549 			return;
   2550 		}
   2551 
   2552 		if (strftime(expires, sizeof(expires),
   2553 		    "%a, %d %b %y %H:%M:%S GMT", &tm) == 0) {
   2554 			kore_log(LOG_ERR, "strftime(): %s", errno_s);
   2555 			return;
   2556 		}
   2557 
   2558 		kore_buf_appendf(ckhdr_buf, "; Expires=%s", expires);
   2559 	}
   2560 
   2561 	if (ck->maxage > 0)
   2562 		kore_buf_appendf(ckhdr_buf, "; Max-Age=%u", ck->maxage);
   2563 
   2564 	if (ck->flags & HTTP_COOKIE_HTTPONLY)
   2565 		kore_buf_appendf(ckhdr_buf, "; HttpOnly");
   2566 	if (ck->flags & HTTP_COOKIE_SECURE)
   2567 		kore_buf_appendf(ckhdr_buf, "; Secure");
   2568 
   2569 	kore_buf_appendf(header_buf, "set-cookie: %s\r\n",
   2570 	    kore_buf_stringify(ckhdr_buf, NULL));
   2571 }
   2572 
   2573 static int
   2574 http_data_convert(void *data, void **out, void *nout, int type)
   2575 {
   2576 	switch (type) {
   2577 	case HTTP_ARG_TYPE_RAW:
   2578 	case HTTP_ARG_TYPE_STRING:
   2579 		*out = data;
   2580 		return (KORE_RESULT_OK);
   2581 	case HTTP_ARG_TYPE_BYTE:
   2582 		COPY_ARG_TYPE(*(u_int8_t *)data, u_int8_t);
   2583 		return (KORE_RESULT_OK);
   2584 	case HTTP_ARG_TYPE_INT16:
   2585 		COPY_AS_INTTYPE(SHRT_MIN, SHRT_MAX, int16_t);
   2586 		return (KORE_RESULT_OK);
   2587 	case HTTP_ARG_TYPE_UINT16:
   2588 		COPY_AS_INTTYPE(0, USHRT_MAX, u_int16_t);
   2589 		return (KORE_RESULT_OK);
   2590 	case HTTP_ARG_TYPE_INT32:
   2591 		COPY_AS_INTTYPE(INT_MIN, INT_MAX, int32_t);
   2592 		return (KORE_RESULT_OK);
   2593 	case HTTP_ARG_TYPE_UINT32:
   2594 		COPY_AS_INTTYPE(0, UINT_MAX, u_int32_t);
   2595 		return (KORE_RESULT_OK);
   2596 	case HTTP_ARG_TYPE_INT64:
   2597 		COPY_AS_INTTYPE_64(int64_t, 1);
   2598 		return (KORE_RESULT_OK);
   2599 	case HTTP_ARG_TYPE_UINT64:
   2600 		COPY_AS_INTTYPE_64(u_int64_t, 0);
   2601 		return (KORE_RESULT_OK);
   2602 	case HTTP_ARG_TYPE_FLOAT:
   2603 		COPY_ARG_DOUBLE(-FLT_MAX, FLT_MAX, float);
   2604 		return (KORE_RESULT_OK);
   2605 	case HTTP_ARG_TYPE_DOUBLE:
   2606 		COPY_ARG_DOUBLE(-DBL_MAX, DBL_MAX, double);
   2607 		return (KORE_RESULT_OK);
   2608 	default:
   2609 		break;
   2610 	}
   2611 
   2612 	return (KORE_RESULT_ERROR);
   2613 }