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 223982
http_hdr_flags(const char *b, const char *e)
183
{
184
        unsigned u;
185
        struct http_hdrflg *retval;
186
187 223982
        if (b == NULL || e == NULL)
188 8
                return (NULL);
189 223980
        assert(b <= e);
190 223980
        u = (unsigned)(e - b);
191 223980
        assert(b + u == e);
192 223980
        if (u < GPERF_MIN_WORD_LENGTH || u > GPERF_MAX_WORD_LENGTH)
193 87
                return (NULL);
194 447786
        u += http_asso_values[(uint8_t)(e[-1])] +
195 223893
             http_asso_values[(uint8_t)(b[0])];
196 223893
        if (u > GPERF_MAX_HASH_VALUE)
197 3009
                return (NULL);
198 220884
        retval = &http_hdrflg[u];
199 220884
        if (retval->hdr == NULL)
200 829
                return (NULL);
201 220055
        if (!http_hdr_at(retval->hdr + 1, b, e - b))
202 3069
                return (NULL);
203 216986
        return (retval);
204 223980
}
205
206
/*--------------------------------------------------------------------*/
207
208
static void
209 144872
http_init_hdr(char *hdr, int flg)
210
{
211
        struct http_hdrflg *f;
212
213 144872
        hdr[0] = strlen(hdr + 1);
214 144872
        f = http_hdr_flags(hdr + 1, hdr + hdr[0]);
215 144872
        AN(f);
216 144872
        assert(f->hdr == hdr);
217 144872
        f->flag = flg;
218 144872
}
219
220
void
221 2786
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 2786
        AN(vsb);
230
        VSB_printf(vsb, "1.1 %s (Varnish/" PACKAGE_BRANCH ")",
231
            heritage.identity);
232 2786
        AZ(VSB_finish(vsb));
233 2786
        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 369381
http_VSLH(const struct http *hp, unsigned hdr)
247
{
248
        int i;
249
250 369381
        if (hp->vsl != NULL) {
251 369380
                assert(VXID_TAG(hp->vsl->wid));
252 369380
                i = hdr;
253 369380
                if (i > HTTP_HDR_FIRST)
254 193954
                        i = HTTP_HDR_FIRST;
255 369380
                i += hp->logtag;
256 369380
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
257 369380
        }
258 369383
}
259
260
static void
261 2835
http_VSLH_del(const struct http *hp, unsigned hdr)
262
{
263
        int i;
264
265 2835
        if (hp->vsl != NULL) {
266
                /* We don't support unsetting stuff in the first line */
267 2835
                assert (hdr >= HTTP_HDR_FIRST);
268 2835
                assert(VXID_TAG(hp->vsl->wid));
269 2835
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
270 2835
                i += hp->logtag;
271 2835
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
272 2835
        }
273 2835
}
274
275
/*--------------------------------------------------------------------*/
276
277
void
278 17214
http_VSL_log(const struct http *hp)
279
{
280
        unsigned u;
281
282 150352
        for (u = 0; u < hp->nhd; u++)
283 231849
                if (hp->hd[u].b != NULL)
284 98711
                        http_VSLH(hp, u);
285 17214
}
286
287
/*--------------------------------------------------------------------*/
288
289
static void
290 312
http_fail(const struct http *hp)
291
{
292
        char id[WS_ID_SIZE];
293
294 312
        VSC_C_main->losthdr++;
295 312
        WS_Id(hp->ws, id);
296 312
        VSLb(hp->vsl, SLT_Error, "out of workspace (%s)", id);
297 312
        WS_MarkOverflow(hp->ws);
298 312
}
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 4356
http_Status2Reason(unsigned status, const char **sstr)
316
{
317
        struct http_msg *mp;
318
319 4356
        status %= 1000;
320 4356
        assert(status >= 100);
321 134316
        for (mp = http_msg; mp->nbr != 0 && mp->nbr <= status; mp++)
322 134181
                if (mp->nbr == status) {
323 4221
                        if (sstr)
324 3237
                                *sstr = mp->status;
325 4221
                        return (mp->txt);
326
                }
327 135
        return ("Unknown HTTP Status");
328 4356
}
329
330
/*--------------------------------------------------------------------*/
331
332
unsigned
333 15808
HTTP_estimate(unsigned nhttp)
334
{
335
336
        /* XXX: We trust the structs to size-aligned as necessary */
337 15808
        return (PRNDUP(sizeof(struct http) + sizeof(txt) * nhttp + nhttp));
338
}
339
340
struct http *
341 47424
HTTP_create(void *p, uint16_t nhttp, unsigned len)
342
{
343
        struct http *hp;
344
345 47424
        hp = p;
346 47424
        hp->magic = HTTP_MAGIC;
347 47424
        hp->hd = (void*)(hp + 1);
348 47424
        hp->shd = nhttp;
349 47424
        hp->hdf = (void*)(hp->hd + nhttp);
350 47424
        assert((unsigned char*)p + len == hp->hdf + PRNDUP(nhttp));
351 47424
        return (hp);
352
}
353
354
/*--------------------------------------------------------------------*/
355
356
void
357 44014
HTTP_Setup(struct http *hp, struct ws *ws, struct vsl_log *vsl,
358
    enum VSL_tag_e  whence)
