varnish-cache/bin/varnishd/cache/cache_http.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2017 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 * HTTP request storage and manipulation
31
 */
32
33
#include "config.h"
34
35
#include "cache_varnishd.h"
36
#include <stdio.h>
37
#include <stdlib.h>
38
39
#include "common/heritage.h"
40
41
#include "vct.h"
42
#include "vend.h"
43
#include "vnum.h"
44
#include "vtim.h"
45
46
#define BODYSTATUS(U, l, n, a, k)                               \
47
        const struct body_status BS_##U[1] = {{                 \
48
                .name = #l,                                     \
49
                .nbr = n,                                       \
50
                .avail = a,                                     \
51
                .length_known = k                               \
52
        }};
53
#include "tbl/body_status.h"
54
55
56
#define HTTPH(a, b, c) char b[] = "*" a ":";
57
#include "tbl/http_headers.h"
58
59
const char H__Status[]  = "\010:status:";
60
const char H__Proto[]   = "\007:proto:";
61
const char H__Reason[]  = "\010:reason:";
62
63
static char * via_hdr;
64
65
/*--------------------------------------------------------------------
66
 * Perfect hash to rapidly recognize headers from tbl/http_headers.h
67
 * which have non-zero flags.
68
 *
69
 * A suitable algorithm can be found with `gperf`:
70
 *
71
 *      tr '" ,' '   ' < include/tbl/http_headers.h |
72
 *              awk '$1 == "H(" {print $2}' |
73
 *              gperf --ignore-case
74
 *
75
 */
76
77
#define GPERF_MIN_WORD_LENGTH 2
78
#define GPERF_MAX_WORD_LENGTH 19
79
#define GPERF_MAX_HASH_VALUE 79
80
81
static const unsigned char http_asso_values[256] = {
82
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
83
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
84
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
85
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
86
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
87
        80, 80, 80,  0, 80, 80, 80, 80, 80, 80,
88
        80, 80, 80, 80, 80,  5, 80, 20,  0,  0,
89
        5, 10,  5,  5, 80,  0, 15,  0, 20, 80,
90
        40, 80,  0, 35, 10, 20, 55, 45,  0,  0,
91
        80, 80, 80, 80, 80, 80, 80,  5, 80, 20,
92
        0,  0,  5, 10,  5,  5, 80,  0, 15,  0,
93
        20, 80, 40, 80,  0, 35, 10, 20, 55, 45,
94
        0,  0, 80, 80, 80, 80, 80, 80, 80, 80,
95
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
96
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
97
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
98
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
99
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
100
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
101
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
102
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
103
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
104
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
105
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
106
        80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
107
        80, 80, 80, 80, 80, 80
108
};
109
110
static struct http_hdrflg {
111
        char            *hdr;
112
        unsigned        flag;
113
} http_hdrflg[GPERF_MAX_HASH_VALUE + 1] = {
114
        { NULL }, { NULL }, { NULL }, { NULL },
115
        { H_Date },
116
        { H_Range },
117
        { NULL },
118
        { H_Referer },
119
        { H_Age },
120
        { H_From },
121
        { H_Keep_Alive },
122
        { H_Retry_After },
123
        { H_TE },
124
        { H_If_Range },
125
        { H_ETag },
126
        { H_X_Forwarded_For },
127
        { H_Expect },
128
        { H_Trailer },
129
        { H_If_Match },
130
        { H_Host },
131
        { H_Accept_Language },
132
        { H_Accept },
133
        { H_If_Modified_Since },
134
        { H_If_None_Match },
135
        { H_If_Unmodified_Since },
136
        { NULL },
137
        { H_Cookie },
138
        { H_Upgrade },
139
        { H_Last_Modified },
140
        { H_Accept_Charset },
141
        { H_Accept_Encoding },
142
        { H_Content_MD5 },
143
        { H_Content_Type },
144
        { H_Content_Range },
145
        { NULL }, { NULL },
146
        { H_Content_Language },
147
        { H_Transfer_Encoding },
148
        { H_Authorization },
149
        { H_Content_Length },
150
        { H_User_Agent },
151
        { H_Server },
152
        { H_Expires },
153
        { H_Location },
154
        { NULL },
155
        { H_Set_Cookie },
156
        { H_Content_Encoding },
157
        { H_Max_Forwards },
158
        { H_Cache_Control },
159
        { NULL },
160
        { H_Connection },
161
        { H_Pragma },
162
        { NULL },
163
        { H_Accept_Ranges },
164
        { H_HTTP2_Settings },
165
        { H_Allow },
166
        { H_Content_Location },
167
        { NULL },
168
        { H_Proxy_Authenticate },
169
        { H_Vary },
170
        { NULL },
171
        { H_WWW_Authenticate },
172
        { H_Warning },
173
        { H_Via },
174
        { NULL }, { NULL }, { NULL }, { NULL },
175
        { NULL }, { NULL }, { NULL }, { NULL },
176
        { NULL }, { NULL }, { NULL }, { NULL },
177
        { NULL }, { NULL }, { NULL },
178
        { H_Proxy_Authorization }
179
};
180
181
static struct http_hdrflg *
182 369378
http_hdr_flags(const char *b, const char *e)
183
{
184
        unsigned u;
185
        struct http_hdrflg *retval;
186
187 369378
        if (b == NULL || e == NULL)
188 36
                return (NULL);
189 369378
        assert(b <= e);
190 369378
        u = (unsigned)(e - b);
191 369378
        assert(b + u == e);
192 369378
        if (u < GPERF_MIN_WORD_LENGTH || u > GPERF_MAX_WORD_LENGTH)
193 145
                return (NULL);
194 738466
        u += http_asso_values[(uint8_t)(e[-1])] +
195 369233
             http_asso_values[(uint8_t)(b[0])];
196 369233
        if (u > GPERF_MAX_HASH_VALUE)
197 5015
                return (NULL);
198 364218
        retval = &http_hdrflg[u];
199 364218
        if (retval->hdr == NULL)
200 1298
                return (NULL);
201 362920
        if (!http_hdr_at(retval->hdr + 1, b, e - b))
202 4595
                return (NULL);
203 358325
        return (retval);
204 369378
}
205
206
/*--------------------------------------------------------------------*/
207
208
static void
209 239876
http_init_hdr(char *hdr, int flg)
210
{
211
        struct http_hdrflg *f;
212
213 239876
        hdr[0] = strlen(hdr + 1);
214 239876
        f = http_hdr_flags(hdr + 1, hdr + hdr[0]);
215 239876
        AN(f);
216 239876
        assert(f->hdr == hdr);
217 239876
        f->flag = flg;
218 239876
}
219
220
void
221 4613
HTTP_Init(void)
222
{
223
        struct vsb *vsb;
224
225
#define HTTPH(a, b, c) http_init_hdr(b, c);
226
#include "tbl/http_headers.h"
227
228
        vsb = VSB_new_auto();
229 4613
        AN(vsb);
230
        VSB_printf(vsb, "1.1 %s (Varnish/" PACKAGE_BRANCH ")",
231
            heritage.identity);
232 4613
        AZ(VSB_finish(vsb));
233 4613
        REPLACE(via_hdr, VSB_data(vsb));
234
        VSB_destroy(&vsb);
235
}
236
237
/*--------------------------------------------------------------------
238
 * These two functions are in an incestuous relationship with the
239
 * order of macros in include/tbl/vsl_tags_http.h
240
 *
241
 * The http->logtag is the SLT_*Method enum, and we add to that, to
242
 * get the SLT_ to use.
243
 */