359
{
360 44014
        http_Teardown(hp);
361 44014
        hp->nhd = HTTP_HDR_FIRST;
362 44014
        hp->logtag = whence;
363 44014
        hp->ws = ws;
364 44014
        hp->vsl = vsl;
365 44014
}
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 68728
http_Teardown(struct http *hp)
375
{
376
377 68728
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
378 68728
        AN(hp->shd);
379 68728
        memset(&hp->nhd, 0, sizeof *hp - offsetof(struct http, nhd));
380 68728
        memset(hp->hd, 0, sizeof *hp->hd * hp->shd);
381 68728
        memset(hp->hdf, 0, sizeof *hp->hdf * hp->shd);
382 68728
}
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 19331
HTTP_Dup(struct http *to, const struct http * fm)
392
{
393
394 19331
        assert(fm->nhd <= to->shd);
395 19331
        memcpy(to->hd, fm->hd, fm->nhd * sizeof *to->hd);
396 19331
        memcpy(to->hdf, fm->hdf, fm->nhd * sizeof *to->hdf);
397 19331
        to->nhd = fm->nhd;
398 19331
        to->logtag = fm->logtag;
399 19331
        to->status = fm->status;
400 19331
        to->protover = fm->protover;
401 19331
}
402
403
404
/*--------------------------------------------------------------------
405
 * Clone the entire http structure, including vsl & ws
406
 */
407
408
void
409 18233
HTTP_Clone(struct http *to, const struct http * const fm)
410
{
411
412 18233
        HTTP_Dup(to, fm);
413 18233
        to->vsl = fm->vsl;
414 18233
        to->ws = fm->ws;
415 18233
}
416
417
/*--------------------------------------------------------------------*/
418
419
void
420 19682
http_Proto(struct http *to)
421
{
422
        const char *fm;
423
424 19682
        fm = to->hd[HTTP_HDR_PROTO].b;
425
426 39337
        if (fm != NULL &&
427 19658
            (fm[0] == 'H' || fm[0] == 'h') &&
428 19655
            (fm[1] == 'T' || fm[1] == 't') &&
429 19655
            (fm[2] == 'T' || fm[2] == 't') &&
430 19655
            (fm[3] == 'P' || fm[3] == 'p') &&
431 19655
            fm[4] == '/' &&
432 19655
            vct_isdigit(fm[5]) &&
433 19655
            fm[6] == '.' &&
434 19655
            vct_isdigit(fm[7]) &&
435 19655
            fm[8] == '\0') {
436 19655
                to->protover = 10 * (fm[5] - '0') + (fm[7] - '0');
437 19655
        } else {
438 27
                to->protover = 0;
439
        }
440 19682
}
441
442
/*--------------------------------------------------------------------*/
443
444
void
445 116914
http_SetH(struct http *to, unsigned n, const char *header)
446
{
447
448 116914
        assert(n < to->nhd);
449 116914
        AN(header);
450 116914
        to->hd[n].b = TRUST_ME(header);
451 116914
        to->hd[n].e = strchr(to->hd[n].b, '\0');
452 116914
        to->hdf[n] = 0;
453 116914
        http_VSLH(to, n);
454 116914
        if (n == HTTP_HDR_PROTO)
455 4038
                http_Proto(to);
456 116914
}
457
458
/*--------------------------------------------------------------------*/
459
460
static void
461 108
http_PutField(struct http *to, int field, const char *string)
462
{
463
        const char *p;
464
465 108
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
466 108
        p = WS_Copy(to->ws, string, -1);
467 108
        if (p == NULL) {
468 3
                http_fail(to);
469 3
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(string));
470 3
                return;
471
        }
472 105
        http_SetH(to, field, p);
473 108
}
474
475
/*--------------------------------------------------------------------*/
476
477
int
478 426087
http_IsHdr(const txt *hh, hdr_t hdr)
479
{
480
        unsigned l;
481
482 426087
        Tcheck(*hh);
483 426087
        AN(hdr);
484 426087
        l = hdr[0];
485 426087
        assert(l == strlen(hdr + 1));
486 426087
        assert(hdr[l] == ':');
487 426087
        hdr++;
488 426087
        return (http_hdr_at(hdr, hh->b, l));
489
}
490
491
/*--------------------------------------------------------------------*/
492
493
static unsigned
494 439123
http_findhdr(const struct http *hp, unsigned l, const char *hdr)
495
{
496
        unsigned u;
497
498 1893135
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
499 1551558
                Tcheck(hp->hd[u]);
500 1551558
                if (hp->hd[u].e < hp->hd[u].b + l + 1)
501 281324
                        continue;
502 1270234
                if (hp->hd[u].b[l] != ':')
503 1066977
                        continue;
504 203257
                if (!http_hdr_at(hdr, hp->hd[u].b, l))
505 105711
                        continue;
506 97546
                return (u);
507
        }
508 341577
        return (0);
509 439123
}
510
511
/*--------------------------------------------------------------------
512
 * Count how many instances we have of this header
513
 */
514
515
unsigned
516 22268
http_CountHdr(const struct http *hp, hdr_t hdr)
517
{
518 22268
        unsigned retval = 0;
519
        unsigned u;
520
521 22268
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
522
523 74190
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
524 51922
                Tcheck(hp->hd[u]);
525 51922
                if (http_IsHdr(&hp->hd[u], hdr))
526 11005
                        retval++;
527 51922
        }
528 22268
        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 71796
http_CollectHdr(struct http *hp, hdr_t hdr)
538
{
539
540 71796
        http_CollectHdrSep(hp, hdr, NULL);
541 71796
}
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 72234
http_CollectHdrSep(struct http *hp, hdr_t hdr, const char *sep)
551
{
552
        unsigned u, l, lsep, ml, f, x, d;
553 72234
        char *b = NULL, *e = NULL;
554
        const char *v;
555
556 72234
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
557 72234
        if (WS_Overflowed(hp->ws))
558 60
                return;
559
560 72174
        if (sep == NULL || *sep == '\0')
561 71734
                sep = ", ";
562 72182
        lsep = strlen(sep);
563
564 72182
        l = hdr[0];
565 72182
        assert(l == strlen(hdr + 1));
566 72182
        assert(hdr[l] == ':');
567 72182
        f = http_findhdr(hp, l - 1, hdr + 1);
568 72182
        if (f == 0)
569 70957
                return;
570
571 4510
        for (d = u = f + 1; u < hp->nhd; u++) {
572 3285
                Tcheck(hp->hd[u]);
573 3285
                if (!http_IsHdr(&hp->hd[u], hdr)) {
574 3231
                        if (d != u) {
575 213
                                hp->hd[d] = hp->hd[u];
576 213
                                hp->hdf[d] = hp->hdf[u];
577 213
                        }
578 3231
                        d++;
579 3231
                        continue;
580
                }
581 54
                if (b == NULL) {
582
                        /* Found second header, start our collection */
583 48
                        ml = WS_ReserveAll(hp->ws);
584 48
                        b = WS_Reservation(hp->ws);
585 48
                        e = b + ml;
586 48
                        x = Tlen(hp->hd[f]);
587 48
                        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 48
                        memcpy(b, hp->hd[f].b, x);
595 48
                        b += x;
596 48
                }
597
598 54
                AN(b);
599 54
                AN(e);
600
601
                /* Append the Nth header we found */
602 54
                x = Tlen(hp->hd[u]) - l;
603
604 54
                v = hp->hd[u].b + *hdr;
605 108
                while (vct_issp(*v)) {
606 54
                        v++;
607 54
                        x--;
608
                }
609
610 54
                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 54
                memcpy(b, sep, lsep);
617 54
                b += lsep;
618 54
                memcpy(b, v, x);
619 54
                b += x;
620 54
        }
621 1225
        if (b == NULL)
622 1177
                return;
623 48
        hp->nhd = (uint16_t)d;
624 48
        AN(e);
625 48
        *b = '\0';
626 48
        hp->hd[f].b = WS_Reservation(hp->ws);
627 48
        hp->hd[f].e = b;
628 48
        WS_ReleaseP(hp->ws, b + 1);
629 72242
}
630
631
/*--------------------------------------------------------------------*/
632
633
int
634 366588
http_GetHdr(const struct http *hp, hdr_t hdr, const char **ptr)
635
{
636
        unsigned u, l;
637
        const char *p;
638
639 366588
        l = hdr[0];
640 366588
        assert(l == strlen(hdr + 1));
641 366588
        assert(hdr[l] == ':');
642 366588
        hdr++;
643 366588
        u = http_findhdr(hp, l - 1, hdr);
644 366588
        if (u == 0) {
645 270499
                if (ptr != NULL)
646 248577
                        *ptr = NULL;
647 270499
                return (0);
648
        }
649 96089
        if (ptr != NULL) {
650 78605
                p = hp->hd[u].b + l;
651 157077
                while (vct_issp(*p))
652 78472
                        p++;
653 78605
                *ptr = p;
654 78605
        }
655 96089
        return (1);
656 366588
}
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 6818
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 6818
        AN(src);
672 6818
        AN(*src);
673 6818
        AN(sep);
674 6818
        AN(b);
675 6818
        AN(e);
676
677 6818
        if (stop == NULL)
678 6797
                stop = strchr(*src, '\0');
679
680 11718
        for (p = *src; p < stop && (vct_issp(*p) || strchr(sep, *p)); p++)
681 261
                continue;
682
683 6818
        if (p >= stop) {
684 2440
                *b = NULL;
685 2440
                *e = NULL;
686 2440
                return (0);
687
        }
688
689 4378
        *b = p;
690 4378
        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 21542
        for (q = p + 1; q < stop && !strchr(sep, *q); q++)
698 17164
                continue;
699 4378
        *src = q;
700 4378
        while (q > p && vct_issp(q[-1]))
701 0
                q--;
702 4378
        *e = q;
703 4378
        return (1);
704 6818
}
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 3819
http_istoken(const char **bp, const char *e, const char *token)
717
{
718 3819
        int fl = strlen(token);
719
        const char *b;
720
721 3819
        AN(bp);
722 3819
        AN(e);
723 3819
        AN(token);
724
725 3819
        b = *bp;
726
727 3819
        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 3939
        if (b + fl <= e && http_tok_at(b, token, fl) &&
733 1788
            (b + fl == e || !vct_istchar(b[fl]))) {
734 1788
                *bp += fl;
735 1788
                return (1);
736
        }
737 2031
        return (0);
738 3819
}
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 43439
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 43439
        if (pb != NULL)
767 33000
                *pb = NULL;
768 43439
        if (pe != NULL)
769 10065
                *pe = NULL;
770 43439
        if (!http_GetHdr(hp, hdr, &h))
771 39731
                return (0);
772 3708
        AN(h);
773
774 5739
        while (http_split(&h, NULL, ",", &b, &e))
775 3819
                if (http_istoken(&b, e, token))
776 1788
                        break;
777 3708
        if (b == NULL)
778 1920
                return (0);
779 1788
        if (pb != NULL) {
780 1776
                for (; vct_islws(*b); b++)
781 15
                        continue;
782 1761
                if (b == e) {
783 1644
                        b = NULL;
784 1644
                        e = NULL;
785 1644
                }
786 1761
                *pb = b;
787 1761
                if (pe != NULL)
788 1623
                        *pe = e;
789 1761
        }