244
245
static void
246 608058
http_VSLH(const struct http *hp, unsigned hdr)
247
{
248
        int i;
249
250 608058
        if (hp->vsl != NULL) {
251 608073
                assert(VXID_TAG(hp->vsl->wid));
252 608073
                i = hdr;
253 608073
                if (i > HTTP_HDR_FIRST)
254 319453
                        i = HTTP_HDR_FIRST;
255 608073
                i += hp->logtag;
256 608073
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
257 608073
        }
258 608096
}
259
260
static void
261 4695
http_VSLH_del(const struct http *hp, unsigned hdr)
262
{
263
        int i;
264
265 4695
        if (hp->vsl != NULL) {
266
                /* We don't support unsetting stuff in the first line */
267 4695
                assert (hdr >= HTTP_HDR_FIRST);
268 4695
                assert(VXID_TAG(hp->vsl->wid));
269 4695
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
270 4695
                i += hp->logtag;
271 4695
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
272 4695
        }
273 4695
}
274
275
/*--------------------------------------------------------------------*/
276
277
void
278 28350
http_VSL_log(const struct http *hp)
279
{
280
        unsigned u;
281
282 247786
        for (u = 0; u < hp->nhd; u++)
283 382179
                if (hp->hd[u].b != NULL)
284 162743
                        http_VSLH(hp, u);
285 28350
}
286
287
/*--------------------------------------------------------------------*/
288
289
static void
290 520
http_fail(const struct http *hp)
291
{
292
        char id[WS_ID_SIZE];
293
294 520
        VSC_C_main->losthdr++;
295 520
        WS_Id(hp->ws, id);
296 520
        VSLb(hp->vsl, SLT_Error, "out of workspace (%s)", id);
297 520
        WS_MarkOverflow(hp->ws);
298 520
}
299
300
/*--------------------------------------------------------------------
301
 * List of canonical HTTP response code names from RFC2616
302
 */
303
304
static struct http_msg {
305
        unsigned        nbr;
306
        const char      *status;
307
        const char      *txt;
308
} http_msg[] = {
309
#define HTTP_RESP(n, t) { n, #n, t},
310
#include "tbl/http_response.h"
311
        { 0, "0", NULL }
312
};
313
314
const char *
315 7179
http_Status2Reason(unsigned status, const char **sstr)
316
{
317
        struct http_msg *mp;
318
319 7179
        status %= 1000;
320 7179
        assert(status >= 100);
321 221569
        for (mp = http_msg; mp->nbr != 0 && mp->nbr <= status; mp++)
322 221344
                if (mp->nbr == status) {
323 6954
                        if (sstr)
324 5325
                                *sstr = mp->status;
325 6954
                        return (mp->txt);
326
                }
327 225
        return ("Unknown HTTP Status");
328 7179
}
329
330
/*--------------------------------------------------------------------*/
331
332
unsigned
333 25924
HTTP_estimate(unsigned nhttp)
334
{
335
336
        /* XXX: We trust the structs to size-aligned as necessary */
337 25924
        return (PRNDUP(sizeof(struct http) + sizeof(txt) * nhttp + nhttp));
338
}
339
340
struct http *
341 77775
HTTP_create(void *p, uint16_t nhttp, unsigned len)
342
{
343
        struct http *hp;
344
345 77775
        hp = p;
346 77775
        hp->magic = HTTP_MAGIC;
347 77775
        hp->hd = (void*)(hp + 1);
348 77775
        hp->shd = nhttp;
349 77775
        hp->hdf = (void*)(hp->hd + nhttp);
350 77775
        assert((unsigned char*)p + len == hp->hdf + PRNDUP(nhttp));
351 77775
        return (hp);
352
}
353
354
/*--------------------------------------------------------------------*/
355
356
void
357 72468
HTTP_Setup(struct http *hp, struct ws *ws, struct vsl_log *vsl,
358
    enum VSL_tag_e  whence)
359
{
360 72468
        http_Teardown(hp);
361 72468
        hp->nhd = HTTP_HDR_FIRST;
362 72468
        hp->logtag = whence;
363 72468
        hp->ws = ws;
364 72468
        hp->vsl = vsl;
365 72468
}
366
367
/*--------------------------------------------------------------------
368
 * http_Teardown() is a safety feature, we use it to zap all http
369
 * structs once we're done with them, to minimize the risk that
370
 * old stale pointers exist to no longer valid stuff.
371
 */
372
373
void
374 113159
http_Teardown(struct http *hp)
375
{
376
377 113159
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
378 113159
        AN(hp->shd);
379 113159
        memset(&hp->nhd, 0, sizeof *hp - offsetof(struct http, nhd));
380 113159
        memset(hp->hd, 0, sizeof *hp->hd * hp->shd);
381 113159
        memset(hp->hdf, 0, sizeof *hp->hdf * hp->shd);
382 113159
}
383
384
/*--------------------------------------------------------------------
385
 * Duplicate the http content into another http
386
 * We cannot just memcpy the struct because the hd & hdf are private
387
 * storage to the struct http.
388
 */
389
390
void
391 31863
HTTP_Dup(struct http *to, const struct http * fm)
392
{
393
394 31863
        assert(fm->nhd <= to->shd);
395 31863
        memcpy(to->hd, fm->hd, fm->nhd * sizeof *to->hd);
396 31863
        memcpy(to->hdf, fm->hdf, fm->nhd * sizeof *to->hdf);
397 31863
        to->nhd = fm->nhd;
398 31863
        to->logtag = fm->logtag;
399 31863
        to->status = fm->status;
400 31863
        to->protover = fm->protover;
401 31863
}
402
403
404
/*--------------------------------------------------------------------
405
 * Clone the entire http structure, including vsl & ws
406
 */
407
408
void
409 30032
HTTP_Clone(struct http *to, const struct http * const fm)
410
{
411
412 30032
        HTTP_Dup(to, fm);
413 30032
        to->vsl = fm->vsl;
414 30032
        to->ws = fm->ws;
415 30032
}
416
417
/*--------------------------------------------------------------------*/
418
419
void
420 32402
http_Proto(struct http *to)
421
{
422
        const char *fm;
423
424 32402
        fm = to->hd[HTTP_HDR_PROTO].b;
425
426 64761
        if (fm != NULL &&
427 32363
            (fm[0] == 'H' || fm[0] == 'h') &&
428 32358
            (fm[1] == 'T' || fm[1] == 't') &&
429 32358
            (fm[2] == 'T' || fm[2] == 't') &&
430 32358
            (fm[3] == 'P' || fm[3] == 'p') &&
431 32358
            fm[4] == '/' &&
432 32358
            vct_isdigit(fm[5]) &&
433 32358
            fm[6] == '.' &&
434 32358
            vct_isdigit(fm[7]) &&
435 32359
            fm[8] == '\0') {
436 32359
                to->protover = 10 * (fm[5] - '0') + (fm[7] - '0');
437 32359
        } else {
438 45
                to->protover = 0;
439
        }
440 32404
}
441
442
/*--------------------------------------------------------------------*/
443
444
void
445 192174
http_SetH(struct http *to, unsigned n, const char *header)
446
{
447
448 192174
        assert(n < to->nhd);
449 192174
        AN(header);
450 192174
        to->hd[n].b = TRUST_ME(header);
451 192174
        to->hd[n].e = strchr(to->hd[n].b, '\0');
452 192174
        to->hdf[n] = 0;
453 192174
        http_VSLH(to, n);
454 192174
        if (n == HTTP_HDR_PROTO)
455 6544
                http_Proto(to);
456 192174
}
457
458
/*--------------------------------------------------------------------*/
459
460
static void
461 180
http_PutField(struct http *to, int field, const char *string)
462
{
463
        const char *p;
464
465 180
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
466 180
        p = WS_Copy(to->ws, string, -1);
467 180
        if (p == NULL) {
468 5
                http_fail(to);
469 5
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(string));
470 5
                return;
471
        }