790 1788
        return (1);
791 43439
}
792
793
/*--------------------------------------------------------------------
794
 * Find a given header field's quality value (qvalue).
795
 */
796
797
double
798 10065
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 10065
        i = http_GetHdrToken(hp, hdr, field, &hb, &he);
805 10065
        if (!i)
806 8442
                return (0.);
807
808 1623
        if (hb == NULL)
809 1602
                return (1.);
810 21
        while (http_split(&hb, he, ";", &b, &e)) {
811 21
                if (*b != 'q')
812 0
                        continue;
813 21
                for (b++; b < e && vct_issp(*b); b++)
814 0
                        continue;
815 21
                if (b == e || *b != '=')
816 0
                        continue;
817 21
                break;
818
        }
819 21
        if (b == NULL)
820 0
                return (1.);
821 21
        for (b++; b < e && vct_issp(*b); b++)
822 0
                continue;
823 21
        if (b == e || (*b != '.' && !vct_isdigit(*b)))
824 3
                return (0.);
825 18
        a = 0;
826 36
        while (b < e && vct_isdigit(*b)) {
827 18
                a *= 10.;
828 18
                a += *b - '0';
829 18
                b++;
830
        }
831 18
        if (b == e || *b++ != '.')
832 3
                return (a);
833 15
        f = .1;
834 48
        while (b < e && vct_isdigit(*b)) {
835 33
                a += f * (*b - '0');
836 33
                f *= .1;
837 33
                b++;
838
        }
839 15
        return (a);
840 10065
}
841
842
/*--------------------------------------------------------------------
843
 * Find a given header field's value.
844
 */
845
846
int
847 22938
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 22938
        if (ptr != NULL)
854 11643
                *ptr = NULL;
855
856 22938
        h = NULL;
857 22938
        i = http_GetHdrToken(hp, hdr, field, &h, NULL);
858 22938
        if (!i)
859 22800
                return (i);
860
861 138
        if (ptr != NULL && h != NULL) {
862
                /* Skip whitespace, looking for '=' */
863 96
                while (*h && vct_issp(*h))
864 0
                        h++;
865 96
                if (*h == '=') {
866 96
                        h++;
867 108
                        while (*h && vct_issp(*h))
868 12
                                h++;
869 96
                        *ptr = h;
870 96
                }
871 96
        }
872 138
        return (i);
873 22938
}
874
875
/*--------------------------------------------------------------------*/
876
877
ssize_t
878 32897
http_GetContentLength(const struct http *hp)
879
{
880
        ssize_t cl;
881
        const char *b;
882
883 32897
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
884
885 32897
        if (!http_GetHdr(hp, H_Content_Length, &b))
886 12888
                return (-1);
887 20009
        cl = VNUM_uint(b, NULL, &b);
888 20009
        if (cl < 0)
889 12
                return (-2);
890 19997
        while (vct_islws(*b))
891 0
                b++;
892 19997
        if (*b != '\0')
893 0
                return (-2);
894 19997
        return (cl);
895 32897
}
896
897
ssize_t
898 5940
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 5940
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
904
905 5940
        if (lo == NULL)
906 0
                lo = &tmp;
907 5940
        if (hi == NULL)
908 0
                hi = &tmp;
909
910 5940
        *lo = *hi = -1;
911
912 5940
        if (!http_GetHdr(hp, H_Content_Range, &b))
913 5913
                return (-1);
914
915 27
        t = strchr(b, ' ');
916 27
        if (t == NULL)
917 3
                return (-2);            // Missing space after range unit
918
919 24
        if (!http_range_at(b, bytes, t - b))
920 3
                return (-1);            // Unknown range unit, ignore
921 21
        b = t + 1;
922
923 21
        if (*b == '*') {                // Content-Range: bytes */123
924 9
                *lo = *hi = -1;
925 9
                b++;
926 9
        } else {                        // Content-Range: bytes 1-2/3
927 12
                *lo = VNUM_uint(b, NULL, &b);
928 12
                if (*lo < 0)
929 0
                        return (-2);
930 12
                if (*b != '-')
931 0
                        return (-2);
932 12
                *hi = VNUM_uint(b + 1, NULL, &b);
933 12
                if (*hi < 0)
934 0
                        return (-2);
935
        }
936 21
        if (*b != '/')
937 0
                return (-2);
938 21
        if (b[1] == '*') {              // Content-Range: bytes 1-2/*
939 3
                cl = -1;
940 3
                b += 2;
941 3
        } else {
942 18
                cl = VNUM_uint(b + 1, NULL, &b);
943 18
                if (cl <= 0)
944 0
                        return (-2);
945
        }
946 21
        while (vct_islws(*b))
947 0
                b++;
948 21
        if (*b != '\0')
949 0
                return (-2);
950 21
        if (*lo > *hi)
951 0
                return (-2);
952 21
        assert(cl >= -1);
953 21
        if (*lo >= cl || *hi >= cl)
954 3
                return (-2);
955 18
        AN(cl);
956 18
        return (cl);
957 5940
}
958
959
const char *
960 6081
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 6081
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
966
967 6081
        if (lo == NULL)
968 0
                lo = &tmp_lo;
969 6081
        if (hi == NULL)
970 0
                hi = &tmp_hi;
971
972 6081
        *lo = *hi = -1;
973
974 6081
        if (!http_GetHdr(hp, H_Range, &b))
975 5925
                return (NULL);
976
977 156
        t = strchr(b, '=');
978 156
        if (t == NULL)
979 6
                return ("Missing '='");
980
981 150
        if (!http_range_at(b, bytes, t - b))
982 9
                return ("Not Bytes");
983 141
        b = t + 1;
984
985 141
        *lo = VNUM_uint(b, NULL, &b);
986 141
        if (*lo == -2)
987 0
                return ("Low number too big");
988 141
        if (*b++ != '-')
989 0
                return ("Missing hyphen");
990
991 141
        *hi = VNUM_uint(b, NULL, &b);
992 141
        if (*hi == -2)
993 0
                return ("High number too big");
994 141
        if (*lo == -1 && *hi == -1)
995 3
                return ("Neither high nor low");
996 138
        if (*lo == -1 && *hi == 0)
997 3
                return ("No low, high is zero");
998 135
        if (*hi >= 0 && *hi < *lo)
999 3
                return ("high smaller than low");
1000
1001 135
        while (vct_islws(*b))
1002 3
                b++;
1003 132
        if (*b != '\0')
1004 3
                return ("Trailing stuff");
1005
1006 129
        assert(*lo >= -1);
1007 129
        assert(*hi >= -1);
1008
1009 129
        if (len <= 0)
1010 48
                return (NULL);                  // Allow 200 response
1011
1012 81
        if (*lo < 0) {
1013 9
                assert(*hi > 0);
1014 9
                *lo = len - *hi;
1015 9
                if (*lo < 0)
1016 3
                        *lo = 0;
1017 9
                *hi = len - 1;
1018 81
        } else if (len >= 0 && (*hi >= len || *hi < 0)) {
1019 24
                *hi = len - 1;
1020 24
        }
1021
1022 81
        if (*lo >= len)
1023 3
                return ("low range beyond object");
1024
1025 78
        return (NULL);
1026 6081
}
1027
1028
/*--------------------------------------------------------------------
1029
 */
1030
1031
stream_close_t
1032 17310
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 17310
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1040 17310
        assert(sc_close == SC_REQ_CLOSE || sc_close == SC_RESP_CLOSE);
1041
1042 17310
        if (hp->protover == 10)
1043 116
                retval = SC_REQ_HTTP10;
1044
        else
1045 17194
                retval = SC_NULL;
1046
1047 17310
        http_CollectHdr(hp, H_Connection);
1048 17310
        if (!http_GetHdr(hp, H_Connection, &h))
1049 16781
                return (retval);
1050 529
        AN(h);
1051 1058
        while (http_split(&h, NULL, ",", &b, &e)) {
1052 538
                u = pdiff(b, e);
1053 538
                if (u == 5 && http_hdr_at(b, "close", u))
1054 433
                        retval = sc_close;
1055 538
                if (u == 10 && http_hdr_at(b, "keep-alive", u))
1056 69
                        retval = SC_NULL;
1057
1058
                /* Refuse removal of well-known-headers if they would pass. */
1059 538
                f = http_hdr_flags(b, e);
1060 538
                if (f != NULL && !(f->flag & HTTPH_R_PASS))
1061 9
                        return (SC_RX_BAD);
1062
1063 2571
                for (v = HTTP_HDR_FIRST; v < hp->nhd; v++) {
1064 2042
                        Tcheck(hp->hd[v]);
1065 2042
                        if (hp->hd[v].e < hp->hd[v].b + u + 1)
1066 93
                                continue;
1067 1949
                        if (hp->hd[v].b[u] != ':')
1068 1799
                                continue;
1069 150
                        if (!http_hdr_at(b, hp->hd[v].b, u))
1070 114
                                continue;
1071 36
                        hp->hdf[v] |= HDF_FILTER;
1072 36
                }
1073
        }
1074 520
        CHECK_OBJ_NOTNULL(retval, STREAM_CLOSE_MAGIC);
1075 520
        return (retval);
1076 17310
}
1077
1078
/*--------------------------------------------------------------------*/
1079
1080
int
1081 32743
http_HdrIs(const struct http *hp, hdr_t hdr, const char *val)
1082
{
1083
        const char *p;
1084
1085 32743
        if (!http_GetHdr(hp, hdr, &p))
1086 31018
                return (0);
1087 1725
        AN(p);
1088 1725
        if (http_tok_eq(p, val))
1089 1647
                return (1);
1090 78
        return (0);
1091 32743
}
1092
1093
/*--------------------------------------------------------------------*/
1094
1095
uint16_t
1096 42467
http_GetStatus(const struct http *hp)
1097
{
1098
1099 42467
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1100 42467
        return (hp->status);
1101
}
1102
1103
int
1104 29665
http_IsStatus(const struct http *hp, int val)
1105
{
1106
1107 29665
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1108 29665
        assert(val >= 100 && val <= 999);
1109 29665
        return (val == (hp->status % 1000));
1110
}
1111
1112
/*--------------------------------------------------------------------
1113
 * Setting the status will also set the Reason appropriately
1114
 */