472 175
        http_SetH(to, field, p);
473 180
}
474
475
/*--------------------------------------------------------------------*/
476
477
int
478 573541
http_IsHdr(const txt *hh, hdr_t hdr)
479
{
480
        unsigned l;
481
482 573541
        Tcheck(*hh);
483 573541
        AN(hdr);
484 573541
        l = hdr[0];
485 573541
        assert(l == strlen(hdr + 1));
486 573541
        assert(hdr[l] == ':');
487 573541
        hdr++;
488 573541
        return (http_hdr_at(hdr, hh->b, l));
489
}
490
491
/*--------------------------------------------------------------------*/
492
493
static unsigned
494 733001
http_findhdr(const struct http *hp, unsigned l, const char *hdr)
495
{
496
        unsigned u;
497
498 3164776
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
499 2593065
                Tcheck(hp->hd[u]);
500 2593065
                if (hp->hd[u].e < hp->hd[u].b + l + 1)
501 475177
                        continue;
502 2117888
                if (hp->hd[u].b[l] != ':')
503 1781845
                        continue;
504 336043
                if (!http_hdr_at(hdr, hp->hd[u].b, l))
505 174753
                        continue;
506 161290
                return (u);
507
        }
508 571711
        return (0);
509 733001
}
510
511
/*--------------------------------------------------------------------
512
 * Count how many instances we have of this header
513
 */
514
515
unsigned
516 36620
http_CountHdr(const struct http *hp, hdr_t hdr)
517
{
518 36620
        unsigned retval = 0;
519
        unsigned u;
520
521 36620
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
522
523 122338
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
524 85718
                Tcheck(hp->hd[u]);
525 85718
                if (http_IsHdr(&hp->hd[u], hdr))
526 18190
                        retval++;
527 85718
        }
528 36620
        return (retval);
529
}
530
531
/*--------------------------------------------------------------------
532
 * This function collapses multiple header lines of the same name.
533
 * The lines are joined with a comma, according to [rfc2616, 4.2bot, p32]
534
 */
535
536
void
537 118133
http_CollectHdr(struct http *hp, hdr_t hdr)
538
{
539
540 118133
        http_CollectHdrSep(hp, hdr, NULL);
541 118133
}
542
543
/*--------------------------------------------------------------------
544
 * You may prefer to collapse header fields using a different separator.
545
 * For Cookie headers, the separator is "; " for example. That's probably
546
 * the only example too.
547
 */
548
549
void
550 118770
http_CollectHdrSep(struct http *hp, hdr_t hdr, const char *sep)
551
{
552
        unsigned u, l, lsep, ml, f, x, d;
553 118770
        char *b = NULL, *e = NULL;
554
        const char *v;
555
556 118770
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
557 118770
        if (WS_Overflowed(hp->ws))
558 100
                return;
559
560 118670
        if (sep == NULL || *sep == '\0')
561 118030
                sep = ", ";
562 118672
        lsep = strlen(sep);
563
564 118672
        l = hdr[0];
565 118672
        assert(l == strlen(hdr + 1));
566 118672
        assert(hdr[l] == ':');
567 118672
        f = http_findhdr(hp, l - 1, hdr + 1);
568 118672
        if (f == 0)
569 116624
                return;
570
571 7532
        for (d = u = f + 1; u < hp->nhd; u++) {
572 5484
                Tcheck(hp->hd[u]);
573 5484
                if (!http_IsHdr(&hp->hd[u], hdr)) {
574 5394
                        if (d != u) {
575 355
                                hp->hd[d] = hp->hd[u];
576 355
                                hp->hdf[d] = hp->hdf[u];
577 355
                        }
578 5394
                        d++;
579 5394
                        continue;
580
                }
581 90
                if (b == NULL) {
582
                        /* Found second header, start our collection */
583 80
                        ml = WS_ReserveAll(hp->ws);
584 80
                        b = WS_Reservation(hp->ws);
585 80
                        e = b + ml;
586 80
                        x = Tlen(hp->hd[f]);
587 80
                        if (b + x >= e) {
588 0
                                http_fail(hp);
589 0
                                VSLbs(hp->vsl, SLT_LostHeader,
590 0
                                    TOSTRAND(hdr + 1));
591 0
                                WS_Release(hp->ws, 0);
592 0
                                return;
593
                        }
594 80
                        memcpy(b, hp->hd[f].b, x);
595 80
                        b += x;
596 80
                }
597
598 90
                AN(b);
599 90
                AN(e);
600
601
                /* Append the Nth header we found */
602 90
                x = Tlen(hp->hd[u]) - l;
603
604 90
                v = hp->hd[u].b + *hdr;
605 180
                while (vct_issp(*v)) {
606 90
                        v++;
607 90
                        x--;
608
                }
609
610 90
                if (b + lsep + x >= e) {
611 0
                        http_fail(hp);
612 0
                        VSLbs(hp->vsl, SLT_LostHeader, TOSTRAND(hdr + 1));
613 0
                        WS_Release(hp->ws, 0);
614 0
                        return;
615
                }
616 90
                memcpy(b, sep, lsep);
617 90
                b += lsep;
618 90
                memcpy(b, v, x);
619 90
                b += x;
620 90
        }
621 2048
        if (b == NULL)
622 1968
                return;
623 80
        hp->nhd = (uint16_t)d;
624 80
        AN(e);
625 80
        *b = '\0';
626 80
        hp->hd[f].b = WS_Reservation(hp->ws);
627 80
        hp->hd[f].e = b;
628 80
        WS_ReleaseP(hp->ws, b + 1);
629 118772
}
630
631
/*--------------------------------------------------------------------*/
632
633
int
634 613633
http_GetHdr(const struct http *hp, hdr_t hdr, const char **ptr)
635
{
636
        unsigned u, l;
637
        const char *p;
638
639 613633
        l = hdr[0];
640 613633
        assert(l == strlen(hdr + 1));
641 613633
        assert(hdr[l] == ':');
642 613633
        hdr++;
643 613633
        u = http_findhdr(hp, l - 1, hdr);
644 613633
        if (u == 0) {
645 454782
                if (ptr != NULL)
646 408953
                        *ptr = NULL;
647 454782
                return (0);
648
        }
649 158851
        if (ptr != NULL) {
650 129907
                p = hp->hd[u].b + l;
651 259592
                while (vct_issp(*p))
652 129685
                        p++;
653 129907
                *ptr = p;
654 129907
        }
655 158851
        return (1);
656 613633
}
657
658
/*-----------------------------------------------------------------------------
659
 * Split source string at any of the separators, return pointer to first
660
 * and last+1 char of substrings, with whitespace trimmed at both ends.
661
 * If sep being an empty string is shorthand for VCT::SP
662
 * If stop is NULL, src is NUL terminated.
663
 */