1115
1116
void
1117 3345
http_SetStatus(struct http *to, uint16_t status, const char *reason)
1118
{
1119
        char buf[4];
1120 3345
        const char *sstr = NULL;
1121
1122 3345
        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 3345
        to->status = status;
1128 3345
        status %= 1000;
1129 3345
        assert(status >= 100);
1130
1131 3345
        if (reason == NULL)
1132 639
                reason = http_Status2Reason(status, &sstr);
1133
        else
1134 2706
                (void)http_Status2Reason(status, &sstr);
1135
1136 3345
        if (sstr) {
1137 3237
                http_SetH(to, HTTP_HDR_STATUS, sstr);
1138 3237
        } else {
1139 108
                bprintf(buf, "%03d", status);
1140 108
                http_PutField(to, HTTP_HDR_STATUS, buf);
1141
        }
1142 3345
        http_SetH(to, HTTP_HDR_REASON, reason);
1143 3345
}
1144
1145
/*--------------------------------------------------------------------*/
1146
1147
const char *
1148 15517
http_GetMethod(const struct http *hp)
1149
{
1150
1151 15517
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1152 15517
        Tcheck(hp->hd[HTTP_HDR_METHOD]);
1153 15517
        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 22905
http_ForceField(struct http *to, unsigned n, const char *t)
1162
{
1163
        int i;
1164
1165 22905
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1166 22905
        assert(n < HTTP_HDR_FIRST);
1167 22905
        assert(n == HTTP_HDR_METHOD || n == HTTP_HDR_PROTO);
1168 22905
        AN(t);
1169
1170
        /* NB: method names and protocol versions are case-sensitive. */
1171 22905
        if (to->hd[n].b == NULL || strcmp(to->hd[n].b, t)) {
1172 357
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
1173 357
                i += to->logtag;
1174
                /* XXX: this is a dead branch */
1175 357
                if (n >= HTTP_HDR_FIRST)
1176 0
                        VSLbt(to->vsl, (enum VSL_tag_e)i, to->hd[n]);
1177 357
                http_SetH(to, n, t);
1178 357
        }
1179 22905
}
1180
1181
/*--------------------------------------------------------------------*/
1182
1183
void
1184 3054
http_PutResponse(struct http *to, const char *proto, uint16_t status,
1185
    const char *reason)
1186
{
1187
1188 3054
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1189 3054
        if (proto != NULL)
1190 3054
                http_SetH(to, HTTP_HDR_PROTO, proto);
1191 3054
        http_SetStatus(to, status, reason);
1192 3054
}
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 118352
http_isfiltered(const struct http *fm, unsigned u, unsigned how)
1201
{
1202
        const char *e;
1203
        const struct http_hdrflg *f;
1204
1205 118352
        if (fm->hdf[u] & HDF_FILTER)
1206 51
                return (1);
1207 118301
        if (u < HTTP_HDR_FIRST)
1208 39732
                return (0);
1209 78569
        e = strchr(fm->hd[u].b, ':');
1210 78569
        if (e == NULL)
1211 0
                return (0);
1212 78569
        f = http_hdr_flags(fm->hd[u].b, e);
1213 78569
        return (f != NULL && f->flag & how);
1214 118352
}
1215
1216
int
1217 2520
http_IsFiltered(const struct http *fm, unsigned u, unsigned how)
1218
{
1219
1220 2520
        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 6632
http_EstimateWS(const struct http *fm, unsigned how)
1230
{
1231
        unsigned u, l;
1232
1233 6632
        l = 4;
1234 6632
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1235 63311
        for (u = 0; u < fm->nhd; u++) {
1236 56679
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1237 13264
                        continue;
1238 43415
                Tcheck(fm->hd[u]);
1239 43415
                if (http_isfiltered(fm, u, how))
1240 777
                        continue;
1241 42638
                l += Tlen(fm->hd[u]) + 1L;
1242 42638
        }
1243 6632
        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 6615
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 6615
        AN(p0);
1263 6615
        AN(l);
1264 6615
        p = p0;
1265 6615
        e = p + l;
1266 6615
        assert(p + 5 <= e);
1267 6615
        assert(fm->nhd <= fm->shd);
1268 6615
        n = HTTP_HDR_FIRST - 3;
1269 6615
        vbe16enc(p + 2, fm->status);
1270 6615
        p += 4;
1271 6615
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1272 63125
        for (u = 0; u < fm->nhd; u++) {
1273 56510
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1274 13230
                        continue;
1275 43280
                Tcheck(fm->hd[u]);
1276 43280
                if (http_isfiltered(fm, u, how))
1277 777
                        continue;
1278 42503
                http_VSLH(fm, u);
1279 42503
                w = Tlen(fm->hd[u]) + 1L;
1280 42503
                assert(p + w + 1 <= e);
1281 42503
                memcpy(p, fm->hd[u].b, w);
1282 42503
                p += w;
1283 42503
                n++;
1284 42503
        }
1285 6615
        *p++ = '\0';
1286 6615
        assert(p <= e);
1287 6615
        vbe16enc(p0, n + 1);
1288 6615
}
1289
1290
/*--------------------------------------------------------------------
1291
 * Decode byte string into http struct
1292
 */
1293
1294
int
1295 9643
HTTP_Decode(struct http *to, const uint8_t *fm)
1296
{
1297
1298 9643
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1299 9643
        AN(to->vsl);
1300 9643
        AN(fm);
1301 9643
        if (vbe16dec(fm) <= to->shd) {
1302 9636
                to->status = vbe16dec(fm + 2);
1303 9636
                fm += 4;
1304 91052
                for (to->nhd = 0; to->nhd < to->shd; to->nhd++) {
1305 91052
                        if (to->nhd == HTTP_HDR_METHOD ||
1306 81393
                            to->nhd == HTTP_HDR_URL) {
1307 19274
                                to->hd[to->nhd].b = NULL;
1308 19274
                                to->hd[to->nhd].e = NULL;
1309 19274
                                continue;
1310
                        }
1311 71778
                        if (*fm == '\0')
1312 9636
                                return (0);
1313 62142
                        to->hd[to->nhd].b = (const void*)fm;
1314 62142
                        fm = (const void*)strchr((const void*)fm, '\0');
1315 62142
                        to->hd[to->nhd].e = (const void*)fm;
1316 62142
                        fm++;
1317 62142
                        http_VSLH(to, to->nhd);
1318 62142
                }
1319 0
        }
1320 14
        VSLb(to->vsl, SLT_Error,
1321
            "Too many headers to Decode object (%u vs. %u)",
1322 7
            vbe16dec(fm), to->shd);
1323 7
        return (-1);
1324 9643
}
1325
1326
/*--------------------------------------------------------------------*/
1327
1328
uint16_t
1329 3
HTTP_GetStatusPack(struct worker *wrk, struct objcore *oc)
1330
{
1331
        const char *ptr;
1332 3
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1333 3
        AN(ptr);
1334
1335 3
        return (vbe16dec(ptr + 2));
1336
}
1337
1338
/*--------------------------------------------------------------------*/
1339
1340
/* Get the first packed header */
1341
int
1342 2203
HTTP_IterHdrPack(struct worker *wrk, struct objcore *oc, const char **p)
1343
{
1344
        const char *ptr;
1345
1346 2203
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1347 2203
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1348 2203
        AN(p);
1349
1350 2203
        if (*p == NULL) {
1351 695
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1352 695
                AN(ptr);
1353 695
                ptr += 4;       /* Skip nhd and status */
1354 695
                ptr = strchr(ptr, '\0') + 1;    /* Skip :proto: */
1355 695
                ptr = strchr(ptr, '\0') + 1;    /* Skip :status: */
1356 695
                ptr = strchr(ptr, '\0') + 1;    /* Skip :reason: */
1357 695
                *p = ptr;
1358 695
        } else {
1359 1508
                *p = strchr(*p, '\0') + 1;      /* Skip to next header */
1360
        }
1361 2203
        if (**p == '\0')
1362 133
                return (0);
1363 2070
        return (1);
1364 2203
}
1365
1366
const char *
1367 713
HTTP_GetHdrPack(struct worker *wrk, struct objcore *oc, hdr_t hdr)
1368
{
1369
        const char *ptr;
1370
        unsigned l;
1371
1372 713
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1373 713
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1374 713
        AN(hdr);
1375
1376 713
        l = hdr[0];
1377 713
        assert(l > 0);
1378 713
        assert(l == strlen(hdr + 1));
1379 713
        assert(hdr[l] == ':');
1380 713
        hdr++;
1381
1382 713
        if (hdr[0] == ':') {
1383
                /* Special cases */
1384 18
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1385 18
                AN(ptr);
1386 18
                ptr += 4;       /* Skip nhd and status */
1387
1388
                /* XXX: should we also have h2_hdr_eq() ? */
1389 18
                if (!strcmp(hdr, ":proto:"))
1390 3
                        return (ptr);
1391 15
                ptr = strchr(ptr, '\0') + 1;
1392 15
                if (!strcmp(hdr, ":status:"))
1393 12
                        return (ptr);
1394 3
                ptr = strchr(ptr, '\0') + 1;
1395 3
                if (!strcmp(hdr, ":reason:"))
1396 3
                        return (ptr);
1397 0
                WRONG("Unknown magic packed header");
1398 0
        }
1399
1400 2203
        HTTP_FOREACH_PACK(wrk, oc, ptr) {
1401 2070
                if (http_hdr_at(ptr, hdr, l)) {
1402 562
                        ptr += l;
1403 1121
                        while (vct_islws(*ptr))
1404 559
                                ptr++;
1405 562
                        return (ptr);
1406
                }
1407
        }
1408
1409 133
        return (NULL);
1410 713
}
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 84
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 84
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1426 84
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1427 84
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1428
1429 84
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1430 84
        AN(ptr);
1431
1432 84
        to->status = vbe16dec(ptr + 2);
1433 84
        ptr += 4;
1434
1435 504
        for (u = 0; u < HTTP_HDR_FIRST; u++) {
1436 420
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1437 168
                        continue;
1438 252
                http_SetH(to, u, ptr);
1439 252
                ptr = strchr(ptr, '\0') + 1;
1440 252
        }
1441 84
        nhd_before_merge = to->nhd;
1442 495
        while (*ptr != '\0') {
1443 411
                p = strchr(ptr, ':');
1444 411
                AN(p);
1445 411
                u = http_findhdr(to, p - ptr, ptr);
1446 411
                if (u == 0 || u >= nhd_before_merge)
1447 183
                        http_SetHeader(to, ptr);
1448 411
                ptr = strchr(ptr, '\0') + 1;
1449
        }
1450 84
}
1451
1452
/*--------------------------------------------------------------------*/
1453
1454
static void
1455 20384
http_linkh(const struct http *to, const struct http *fm, unsigned n)
1456
{
1457
1458 20384
        assert(n < HTTP_HDR_FIRST);
1459 20384
        Tcheck(fm->hd[n]);
1460 20384
        to->hd[n] = fm->hd[n];
1461 20384
        to->hdf[n] = fm->hdf[n];
1462 20384
        http_VSLH(to, n);
1463 20384
}
1464
1465
/*--------------------------------------------------------------------*/
1466
1467
void
1468 6795
http_FilterReq(struct http *to, const struct http *fm, unsigned how)
1469
{
1470
        unsigned u;
1471
1472 6795
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1473 6795
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1474
1475 6795
        http_linkh(to, fm, HTTP_HDR_METHOD);
1476 6795
        http_linkh(to, fm, HTTP_HDR_URL);
1477 6795
        http_linkh(to, fm, HTTP_HDR_PROTO);
1478 6795
        to->protover = fm->protover;
1479 6795
        to->status = fm->status;
1480
1481 6795
        to->nhd = HTTP_HDR_FIRST;
1482 35931
        for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
1483 29136
                Tcheck(fm->hd[u]);
1484 29136
                if (http_isfiltered(fm, u, how))
1485 333
                        continue;
1486 28803
                assert (to->nhd < to->shd);
1487 28803
                to->hd[to->nhd] = fm->hd[u];
1488 28803
                to->hdf[to->nhd] = 0;
1489 28803
                http_VSLH(to, to->nhd);
1490 28803
                to->nhd++;
1491 28803
        }
1492 6795
}
1493
1494
/*--------------------------------------------------------------------
1495
 * This function copies any header fields which reference foreign
1496
 * storage into our own WS.
1497
 */