664
665
static int
666 11376
http_split(const char **src, const char *stop, const char *sep,
667
    const char **b, const char **e)
668
{
669
        const char *p, *q;
670
671 11376
        AN(src);
672 11376
        AN(*src);
673 11376
        AN(sep);
674 11376
        AN(b);
675 11376
        AN(e);
676
677 11376
        if (stop == NULL)
678 11341
                stop = strchr(*src, '\0');
679
680 19549
        for (p = *src; p < stop && (vct_issp(*p) || strchr(sep, *p)); p++)
681 435
                continue;
682
683 11376
        if (p >= stop) {
684 4073
                *b = NULL;
685 4073
                *e = NULL;
686 4073
                return (0);
687
        }
688
689 7303
        *b = p;
690 7303
        if (*sep == '\0') {
691 0
                for (q = p + 1; q < stop && !vct_issp(*q); q++)
692 0
                        continue;
693 0
                *e = q;
694 0
                *src = q;
695 0
                return (1);
696
        }
697 35935
        for (q = p + 1; q < stop && !strchr(sep, *q); q++)
698 28632
                continue;
699 7303
        *src = q;
700 7303
        while (q > p && vct_issp(q[-1]))
701 0
                q--;
702 7303
        *e = q;
703 7303
        return (1);
704 11376
}
705
706
/*-----------------------------------------------------------------------------
707
 * Comparison rule for tokens:
708
 *      if target string starts with '"', we use memcmp() and expect closing
709
 *      double quote as well
710
 *      otherwise we use http_tok_at()
711
 *
712
 * On match we increment *bp past the token name.
713
 */
714
715
static int
716 6365
http_istoken(const char **bp, const char *e, const char *token)
717
{
718 6365
        int fl = strlen(token);
719
        const char *b;
720
721 6365
        AN(bp);
722 6365
        AN(e);
723 6365
        AN(token);
724
725 6365
        b = *bp;
726
727 6365
        if (b + fl + 2 <= e && *b == '"' &&
728 0
            !memcmp(b + 1, token, fl) && b[fl + 1] == '"') {
729 0
                *bp += fl + 2;
730 0
                return (1);
731
        }
732 6565
        if (b + fl <= e && http_tok_at(b, token, fl) &&
733 2980
            (b + fl == e || !vct_istchar(b[fl]))) {
734 2980
                *bp += fl;
735 2980
                return (1);
736
        }
737 3385
        return (0);
738 6365
}
739
740
/*-----------------------------------------------------------------------------
741
 * Find a given data element (token) in a header according to RFC2616's #rule
742
 * (section 2.1, p15)
743
 *
744
 * On case sensitivity:
745
 *
746
 * Section 4.2 (Messages Headers) defines field (header) name as case
747
 * insensitive, but the field (header) value/content may be case-sensitive.
748
 *
749
 * http_GetHdrToken looks up a token in a header value and the rfc does not say
750
 * explicitly if tokens are to be compared with or without respect to case.
751
 *
752
 * But all examples and specific statements regarding tokens follow the rule
753
 * that unquoted tokens are to be matched case-insensitively and quoted tokens
754
 * case-sensitively.
755
 *
756
 * The optional pb and pe arguments will point to the token content start and
757
 * end+1, white space trimmed on both sides.
758
 */
759
760
int
761 71556
http_GetHdrToken(const struct http *hp, hdr_t hdr,
762
    const char *token, const char **pb, const char **pe)
763
{
764
        const char *h, *b, *e;
765
766 71556
        if (pb != NULL)
767 54385
                *pb = NULL;
768 71556
        if (pe != NULL)
769 16558
                *pe = NULL;
770 71556
        if (!http_GetHdr(hp, hdr, &h))
771 65376
                return (0);
772 6180
        AN(h);
773
774 9565
        while (http_split(&h, NULL, ",", &b, &e))
775 6365
                if (http_istoken(&b, e, token))
776 2980
                        break;
777 6180
        if (b == NULL)
778 3200
                return (0);
779 2980
        if (pb != NULL) {
780 2960
                for (; vct_islws(*b); b++)
781 25
                        continue;
782 2935
                if (b == e) {
783 2740
                        b = NULL;
784 2740
                        e = NULL;
785 2740
                }
786 2935
                *pb = b;
787 2935
                if (pe != NULL)
788 2705
                        *pe = e;
789 2935
        }
790 2980
        return (1);
791 71556
}
792
793
/*--------------------------------------------------------------------
794
 * Find a given header field's quality value (qvalue).
795
 */
796
797
double
798 16557
http_GetHdrQ(const struct http *hp, hdr_t hdr, const char *field)
799
{
800
        const char *hb, *he, *b, *e;
801
        int i;
802
        double a, f;
803
804 16557
        i = http_GetHdrToken(hp, hdr, field, &hb, &he);
805 16557
        if (!i)
806 13852
                return (0.);
807
808 2705
        if (hb == NULL)
809 2670
                return (1.);
810 35
        while (http_split(&hb, he, ";", &b, &e)) {
811 35
                if (*b != 'q')
812 0
                        continue;
813 35
                for (b++; b < e && vct_issp(*b); b++)
814 0
                        continue;
815 35
                if (b == e || *b != '=')
816 0
                        continue;
817 35
                break;
818
        }
819 35
        if (b == NULL)
820 0
                return (1.);
821 35
        for (b++; b < e && vct_issp(*b); b++)
822 0
                continue;
823 35
        if (b == e || (*b != '.' && !vct_isdigit(*b)))
824 5
                return (0.);
825 30
        a = 0;
826 60
        while (b < e && vct_isdigit(*b)) {
827 30
                a *= 10.;
828 30
                a += *b - '0';
829 30
                b++;
830
        }
831 30
        if (b == e || *b++ != '.')
832 5
                return (a);
833 25
        f = .1;
834 80
        while (b < e && vct_isdigit(*b)) {
835 55
                a += f * (*b - '0');
836 55
                f *= .1;
837 55
                b++;
838
        }
839 25
        return (a);
840 16557
}
841
842
/*--------------------------------------------------------------------
843
 * Find a given header field's value.
844
 */
845
846
int
847 37826
http_GetHdrField(const struct http *hp, hdr_t hdr,
848
    const char *field, const char **ptr)
849
{
850
        const char *h;
851
        int i;
852
853 37826
        if (ptr != NULL)
854 19195
                *ptr = NULL;
855
856 37826
        h = NULL;
857 37826
        i = http_GetHdrToken(hp, hdr, field, &h, NULL);
858 37826
        if (!i)
859 37596
                return (i);
860
861 230
        if (ptr != NULL && h != NULL) {
862
                /* Skip whitespace, looking for '=' */
863 160
                while (*h && vct_issp(*h))
864 0
                        h++;
865 160
                if (*h == '=') {
866 160
                        h++;
867 180
                        while (*h && vct_issp(*h))
868 20
                                h++;
869 160
                        *ptr = h;
870 160
                }
871 160
        }
872 230
        return (i);
873 37826
}
874
875
/*--------------------------------------------------------------------*/
876
877
ssize_t
878 54192
http_GetContentLength(const struct http *hp)
879
{
880
        ssize_t cl;
881
        const char *b;
882
883 54192
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
884
885 54192
        if (!http_GetHdr(hp, H_Content_Length, &b))
886 21224
                return (-1);
887 32968
        cl = VNUM_uint(b, NULL, &b);
888 32968
        if (cl < 0)
889 20
                return (-2);
890 32948
        while (vct_islws(*b))
891 0
                b++;
892 32948
        if (*b != '\0')
893 0
                return (-2);
894 32948
        return (cl);
895 54192
}
896
897
ssize_t
898 9805
http_GetContentRange(const struct http *hp, ssize_t *lo, ssize_t *hi)
899
{
900
        ssize_t tmp, cl;
901
        const char *b, *t;
902
903 9805
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
904
905 9805
        if (lo == NULL)
906 0
                lo = &tmp;
907 9805
        if (hi == NULL)
908 0
                hi = &tmp;
909
910 9805
        *lo = *hi = -1;
911
912 9805
        if (!http_GetHdr(hp, H_Content_Range, &b))
913 9765
                return (-1);
914
915 40
        t = strchr(b, ' ');
916 40
        if (t == NULL)
917 5
                return (-2);            // Missing space after range unit
918
919 35
        if (!http_range_at(b, bytes, t - b))
920 0
                return (-1);            // Unknown range unit, ignore
921 35
        b = t + 1;
922
923 35
        if (*b == '*') {                // Content-Range: bytes */123
924 15
                *lo = *hi = -1;
925 15
                b++;
926 15
        } else {                        // Content-Range: bytes 1-2/3
927 20
                *lo = VNUM_uint(b, NULL, &b);
928 20
                if (*lo < 0)
929 0
                        return (-2);
930 20
                if (*b != '-')
931 0
                        return (-2);
932 20
                *hi = VNUM_uint(b + 1, NULL, &b);
933 20
                if (*hi < 0)
934 0
                        return (-2);
935
        }
936 35
        if (*b != '/')
937 0
                return (-2);
938 35
        if (b[1] == '*') {              // Content-Range: bytes 1-2/*
939 5
                cl = -1;
940 5
                b += 2;
941 5
        } else {
942 30
                cl = VNUM_uint(b + 1, NULL, &b);
943 30
                if (cl <= 0)
944 0
                        return (-2);
945
        }
946 35
        while (vct_islws(*b))
947 0
                b++;
948 35
        if (*b != '\0')
949 0
                return (-2);
950 35
        if (*lo > *hi)
951 0
                return (-2);
952 35
        assert(cl >= -1);
953 35
        if (*lo >= cl || *hi >= cl)
954 5
                return (-2);
955 30
        AN(cl);
956 30
        return (cl);
957 9805
}
958
959
const char *
960 10040
http_GetRange(const struct http *hp, ssize_t *lo, ssize_t *hi, ssize_t len)
961
{
962
        ssize_t tmp_lo, tmp_hi;
963
        const char *b, *t;
964
965 10040
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
966
967 10040
        if (lo == NULL)
968 0
                lo = &tmp_lo;
969 10040
        if (hi == NULL)
970 0
                hi = &tmp_hi;
971
972 10040
        *lo = *hi = -1;
973
974 10040
        if (!http_GetHdr(hp, H_Range, &b))
975 9780
                return (NULL);
976
977 260
        t = strchr(b, '=');
978 260
        if (t == NULL)
979 10
                return ("Missing '='");
980
981 250
        if (!http_range_at(b, bytes, t - b))
982 15
                return ("Not Bytes");
983 235
        b = t + 1;
984
985 235
        *lo = VNUM_uint(b, NULL, &b);
986 235
        if (*lo == -2)
987 0
                return ("Low number too big");
988 235
        if (*b++ != '-')
989 0
                return ("Missing hyphen");
990
991 235
        *hi = VNUM_uint(b, NULL, &b);
992 235
        if (*hi == -2)
993 0
                return ("High number too big");
994 235
        if (*lo == -1 && *hi == -1)
995 5
                return ("Neither high nor low");
996 230
        if (*lo == -1 && *hi == 0)
997 5
                return ("No low, high is zero");
998 225
        if (*hi >= 0 && *hi < *lo)
999 5
                return ("high smaller than low");
1000
1001 225
        while (vct_islws(*b))
1002 5
                b++;
1003 220
        if (*b != '\0')
1004 5
                return ("Trailing stuff");
1005
1006 215
        assert(*lo >= -1);
1007 215
        assert(*hi >= -1);
1008
1009 215
        if (len <= 0)
1010 80
                return (NULL);                  // Allow 200 response
1011
1012 135
        if (*lo < 0) {
1013 15
                assert(*hi > 0);
1014 15
                *lo = len - *hi;
1015 15
                if (*lo < 0)
1016 5
                        *lo = 0;
1017 15
                *hi = len - 1;
1018 135
        } else if (len >= 0 && (*hi >= len || *hi < 0)) {
1019 40
                *hi = len - 1;
1020 40
        }
1021
1022 135
        if (*lo >= len)
1023 5
                return ("low range beyond object");
1024
1025 130
        return (NULL);
1026 10040
}
1027
1028
/*--------------------------------------------------------------------
1029
 */