1498
1499
void
1500 6702
http_CopyHome(const struct http *hp)
1501
{
1502
        unsigned u, l;
1503
        const char *p;
1504
1505 72810
        for (u = 0; u < hp->nhd; u++) {
1506 66108
                if (hp->hd[u].b == NULL) {
1507 13404
                        assert(u < HTTP_HDR_FIRST);
1508 13404
                        continue;
1509
                }
1510
1511 52704
                l = Tlen(hp->hd[u]);
1512 52704
                if (WS_Allocated(hp->ws, hp->hd[u].b, l))
1513 4212
                        continue;
1514
1515 48492
                p = WS_Copy(hp->ws, hp->hd[u].b, l + 1L);
1516 48492
                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 48492
                hp->hd[u].b = p;
1522 48492
                hp->hd[u].e = p + l;
1523 48492
        }
1524 6702
}
1525
1526
/*--------------------------------------------------------------------*/
1527
1528
void
1529 27648
http_SetHeader(struct http *to, const char *header)
1530
{
1531
1532 27648
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1533 27648
        if (to->nhd >= to->shd) {
1534 3
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(header));
1535 3
                http_fail(to);
1536 3
                return;
1537
        }
1538 27645
        http_SetH(to, to->nhd++, header);
1539 27648
}
1540
1541
/*--------------------------------------------------------------------*/
1542
1543
void
1544 12355
http_ForceHeader(struct http *to, hdr_t hdr, const char *val)
1545
{
1546
1547 12355
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1548 12355
        if (http_HdrIs(to, hdr, val))
1549 1110
                return;
1550 11245
        http_Unset(to, hdr);
1551 11245
        http_PrintfHeader(to, "%s %s", hdr + 1, val);
1552 12355
}
1553
1554
void
1555 31597
http_AppendHeader(struct http *to, hdr_t hdr, const char *val)
1556
{
1557
        const char *old;
1558
1559 31597
        http_CollectHdr(to, hdr);
1560 31597
        if (http_GetHdr(to, hdr, &old)) {
1561 144
                http_Unset(to, hdr);
1562 144
                http_PrintfHeader(to, "%s %s, %s", hdr + 1, old, val);
1563 144
        } else {
1564 31453
                http_PrintfHeader(to, "%s %s", hdr + 1, val);
1565
        }
1566 31597
}
1567
1568
void
1569 74295
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 74295
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1577
1578 74295
        va_start(ap, fmt);