1030
1031
stream_close_t
1032 28428
http_DoConnection(struct http *hp, stream_close_t sc_close)
1033
{
1034
        const char *h, *b, *e;
1035
        stream_close_t retval;
1036
        unsigned u, v;
1037
        struct http_hdrflg *f;
1038
1039 28428
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1040 28428
        assert(sc_close == SC_REQ_CLOSE || sc_close == SC_RESP_CLOSE);
1041
1042 28428
        if (hp->protover == 10)
1043 194
                retval = SC_REQ_HTTP10;
1044
        else
1045 28234
                retval = SC_NULL;
1046
1047 28428
        http_CollectHdr(hp, H_Connection);
1048 28428
        if (!http_GetHdr(hp, H_Connection, &h))
1049 27540
                return (retval);
1050 888
        AN(h);
1051 1776
        while (http_split(&h, NULL, ",", &b, &e)) {
1052 903
                u = pdiff(b, e);
1053 903
                if (u == 5 && http_hdr_at(b, "close", u))
1054 728
                        retval = sc_close;
1055 903
                if (u == 10 && http_hdr_at(b, "keep-alive", u))
1056 115
                        retval = SC_NULL;
1057
1058
                /* Refuse removal of well-known-headers if they would pass. */
1059 903
                f = http_hdr_flags(b, e);
1060 903
                if (f != NULL && !(f->flag & HTTPH_R_PASS))
1061 15
                        return (SC_RX_BAD);
1062
1063 4310
                for (v = HTTP_HDR_FIRST; v < hp->nhd; v++) {
1064 3422
                        Tcheck(hp->hd[v]);
1065 3422
                        if (hp->hd[v].e < hp->hd[v].b + u + 1)
1066 155
                                continue;
1067 3267
                        if (hp->hd[v].b[u] != ':')
1068 3017
                                continue;
1069 250
                        if (!http_hdr_at(b, hp->hd[v].b, u))
1070 190
                                continue;
1071 60
                        hp->hdf[v] |= HDF_FILTER;
1072 60
                }
1073
        }
1074 873
        CHECK_OBJ_NOTNULL(retval, STREAM_CLOSE_MAGIC);
1075 873
        return (retval);
1076 28428
}
1077
1078
/*--------------------------------------------------------------------*/
1079
1080
int
1081 54033
http_HdrIs(const struct http *hp, hdr_t hdr, const char *val)
1082
{
1083
        const char *p;
1084
1085 54033
        if (!http_GetHdr(hp, hdr, &p))
1086 51158
                return (0);
1087 2875
        AN(p);
1088 2875
        if (http_tok_eq(p, val))
1089 2745
                return (1);
1090 130
        return (0);
1091 54033
}
1092
1093
/*--------------------------------------------------------------------*/
1094
1095
uint16_t
1096 69936
http_GetStatus(const struct http *hp)
1097
{
1098
1099 69936
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1100 69936
        return (hp->status);
1101
}
1102
1103
int
1104 48896
http_IsStatus(const struct http *hp, int val)
1105
{
1106
1107 48896
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1108 48896
        assert(val >= 100 && val <= 999);
1109 48896
        return (val == (hp->status % 1000));
1110
}
1111
1112
/*--------------------------------------------------------------------
1113
 * Setting the status will also set the Reason appropriately
1114
 */
1115
1116
void
1117 5505
http_SetStatus(struct http *to, uint16_t status, const char *reason)
1118
{
1119
        char buf[4];
1120 5505
        const char *sstr = NULL;
1121
1122 5505
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1123
        /*
1124
         * We allow people to use top digits for internal VCL
1125
         * signalling, but strip them from the ASCII version.
1126
         */
1127 5505
        to->status = status;
1128 5505
        status %= 1000;
1129 5505
        assert(status >= 100);
1130
1131 5505
        if (reason == NULL)
1132 1035
                reason = http_Status2Reason(status, &sstr);
1133
        else
1134 4470
                (void)http_Status2Reason(status, &sstr);
1135
1136 5505
        if (sstr) {
1137 5325
                http_SetH(to, HTTP_HDR_STATUS, sstr);
1138 5325
        } else {
1139 180
                bprintf(buf, "%03d", status);
1140 180
                http_PutField(to, HTTP_HDR_STATUS, buf);
1141
        }
1142 5505
        http_SetH(to, HTTP_HDR_REASON, reason);
1143 5505
}
1144
1145
/*--------------------------------------------------------------------*/
1146
1147
const char *
1148 25644
http_GetMethod(const struct http *hp)
1149
{
1150
1151 25644
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1152 25644
        Tcheck(hp->hd[HTTP_HDR_METHOD]);
1153 25644
        return (hp->hd[HTTP_HDR_METHOD].b);
1154
}
1155
1156
/*--------------------------------------------------------------------
1157
 * Force a particular header field to a particular value
1158
 */
1159
1160
void
1161 37721
http_ForceField(struct http *to, unsigned n, const char *t)
1162
{
1163
        int i;
1164
1165 37721
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1166 37721
        assert(n < HTTP_HDR_FIRST);
1167 37721
        assert(n == HTTP_HDR_METHOD || n == HTTP_HDR_PROTO);
1168 37721
        AN(t);
1169
1170
        /* NB: method names and protocol versions are case-sensitive. */
1171 37721
        if (to->hd[n].b == NULL || strcmp(to->hd[n].b, t)) {
1172 560
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
1173 560
                i += to->logtag;
1174
                /* XXX: this is a dead branch */
1175 560
                if (n >= HTTP_HDR_FIRST)
1176 0
                        VSLbt(to->vsl, (enum VSL_tag_e)i, to->hd[n]);
1177 560
                http_SetH(to, n, t);
1178 560
        }
1179 37721
}
1180
1181
/*--------------------------------------------------------------------*/
1182
1183
void
1184 5050
http_PutResponse(struct http *to, const char *proto, uint16_t status,
1185
    const char *reason)
1186
{
1187
1188 5050
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1189 5050
        if (proto != NULL)
1190 5050
                http_SetH(to, HTTP_HDR_PROTO, proto);
1191 5050
        http_SetStatus(to, status, reason);
1192 5050
}
1193
1194
/*--------------------------------------------------------------------
1195
 * check if header is filtered by the dynamic marker or the static
1196
 * definitions in http_headers.h
1197
 */
1198
1199
static inline int
1200 194144
http_isfiltered(const struct http *fm, unsigned u, unsigned how)
1201
{
1202
        const char *e;
1203
        const struct http_hdrflg *f;
1204
1205 194144
        if (fm->hdf[u] & HDF_FILTER)
1206 85
                return (1);
1207 194059
        if (u < HTTP_HDR_FIRST)
1208 65465
                return (0);
1209 128594
        e = strchr(fm->hd[u].b, ':');
1210 128594
        if (e == NULL)
1211 0
                return (0);
1212 128594
        f = http_hdr_flags(fm->hd[u].b, e);
1213 128594
        return (f != NULL && f->flag & how);
1214 194144
}
1215
1216
int
1217 3080
http_IsFiltered(const struct http *fm, unsigned u, unsigned how)
1218
{
1219
1220 3080
        return (http_isfiltered(fm, u, how));
1221
}
1222
1223
/*--------------------------------------------------------------------
1224
 * Estimate how much workspace we need to Filter this header according
1225
 * to 'how'.
1226
 */
1227
1228
unsigned
1229 10930
http_EstimateWS(const struct http *fm, unsigned how)
1230
{
1231
        unsigned u, l;
1232
1233 10930
        l = 4;
1234 10930
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1235 104407
        for (u = 0; u < fm->nhd; u++) {
1236 93477
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1237 21860
                        continue;
1238 71617
                Tcheck(fm->hd[u]);
1239 71617
                if (http_isfiltered(fm, u, how))
1240 1298
                        continue;
1241 70319
                l += Tlen(fm->hd[u]) + 1L;
1242 70319
        }
1243 10930
        return (PRNDUP(l + 1L));
1244
}
1245
1246
/*--------------------------------------------------------------------
1247
 * Encode http struct as byte string.
1248
 *
1249
 * XXX: We could save considerable special-casing below by encoding also
1250
 * XXX: H__Status, H__Reason and H__Proto into the string, but it would
1251
 * XXX: add 26-30 bytes to all encoded objects to save a little code.
1252
 * XXX: It could possibly be a good idea for later HTTP versions.
1253
 */