1579 74295
        va_copy(ap2, ap);
1580
1581 74295
        WS_VSB_new(vsb, to->ws);
1582 74295
        VSB_vprintf(vsb, fmt, ap);
1583 74295
        p = WS_VSB_finish(vsb, to->ws, &sz);
1584
1585 74295
        if (p == NULL || to->nhd >= to->shd) {
1586 80
                http_fail(to);
1587 80
                VSLbv(to->vsl, SLT_LostHeader, fmt, ap2);
1588 80
        } else {
1589 74215
                http_SetH(to, to->nhd++, p);
1590
        }
1591 74295
        va_end(ap);
1592 74295
        va_end(ap2);
1593 74295
}
1594
1595
void
1596 3081
http_TimeHeader(struct http *to, const char *fmt, vtim_real now)
1597
{
1598
        char *p;
1599
1600 3081
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1601 3081
        if (to->nhd >= to->shd) {
1602 0
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1603 0
                http_fail(to);
1604 0
                return;
1605
        }
1606 3081
        p = WS_Alloc(to->ws, strlen(fmt) + VTIM_FORMAT_SIZE);
1607 3081
        if (p == NULL) {
1608 231
                http_fail(to);
1609 231
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1610 231
                return;
1611
        }
1612 2850
        strcpy(p, fmt);
1613 2850
        VTIM_format(now, strchr(p, '\0'));
1614 2850
        http_SetH(to, to->nhd++, p);
1615 3081
}
1616
1617
const char *
1618 20618
http_ViaHeader(void)
1619
{
1620
1621 20618
        return (via_hdr);
1622
}
1623
1624
/*--------------------------------------------------------------------*/
1625
1626
void
1627 67804
http_Unset(struct http *hp, hdr_t hdr)
1628
{
1629
        uint16_t u, v;
1630
1631 438676
        for (v = u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
1632 370872
                Tcheck(hp->hd[u]);
1633 370872
                if (http_IsHdr(&hp->hd[u], hdr)) {
1634 2835
                        http_VSLH_del(hp, u);
1635 2835
                        continue;
1636
                }
1637 368037
                if (v != u) {
1638 7287
                        memcpy(&hp->hd[v], &hp->hd[u], sizeof *hp->hd);
1639 7287
                        memcpy(&hp->hdf[v], &hp->hdf[u], sizeof *hp->hdf);
1640 7287
                }
1641 368037
                v++;
1642 368037
        }
1643 67804
        hp->nhd = v;
1644 67804
}