1254
1255
void
1256 10900
HTTP_Encode(const struct http *fm, uint8_t *p0, unsigned l, unsigned how)
1257
{
1258
        unsigned u, w;
1259
        uint16_t n;
1260
        uint8_t *p, *e;
1261
1262 10900
        AN(p0);
1263 10900
        AN(l);
1264 10900
        p = p0;
1265 10900
        e = p + l;
1266 10900
        assert(p + 5 <= e);
1267 10900
        assert(fm->nhd <= fm->shd);
1268 10900
        n = HTTP_HDR_FIRST - 3;
1269 10900
        vbe16enc(p + 2, fm->status);
1270 10900
        p += 4;
1271 10900
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1272 104072
        for (u = 0; u < fm->nhd; u++) {
1273 93172
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1274 21798
                        continue;
1275 71374
                Tcheck(fm->hd[u]);
1276 71374
                if (http_isfiltered(fm, u, how))
1277 1298
                        continue;
1278 70076
                http_VSLH(fm, u);
1279 70076
                w = Tlen(fm->hd[u]) + 1L;
1280 70076
                assert(p + w + 1 <= e);
1281 70076
                memcpy(p, fm->hd[u].b, w);
1282 70076
                p += w;
1283 70076
                n++;
1284 70076
        }
1285 10900
        *p++ = '\0';
1286 10900
        assert(p <= e);
1287 10900
        vbe16enc(p0, n + 1);
1288 10900
}
1289
1290
/*--------------------------------------------------------------------
1291
 * Decode byte string into http struct
1292
 */
1293
1294
int
1295 15834
HTTP_Decode(struct http *to, const uint8_t *fm)
1296
{
1297
1298 15834
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1299 15834
        AN(to->vsl);
1300 15834
        AN(fm);
1301 15834
        if (vbe16dec(fm) <= to->shd) {
1302 15820
                to->status = vbe16dec(fm + 2);
1303 15820
                fm += 4;
1304 149612
                for (to->nhd = 0; to->nhd < to->shd; to->nhd++) {
1305 149612
                        if (to->nhd == HTTP_HDR_METHOD ||
1306 133775
                            to->nhd == HTTP_HDR_URL) {
1307 31644
                                to->hd[to->nhd].b = NULL;
1308 31644
                                to->hd[to->nhd].e = NULL;
1309 31644
                                continue;
1310
                        }
1311 117968
                        if (*fm == '\0')
1312 15820
                                return (0);
1313 102148
                        to->hd[to->nhd].b = (const void*)fm;
1314 102148
                        fm = (const void*)strchr((const void*)fm, '\0');
1315 102148
                        to->hd[to->nhd].e = (const void*)fm;
1316 102148
                        fm++;
1317 102148
                        http_VSLH(to, to->nhd);
1318 102148
                }
1319 0
        }
1320 28
        VSLb(to->vsl, SLT_Error,
1321
            "Too many headers to Decode object (%u vs. %u)",
1322 14
            vbe16dec(fm), to->shd);
1323 14
        return (-1);
1324 15834
}
1325
1326
/*--------------------------------------------------------------------*/
1327
1328
uint16_t
1329 5
HTTP_GetStatusPack(struct worker *wrk, struct objcore *oc)
1330
{
1331
        const char *ptr;
1332 5
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1333 5
        AN(ptr);
1334
1335 5
        return (vbe16dec(ptr + 2));
1336
}
1337
1338
/*--------------------------------------------------------------------*/
1339
1340
/* Get the first packed header */
1341
int
1342 3693
HTTP_IterHdrPack(struct worker *wrk, struct objcore *oc, const char **p)
1343
{
1344
        const char *ptr;
1345
1346 3693
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1347 3693
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1348 3693
        AN(p);
1349
1350 3693
        if (*p == NULL) {
1351 1166
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1352 1166
                AN(ptr);
1353 1166
                ptr += 4;       /* Skip nhd and status */
1354 1166
                ptr = strchr(ptr, '\0') + 1;    /* Skip :proto: */
1355 1166
                ptr = strchr(ptr, '\0') + 1;    /* Skip :status: */
1356 1166
                ptr = strchr(ptr, '\0') + 1;    /* Skip :reason: */
1357 1166
                *p = ptr;
1358 1166
        } else {
1359 2527
                *p = strchr(*p, '\0') + 1;      /* Skip to next header */
1360
        }
1361 3693
        if (**p == '\0')
1362 218
                return (0);
1363 3475
        return (1);
1364 3693
}
1365
1366
const char *
1367 1196
HTTP_GetHdrPack(struct worker *wrk, struct objcore *oc, hdr_t hdr)
1368
{
1369
        const char *ptr;
1370
        unsigned l;
1371
1372 1196
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1373 1196
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1374 1196
        AN(hdr);
1375
1376 1196
        l = hdr[0];
1377 1196
        assert(l > 0);
1378 1196
        assert(l == strlen(hdr + 1));
1379 1196
        assert(hdr[l] == ':');
1380 1196
        hdr++;
1381
1382 1196
        if (hdr[0] == ':') {
1383
                /* Special cases */
1384 30
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1385 30
                AN(ptr);
1386 30
                ptr += 4;       /* Skip nhd and status */
1387
1388
                /* XXX: should we also have h2_hdr_eq() ? */
1389 30
                if (!strcmp(hdr, ":proto:"))
1390 5
                        return (ptr);
1391 25
                ptr = strchr(ptr, '\0') + 1;
1392 25
                if (!strcmp(hdr, ":status:"))
1393 20
                        return (ptr);
1394 5
                ptr = strchr(ptr, '\0') + 1;
1395 5
                if (!strcmp(hdr, ":reason:"))
1396 5
                        return (ptr);
1397 0
                WRONG("Unknown magic packed header");
1398 0
        }
1399
1400 3693
        HTTP_FOREACH_PACK(wrk, oc, ptr) {
1401 3475
                if (http_hdr_at(ptr, hdr, l)) {
1402 948
                        ptr += l;
1403 1891
                        while (vct_islws(*ptr))
1404 943
                                ptr++;
1405 948
                        return (ptr);
1406
                }
1407
        }
1408
1409 218
        return (NULL);
1410 1196
}
1411
1412
/*--------------------------------------------------------------------
1413
 * Merge any headers in the oc->OA_HEADER into the struct http if they
1414
 * are not there already.
1415
 */
1416
1417
void
1418 140
HTTP_Merge(struct worker *wrk, struct objcore *oc, struct http *to)
1419
{
1420
        const char *ptr;
1421
        unsigned u;
1422
        const char *p;
1423
        unsigned nhd_before_merge;
1424
1425 140
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1426 140
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1427 140
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1428
1429 140
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1430 140
        AN(ptr);
1431
1432 140
        to->status = vbe16dec(ptr + 2);
1433 140
        ptr += 4;
1434
1435 840
        for (u = 0; u < HTTP_HDR_FIRST; u++) {
1436 700
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1437 280
                        continue;
1438 420
                http_SetH(to, u, ptr);
1439 420
                ptr = strchr(ptr, '\0') + 1;
1440 420
        }
1441 140
        nhd_before_merge = to->nhd;
1442 825
        while (*ptr != '\0') {
1443 685
                p = strchr(ptr, ':');
1444 685
                AN(p);
1445 685
                u = http_findhdr(to, p - ptr, ptr);
1446 685
                if (u == 0 || u >= nhd_before_merge)
1447 305
                        http_SetHeader(to, ptr);
1448 685
                ptr = strchr(ptr, '\0') + 1;
1449
        }
1450 140
}
1451
1452
/*--------------------------------------------------------------------*/
1453
1454
static void
1455 33600
http_linkh(const struct http *to, const struct http *fm, unsigned n)
1456
{
1457
1458 33600
        assert(n < HTTP_HDR_FIRST);
1459 33600
        Tcheck(fm->hd[n]);
1460 33600
        to->hd[n] = fm->hd[n];
1461 33600
        to->hdf[n] = fm->hdf[n];
1462 33600
        http_VSLH(to, n);
1463 33600
}
1464
1465
/*--------------------------------------------------------------------*/
1466
1467
void
1468 11200
http_FilterReq(struct http *to, const struct http *fm, unsigned how)
1469
{
1470
        unsigned u;
1471
1472 11200
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1473 11200
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1474
1475 11200
        http_linkh(to, fm, HTTP_HDR_METHOD);
1476 11200
        http_linkh(to, fm, HTTP_HDR_URL);
1477 11200
        http_linkh(to, fm, HTTP_HDR_PROTO);
1478 11200
        to->protover = fm->protover;
1479 11200
        to->status = fm->status;
1480
1481 11200
        to->nhd = HTTP_HDR_FIRST;
1482 59248
        for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
1483 48048
                Tcheck(fm->hd[u]);
1484 48048
                if (http_isfiltered(fm, u, how))
1485 545
                        continue;
1486 47503
                assert (to->nhd < to->shd);
1487 47503
                to->hd[to->nhd] = fm->hd[u];
1488 47503
                to->hdf[to->nhd] = 0;
1489 47503
                http_VSLH(to, to->nhd);
1490 47503
                to->nhd++;
1491 47503
        }
1492 11200
}
1493
1494
/*--------------------------------------------------------------------
1495
 * This function copies any header fields which reference foreign
1496
 * storage into our own WS.
1497
 */
1498
1499
void
1500 11045
http_CopyHome(const struct http *hp)
1501
{
1502
        unsigned u, l;
1503
        const char *p;
1504
1505 120001
        for (u = 0; u < hp->nhd; u++) {
1506 108956
                if (hp->hd[u].b == NULL) {
1507 22090
                        assert(u < HTTP_HDR_FIRST);
1508 22090
                        continue;
1509
                }
1510
1511 86866
                l = Tlen(hp->hd[u]);
1512 86866
                if (WS_Allocated(hp->ws, hp->hd[u].b, l))
1513 6930
                        continue;
1514
1515 79936
                p = WS_Copy(hp->ws, hp->hd[u].b, l + 1L);
1516 79936
                if (p == NULL) {
1517 0
                        http_fail(hp);
1518 0
                        VSLbs(hp->vsl, SLT_LostHeader, TOSTRAND(hp->hd[u].b));
1519 0
                        return;
1520
                }
1521 79936
                hp->hd[u].b = p;
1522 79936
                hp->hd[u].e = p + l;
1523 79936
        }
1524 11045
}
1525
1526
/*--------------------------------------------------------------------*/
1527
1528
void
1529 45448
http_SetHeader(struct http *to, const char *header)
1530
{
1531
1532 45448
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1533 45448
        if (to->nhd >= to->shd) {
1534 5
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(header));
1535 5
                http_fail(to);
1536 5
                return;
1537
        }
1538 45443
        http_SetH(to, to->nhd++, header);
1539 45448
}
1540
1541
/*--------------------------------------------------------------------*/
1542
1543
void
1544 20299
http_ForceHeader(struct http *to, hdr_t hdr, const char *val)
1545
{
1546
1547 20299
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1548 20299
        if (http_HdrIs(to, hdr, val))
1549 1850
                return;
1550 18449
        http_Unset(to, hdr);
1551 18449
        http_PrintfHeader(to, "%s %s", hdr + 1, val);
1552 20299
}
1553
1554
void
1555 51969
http_AppendHeader(struct http *to, hdr_t hdr, const char *val)
1556
{
1557
        const char *old;
1558
1559 51969
        http_CollectHdr(to, hdr);
1560 51969
        if (http_GetHdr(to, hdr, &old)) {
1561 240
                http_Unset(to, hdr);
1562 240
                http_PrintfHeader(to, "%s %s, %s", hdr + 1, old, val);
1563 240
        } else {
1564 51729
                http_PrintfHeader(to, "%s %s", hdr + 1, val);
1565
        }
1566 51969
}
1567
1568
void
1569 122147
http_PrintfHeader(struct http *to, const char *fmt, ...)
1570
{
1571
        va_list ap, ap2;
1572
        struct vsb vsb[1];
1573
        size_t sz;
1574
        char *p;
1575
1576 122147
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1577
1578 122147
        va_start(ap, fmt);
1579 122147
        va_copy(ap2, ap);
1580
1581 122147
        WS_VSB_new(vsb, to->ws);
1582 122147
        VSB_vprintf(vsb, fmt, ap);
1583 122147
        p = WS_VSB_finish(vsb, to->ws, &sz);
1584
1585 122147
        if (p == NULL || to->nhd >= to->shd) {
1586 133
                http_fail(to);
1587 133
                VSLbv(to->vsl, SLT_LostHeader, fmt, ap2);
1588 133
        } else {
1589 122016
                http_SetH(to, to->nhd++, p);
1590
        }
1591 122149
        va_end(ap);
1592 122149
        va_end(ap2);
1593 122149
}
1594
1595
void
1596 5095
http_TimeHeader(struct http *to, const char *fmt, vtim_real now)
1597
{
1598
        char *p;
1599
1600 5095
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1601 5095
        if (to->nhd >= to->shd) {
1602 0
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1603 0
                http_fail(to);
1604 0
                return;
1605
        }
1606 5095
        p = WS_Alloc(to->ws, strlen(fmt) + VTIM_FORMAT_SIZE);
1607 5095
        if (p == NULL) {
1608 385
                http_fail(to);
1609 385
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1610 385
                return;
1611
        }
1612 4710
        strcpy(p, fmt);
1613 4710
        VTIM_format(now, strchr(p, '\0'));
1614 4710
        http_SetH(to, to->nhd++, p);
1615 5095
}
1616
1617
const char *
1618 33899
http_ViaHeader(void)
1619
{
1620
1621 33899
        return (via_hdr);
1622
}
1623
1624
/*--------------------------------------------------------------------*/
1625
1626
void
1627 90212
http_Unset(struct http *hp, hdr_t hdr)
1628
{
1629
        uint16_t u, v;
1630
1631 572555
        for (v = u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
1632 482343
                Tcheck(hp->hd[u]);
1633 482343
                if (http_IsHdr(&hp->hd[u], hdr)) {
1634 4695
                        http_VSLH_del(hp, u);
1635 4695
                        continue;
1636
                }
1637 477648
                if (v != u) {
1638 12070
                        memcpy(&hp->hd[v], &hp->hd[u], sizeof *hp->hd);
1639 12070
                        memcpy(&hp->hdf[v], &hp->hdf[u], sizeof *hp->hdf);
1640 12070
                }
1641 477648
                v++;
1642 477648
        }
1643 90212
        hp->nhd = v;
1644 90212
}