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) hdr_t b = HDR(a);
57
#include "tbl/http_headers.h"
58
59
hdr_t H__Status = HDR(":status");
60
hdr_t H__Proto  = HDR(":proto");
61
hdr_t H__Reason = HDR(":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
        hdr_t           *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 382094
http_hdr_flags(const char *b, const char *e)
183
{
184
        unsigned u;
185
        struct http_hdrflg *retval;
186
187 382094
        if (b == NULL || e == NULL)
188 32
                return (NULL);
189 382094
        u = pdiff(b, e);
190 382094
        if (u < GPERF_MIN_WORD_LENGTH || u > GPERF_MAX_WORD_LENGTH)
191 175
                return (NULL);
192 763838
        u += http_asso_values[(uint8_t)(e[-1])] +
193 381919
             http_asso_values[(uint8_t)(b[0])];
194 381919
        if (u > GPERF_MAX_HASH_VALUE)
195 5230
                return (NULL);
196 376689
        retval = &http_hdrflg[u];
197 376689
        if (retval->hdr == NULL)
198 1451
                return (NULL);
199 375238
        AN(*retval->hdr);
200 375238
        if (!http_hdr_at(*retval->hdr + 1, b, e - b))
201 5305
                return (NULL);
202 369933
        return (retval);
203 382094
}
204
205
/*--------------------------------------------------------------------*/
206
207
static void
208 247104
http_init_hdr(hdr_t hdr, int flg)
209
{
210
        struct http_hdrflg *f;
211
212 247104
        f = http_hdr_flags(hdr->str, hdr->str + hdr->len - 1);
213 247104
        AN(f);
214 247104
        assert(*f->hdr == hdr);
215 247104
        f->flag = flg;
216 247104
}
217
218
void
219 4752
HTTP_Init(void)
220
{
221
        struct vsb *vsb;
222
223
#define HTTPH(a, b, c) http_init_hdr(b, c);
224
#include "tbl/http_headers.h"
225
226
        vsb = VSB_new_auto();
227 4752
        AN(vsb);
228
        VSB_printf(vsb, "1.1 %s (Varnish/" PACKAGE_BRANCH ")",
229
            heritage.identity);
230 4752
        AZ(VSB_finish(vsb));
231 4752
        REPLACE(via_hdr, VSB_data(vsb));
232
        VSB_destroy(&vsb);
233
}
234
235
/*--------------------------------------------------------------------
236
 * These two functions are in an incestuous relationship with the
237
 * order of macros in include/tbl/vsl_tags_http.h
238
 *
239
 * The http->logtag is the SLT_*Method enum, and we add to that, to
240
 * get the SLT_ to use.
241
 */
242
243
static void
244 633309
http_VSLH(const struct http *hp, unsigned hdr)
245
{
246
        int i;
247
248 633309
        if (hp->vsl != NULL) {
249 633322
                assert(VXID_TAG(hp->vsl->wid));
250 633322
                i = hdr;
251 633322
                if (i > HTTP_HDR_FIRST)
252 333480
                        i = HTTP_HDR_FIRST;
253 633322
                i += hp->logtag;
254 633322
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
255 633322
        }
256 633339
}
257
258
static void
259 5190
http_VSLH_del(const struct http *hp, unsigned hdr)
260
{
261
        int i;
262
263 5190
        if (hp->vsl != NULL) {
264
                /* We don't support unsetting stuff in the first line */
265 5190
                assert (hdr >= HTTP_HDR_FIRST);
266 5190
                assert(VXID_TAG(hp->vsl->wid));
267 5190
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
268 5190
                i += hp->logtag;
269 5190
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
270 5190
        }
271 5190
}
272
273
/*--------------------------------------------------------------------*/
274
275
void
276 29455
http_VSL_log(const struct http *hp)
277
{
278
        unsigned u;
279
280 257299
        for (u = 0; u < hp->nhd; u++)
281 396791
                if (hp->hd[u].b != NULL)
282 168947
                        http_VSLH(hp, u);
283 29455
}
284
285
/*--------------------------------------------------------------------*/
286
287
static void
288 520
http_fail(const struct http *hp)
289
{
290
        char id[WS_ID_SIZE];
291
292 520
        VSC_C_main->losthdr++;
293 520
        WS_Id(hp->ws, id);
294 520
        VSLb(hp->vsl, SLT_Error, "out of workspace (%s)", id);
295 520
        WS_MarkOverflow(hp->ws);
296 520
}
297
298
/*--------------------------------------------------------------------
299
 * List of canonical HTTP response code names from RFC2616
300
 */
301
302
static struct http_msg {
303
        unsigned        nbr;
304
        const char      *status;
305
        const char      *txt;
306
} http_msg[] = {
307
#define HTTP_RESP(n, t) { n, #n, t},
308
#include "tbl/http_response.h"
309
        { 0, "0", NULL }
310
};
311
312
const char *
313 7475
http_Status2Reason(unsigned status, const char **sstr)
314
{
315
        struct http_msg *mp;
316
317 7475
        status %= 1000;
318 7475
        assert(status >= 100);
319 227834
        for (mp = http_msg; mp->nbr != 0 && mp->nbr <= status; mp++)
320 227609
                if (mp->nbr == status) {
321 7250
                        if (sstr)
322 5540
                                *sstr = mp->status;
323 7250
                        return (mp->txt);
324
                }
325 225
        return ("Unknown HTTP Status");
326 7475
}
327
328
/*--------------------------------------------------------------------*/
329
330
unsigned
331 26889
HTTP_estimate(unsigned nhttp)
332
{
333
334
        /* XXX: We trust the structs to size-aligned as necessary */
335 26889
        return (PRNDUP(sizeof(struct http) + sizeof(txt) * nhttp + nhttp));
336
}
337
338
struct http *
339 80664
HTTP_create(void *p, uint16_t nhttp, unsigned len)
340
{
341
        struct http *hp;
342
343 80664
        hp = p;
344 80664
        hp->magic = HTTP_MAGIC;
345 80664
        hp->hd = (void*)(hp + 1);
346 80664
        hp->shd = nhttp;
347 80664
        hp->hdf = (void*)(hp->hd + nhttp);
348 80664
        assert((unsigned char*)p + len == hp->hdf + PRNDUP(nhttp));
349 80664
        return (hp);
350
}
351
352
/*--------------------------------------------------------------------*/
353
354
void
355 75217
HTTP_Setup(struct http *hp, struct ws *ws, struct vsl_log *vsl,
356
    enum VSL_tag_e  whence)
357
{
358 75217
        http_Teardown(hp);
359 75217
        hp->nhd = HTTP_HDR_FIRST;
360 75217
        hp->logtag = whence;
361 75217
        hp->ws = ws;
362 75217
        hp->vsl = vsl;
363 75217
}
364
365
/*--------------------------------------------------------------------
366
 * http_Teardown() is a safety feature, we use it to zap all http
367
 * structs once we're done with them, to minimize the risk that
368
 * old stale pointers exist to no longer valid stuff.
369
 */
370
371
void
372 117420
http_Teardown(struct http *hp)
373
{
374
375 117420
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
376 117420
        AN(hp->shd);
377 117420
        memset(&hp->nhd, 0, sizeof *hp - offsetof(struct http, nhd));
378 117420
        memset(hp->hd, 0, sizeof *hp->hd * hp->shd);
379 117420
        memset(hp->hdf, 0, sizeof *hp->hdf * hp->shd);
380 117420
}
381
382
/*--------------------------------------------------------------------
383
 * Duplicate the http content into another http
384
 * We cannot just memcpy the struct because the hd & hdf are private
385
 * storage to the struct http.
386
 */
387
388
void
389 33026
HTTP_Dup(struct http *to, const struct http * fm)
390
{
391
392 33026
        assert(fm->nhd <= to->shd);
393 33026
        memcpy(to->hd, fm->hd, fm->nhd * sizeof *to->hd);
394 33026
        memcpy(to->hdf, fm->hdf, fm->nhd * sizeof *to->hdf);
395 33026
        to->nhd = fm->nhd;
396 33026
        to->logtag = fm->logtag;
397 33026
        to->status = fm->status;
398 33026
        to->protover = fm->protover;
399 33026
}
400
401
402
/*--------------------------------------------------------------------
403
 * Clone the entire http structure, including vsl & ws
404
 */
405
406
void
407 31197
HTTP_Clone(struct http *to, const struct http * const fm)
408
{
409
410 31197
        HTTP_Dup(to, fm);
411 31197
        to->vsl = fm->vsl;
412 31197
        to->ws = fm->ws;
413 31197
}
414
415
/*--------------------------------------------------------------------*/
416
417
void
418 33709
http_Proto(struct http *to)
419
{
420
        const char *fm;
421
422 33709
        fm = to->hd[HTTP_HDR_PROTO].b;
423
424 67373
        if (fm != NULL &&
425 33669
            (fm[0] == 'H' || fm[0] == 'h') &&
426 33664
            (fm[1] == 'T' || fm[1] == 't') &&
427 33664
            (fm[2] == 'T' || fm[2] == 't') &&
428 33664
            (fm[3] == 'P' || fm[3] == 'p') &&
429 33664
            fm[4] == '/' &&
430 33664
            vct_isdigit(fm[5]) &&
431 33664
            fm[6] == '.' &&
432 33664
            vct_isdigit(fm[7]) &&
433 33664
            fm[8] == '\0') {
434 33664
                to->protover = 10 * (fm[5] - '0') + (fm[7] - '0');
435 33664
        } else {
436 45
                to->protover = 0;
437
        }
438 33709
}
439
440
/*--------------------------------------------------------------------*/
441
442
void
443 200912
http_SetH(struct http *to, unsigned n, const char *header)
444
{
445
446 200912
        assert(n < to->nhd);
447 200912
        AN(header);
448 200912
        to->hd[n].b = TRUST_ME(header);
449 200912
        to->hd[n].e = strchr(to->hd[n].b, '\0');
450 200912
        to->hdf[n] = 0;
451 200912
        http_VSLH(to, n);
452 200912
        if (n == HTTP_HDR_PROTO)
453 6894
                http_Proto(to);
454 200912
}
455
456
/*--------------------------------------------------------------------*/
457
458
static void
459 180
http_PutField(struct http *to, int field, const char *string)
460
{
461
        const char *p;
462
463 180
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
464 180
        p = WS_Copy(to->ws, string, -1);
465 180
        if (p == NULL) {
466 5
                http_fail(to);
467 5
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(string));
468 5
                return;
469
        }
470 175
        http_SetH(to, field, p);
471 180
}
472
473
/*--------------------------------------------------------------------*/
474
475
int
476 733398
http_IsHdr(const txt *hh, hdr_t hdr)
477
{
478
479 733398
        Tcheck(*hh);
480 733398
        CHECK_HDR(hdr);
481 733398
        return (http_hdr_at(hdr->str, hh->b, hdr->len));
482
}
483
484
/*--------------------------------------------------------------------*/
485
486
static unsigned
487 756296
http_findhdr(const struct http *hp, unsigned l, const char *hdr)
488
{
489
        unsigned u;
490
491 3285289
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
492 2696625
                Tcheck(hp->hd[u]);
493 2696625
                if (hp->hd[u].e < hp->hd[u].b + l + 1)
494 486589
                        continue;
495 2210036
                if (hp->hd[u].b[l] != ':')
496 1858121
                        continue;
497 351915
                if (!http_hdr_at(hdr, hp->hd[u].b, l))
498 184283
                        continue;
499 167632
                return (u);
500
        }
501 588664
        return (0);
502 756296
}
503
504
/*--------------------------------------------------------------------
505
 * Count how many instances we have of this header
506
 */
507
508
unsigned
509 38229
http_CountHdr(const struct http *hp, hdr_t hdr)
510
{
511 38229
        unsigned retval = 0;
512
        unsigned u;
513
514 38229
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
515
516 127448
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
517 89219
                Tcheck(hp->hd[u]);
518 89219
                if (http_IsHdr(&hp->hd[u], hdr))
519 18891
                        retval++;
520 89219
        }
521 38229
        return (retval);
522
}
523
524
/*--------------------------------------------------------------------
525
 * This function collapses multiple header lines of the same name.
526
 * The lines are joined with a comma, according to [rfc2616, 4.2bot, p32]
527
 */
528
529
void
530 122988
http_CollectHdr(struct http *hp, hdr_t hdr)
531
{
532
533 122988
        http_CollectHdrSep(hp, hdr, NULL);
534 122988
}
535
536
/*--------------------------------------------------------------------
537
 * You may prefer to collapse header fields using a different separator.
538
 * For Cookie headers, the separator is "; " for example. That's probably
539
 * the only example too.
540
 */
541
542
void
543 123749
http_CollectHdrSep(struct http *hp, hdr_t hdr, const char *sep)
544
{
545
        unsigned u, lsep, ml, f, x, d;
546 123749
        char *b = NULL, *e = NULL;
547
        const char *v;
548
549 123749
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
550 123749
        CHECK_HDR(hdr);
551
552 123749
        if (WS_Overflowed(hp->ws))
553 100
                return;
554
555 123649
        if (sep == NULL || *sep == '\0')
556 122890
                sep = ", ";
557 123657
        lsep = strlen(sep);
558
559 123657
        f = http_findhdr(hp, hdr->len - 1, hdr->str);
560 123657
        if (f == 0)
561 121581
                return;
562
563 7636
        for (d = u = f + 1; u < hp->nhd; u++) {
564 5560
                Tcheck(hp->hd[u]);
565 5560
                if (!http_IsHdr(&hp->hd[u], hdr)) {
566 5470
                        if (d != u) {
567 355
                                hp->hd[d] = hp->hd[u];
568 355
                                hp->hdf[d] = hp->hdf[u];
569 355
                        }
570 5470
                        d++;
571 5470
                        continue;
572
                }
573 90
                if (b == NULL) {
574
                        /* Found second header, start our collection */
575 80
                        ml = WS_ReserveAll(hp->ws);
576 80
                        b = WS_Reservation(hp->ws);
577 80
                        e = b + ml;
578 80
                        x = Tlen(hp->hd[f]);
579 80
                        if (b + x >= e) {
580 0
                                http_fail(hp);
581 0
                                VSLbs(hp->vsl, SLT_LostHeader,
582 0
                                    TOSTRAND(hdr->str));
583 0
                                WS_Release(hp->ws, 0);
584 0
                                return;
585
                        }
586 80
                        memcpy(b, hp->hd[f].b, x);
587 80
                        b += x;
588 80
                }
589
590 90
                AN(b);
591 90
                AN(e);
592
593
                /* Append the Nth header we found */
594 90
                x = Tlen(hp->hd[u]) - hdr->len;
595
596 90
                v = hp->hd[u].b + hdr->len;
597 180
                while (vct_issp(*v)) {
598 90
                        v++;
599 90
                        x--;
600
                }
601
602 90
                if (b + lsep + x >= e) {
603 0
                        http_fail(hp);
604 0
                        VSLbs(hp->vsl, SLT_LostHeader, TOSTRAND(hdr->str));
605 0
                        WS_Release(hp->ws, 0);
606 0
                        return;
607
                }
608 90
                memcpy(b, sep, lsep);
609 90
                b += lsep;
610 90
                memcpy(b, v, x);
611 90
                b += x;
612 90
        }
613 2076
        if (b == NULL)
614 1996
                return;
615 80
        hp->nhd = (uint16_t)d;
616 80
        AN(e);
617 80
        *b = '\0';
618 80
        hp->hd[f].b = WS_Reservation(hp->ws);
619 80
        hp->hd[f].e = b;
620 80
        WS_ReleaseP(hp->ws, b + 1);
621 123757
}
622
623
/*--------------------------------------------------------------------*/
624
625
int
626 631899
http_GetHdr(const struct http *hp, hdr_t hdr, const char **ptr)
627
{
628
        unsigned u;
629
        const char *p;
630
631 631899
        CHECK_HDR(hdr);
632 631899
        u = http_findhdr(hp, hdr->len - 1, hdr->str);
633 631899
        if (u == 0) {
634 466757
                if (ptr != NULL)
635 429042
                        *ptr = NULL;
636 466757
                return (0);
637
        }
638 165142
        if (ptr != NULL) {
639 135143
                p = hp->hd[u].b + hdr->len;
640 270065
                while (vct_issp(*p))
641 134922
                        p++;
642 135143
                *ptr = p;
643 135143
        }
644 165142
        return (1);
645 631899
}
646
647
/*-----------------------------------------------------------------------------
648
 * Split source string at any of the separators, return pointer to first
649
 * and last+1 char of substrings, with whitespace trimmed at both ends.
650
 * If sep being an empty string is shorthand for VCT::SP
651
 * If stop is NULL, src is NUL terminated.
652
 */
653
654
static int
655 12429
http_split(const char **src, const char *stop, const char *sep,
656
    const char **b, const char **e)
657
{
658
        const char *p, *q;
659
660 12429
        AN(src);
661 12429
        AN(*src);
662 12429
        AN(sep);
663 12429
        AN(b);
664 12429
        AN(e);
665
666 12429
        if (stop == NULL)
667 12394
                stop = strchr(*src, '\0');
668
669 21291
        for (p = *src; p < stop && (vct_issp(*p) || strchr(sep, *p)); p++)
670 435
                continue;
671
672 12429
        if (p >= stop) {
673 4437
                *b = NULL;
674 4437
                *e = NULL;
675 4437
                return (0);
676
        }
677
678 7992
        *b = p;
679 7992
        if (*sep == '\0') {
680 0
                for (q = p + 1; q < stop && !vct_issp(*q); q++)
681 0
                        continue;
682 0
                *e = q;
683 0
                *src = q;
684 0
                return (1);
685
        }
686 38902
        for (q = p + 1; q < stop && !strchr(sep, *q); q++)
687 30910
                continue;
688 7992
        *src = q;
689 7992
        while (q > p && vct_issp(q[-1]))
690 0
                q--;
691 7992
        *e = q;
692 7992
        return (1);
693 12429
}
694
695
/*-----------------------------------------------------------------------------
696
 * Comparison rule for tokens:
697
 *      if target string starts with '"', we use memcmp() and expect closing
698
 *      double quote as well
699
 *      otherwise we use http_tok_at()
700
 *
701
 * On match we increment *bp past the token name.
702
 */
703
704
static int
705 7050
http_istoken(const char **bp, const char *e, const char *token)
706
{
707 7050
        int fl = strlen(token);
708
        const char *b;
709
710 7050
        AN(bp);
711 7050
        AN(e);
712 7050
        AN(token);
713
714 7050
        b = *bp;
715
716 7050
        if (b + fl + 2 <= e && *b == '"' &&
717 0
            !memcmp(b + 1, token, fl) && b[fl + 1] == '"') {
718 0
                *bp += fl + 2;
719 0
                return (1);
720
        }
721 7255
        if (b + fl <= e && http_tok_at(b, token, fl) &&
722 3305
            (b + fl == e || !vct_istchar(b[fl]))) {
723 3305
                *bp += fl;
724 3305
                return (1);
725
        }
726 3745
        return (0);
727 7050
}
728
729
/*-----------------------------------------------------------------------------
730
 * Find a given data element (token) in a header according to RFC2616's #rule
731
 * (section 2.1, p15)
732
 *
733
 * On case sensitivity:
734
 *
735
 * Section 4.2 (Messages Headers) defines field (header) name as case
736
 * insensitive, but the field (header) value/content may be case-sensitive.
737
 *
738
 * http_GetHdrToken looks up a token in a header value and the rfc does not say
739
 * explicitly if tokens are to be compared with or without respect to case.
740
 *
741
 * But all examples and specific statements regarding tokens follow the rule
742
 * that unquoted tokens are to be matched case-insensitively and quoted tokens
743
 * case-sensitively.
744
 *
745
 * The optional pb and pe arguments will point to the token content start and
746
 * end+1, white space trimmed on both sides.
747
 */
748
749
int
750 75425
http_GetHdrToken(const struct http *hp, hdr_t hdr,
751
    const char *token, const char **pb, const char **pe)
752
{
753
        const char *h, *b, *e;
754
755 75425
        if (pb != NULL)
756 56990
                *pb = NULL;
757 75425
        if (pe != NULL)
758 17813
                *pe = NULL;
759 75425
        if (!http_GetHdr(hp, hdr, &h))
760 68560
                return (0);
761 6865
        AN(h);
762
763 10610
        while (http_split(&h, NULL, ",", &b, &e))
764 7050
                if (http_istoken(&b, e, token))
765 3305
                        break;
766 6865
        if (b == NULL)
767 3560
                return (0);
768 3305
        if (pb != NULL) {
769 3285
                for (; vct_islws(*b); b++)
770 25
                        continue;
771 3260
                if (b == e) {
772 3060
                        b = NULL;
773 3060
                        e = NULL;
774 3060
                }
775 3260
                *pb = b;
776 3260
                if (pe != NULL)
777 3025
                        *pe = e;
778 3260
        }
779 3305
        return (1);
780 75425
}
781
782
/*--------------------------------------------------------------------
783
 * Find a given header field's quality value (qvalue).
784
 */
785
786
double
787 17815
http_GetHdrQ(const struct http *hp, hdr_t hdr, const char *field)
788
{
789
        const char *hb, *he, *b, *e;
790
        int i;
791
        double a, f;
792
793 17815
        i = http_GetHdrToken(hp, hdr, field, &hb, &he);
794 17815
        if (!i)
795 14790
                return (0.);
796
797 3025
        if (hb == NULL)
798 2990
                return (1.);
799 35
        while (http_split(&hb, he, ";", &b, &e)) {
800 35
                if (*b != 'q')
801 0
                        continue;
802 35
                for (b++; b < e && vct_issp(*b); b++)
803 0
                        continue;
804 35
                if (b == e || *b != '=')
805 0
                        continue;
806 35
                break;
807
        }
808 35
        if (b == NULL)
809 0
                return (1.);
810 35
        for (b++; b < e && vct_issp(*b); b++)
811 0
                continue;
812 35
        if (b == e || (*b != '.' && !vct_isdigit(*b)))
813 5
                return (0.);
814 30
        a = 0;
815 60
        while (b < e && vct_isdigit(*b)) {
816 30
                a *= 10.;
817 30
                a += *b - '0';
818 30
                b++;
819
        }
820 30
        if (b == e || *b++ != '.')
821 5
                return (a);
822 25
        f = .1;
823 80
        while (b < e && vct_isdigit(*b)) {
824 55
                a += f * (*b - '0');
825 55
                f *= .1;
826 55
                b++;
827
        }
828 25
        return (a);
829 17815
}
830
831
/*--------------------------------------------------------------------
832
 * Find a given header field's value.
833
 */
834
835
int
836 39179
http_GetHdrField(const struct http *hp, hdr_t hdr,
837
    const char *field, const char **ptr)
838
{
839
        const char *h;
840
        int i;
841
842 39179
        if (ptr != NULL)
843 19945
                *ptr = NULL;
844
845 39179
        h = NULL;
846 39179
        i = http_GetHdrToken(hp, hdr, field, &h, NULL);
847 39179
        if (!i)
848 38944
                return (i);
849
850 235
        if (ptr != NULL && h != NULL) {
851
                /* Skip whitespace, looking for '=' */
852 165
                while (*h && vct_issp(*h))
853 0
                        h++;
854 165
                if (*h == '=') {
855 165
                        h++;
856 185
                        while (*h && vct_issp(*h))
857 20
                                h++;
858 165
                        *ptr = h;
859 165
                }
860 165
        }
861 235
        return (i);
862 39179
}
863
864
/*--------------------------------------------------------------------*/
865
866
ssize_t
867 56330
http_GetContentLength(const struct http *hp)
868
{
869
        ssize_t cl;
870
        const char *b;
871
872 56330
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
873
874 56330
        if (!http_GetHdr(hp, H_Content_Length, &b))
875 22122
                return (-1);
876 34208
        cl = VNUM_uint(b, NULL, &b);
877 34208
        if (cl < 0)
878 20
                return (-2);
879 34188
        while (vct_islws(*b))
880 0
                b++;
881 34188
        if (*b != '\0')
882 0
                return (-2);
883 34188
        return (cl);
884 56330
}
885
886
ssize_t
887 10105
http_GetContentRange(const struct http *hp, ssize_t *lo, ssize_t *hi)
888
{
889
        ssize_t tmp, cl;
890
        const char *b, *t;
891
892 10105
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
893
894 10105
        if (lo == NULL)
895 0
                lo = &tmp;
896 10105
        if (hi == NULL)
897 0
                hi = &tmp;
898
899 10105
        *lo = *hi = -1;
900
901 10105
        if (!http_GetHdr(hp, H_Content_Range, &b))
902 10055
                return (-1);
903
904 50
        t = strchr(b, ' ');
905 50
        if (t == NULL)
906 5
                return (-2);            // Missing space after range unit
907
908 45
        if (!http_range_at(b, bytes, t - b))
909 5
                return (-1);            // Unknown range unit, ignore
910 40
        b = t + 1;
911
912 40
        if (*b == '*') {                // Content-Range: bytes */123
913 15
                *lo = *hi = -1;
914 15
                b++;
915 15
        } else {                        // Content-Range: bytes 1-2/3
916 25
                *lo = VNUM_uint(b, NULL, &b);
917 25
                if (*lo < 0)
918 0
                        return (-2);
919 25
                if (*b != '-')
920 0
                        return (-2);
921 25
                *hi = VNUM_uint(b + 1, NULL, &b);
922 25
                if (*hi < 0)
923 0
                        return (-2);
924
        }
925 40
        if (*b != '/')
926 0
                return (-2);
927 40
        if (b[1] == '*') {              // Content-Range: bytes 1-2/*
928 5
                cl = -1;
929 5
                b += 2;
930 5
        } else {
931 35
                cl = VNUM_uint(b + 1, NULL, &b);
932 35
                if (cl <= 0)
933 0
                        return (-2);
934
        }
935 40
        while (vct_islws(*b))
936 0
                b++;
937 40
        if (*b != '\0')
938 0
                return (-2);
939 40
        if (*lo > *hi)
940 0
                return (-2);
941 40
        assert(cl >= -1);
942 40
        if (*lo >= cl || *hi >= cl)
943 5
                return (-2);
944 35
        AN(cl);
945 35
        return (cl);
946 10105
}
947
948
const char *
949 10350
http_GetRange(const struct http *hp, ssize_t *lo, ssize_t *hi, ssize_t len)
950
{
951
        ssize_t tmp_lo, tmp_hi;
952
        const char *b, *t;
953
954 10350
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
955
956 10350
        if (lo == NULL)
957 0
                lo = &tmp_lo;
958 10350
        if (hi == NULL)
959 0
                hi = &tmp_hi;
960
961 10350
        *lo = *hi = -1;
962
963 10350
        if (!http_GetHdr(hp, H_Range, &b))
964 10075
                return (NULL);
965
966 275
        t = strchr(b, '=');
967 275
        if (t == NULL)
968 10
                return ("Missing '='");
969
970 265
        if (!http_range_at(b, bytes, t - b))
971 15
                return ("Not Bytes");
972 250
        b = t + 1;
973
974 250
        *lo = VNUM_uint(b, NULL, &b);
975 250
        if (*lo == -2)
976 0
                return ("Low number too big");
977 250
        if (*b++ != '-')
978 0
                return ("Missing hyphen");
979
980 250
        *hi = VNUM_uint(b, NULL, &b);
981 250
        if (*hi == -2)
982 0
                return ("High number too big");
983 250
        if (*lo == -1 && *hi == -1)
984 5
                return ("Neither high nor low");
985 245
        if (*lo == -1 && *hi == 0)
986 5
                return ("No low, high is zero");
987 240
        if (*hi >= 0 && *hi < *lo)
988 5
                return ("high smaller than low");
989
990 240
        while (vct_islws(*b))
991 5
                b++;
992 235
        if (*b != '\0')
993 5
                return ("Trailing stuff");
994
995 230
        assert(*lo >= -1);
996 230
        assert(*hi >= -1);
997
998 230
        if (*lo < 0) {
999 20
                assert(*hi > 0);
1000 20
                *lo = len - *hi;
1001 20
                if (*lo < 0)
1002 10
                        *lo = 0;
1003 20
                *hi = len - 1;
1004 230
        } else if (len >= 0 && (*hi >= len || *hi < 0)) {
1005 45
                *hi = len - 1;
1006 45
        }
1007
1008 230
        if (len <= 0)
1009 90
                return (NULL);                  // Allow 200 response
1010
1011 140
        if (*lo >= len)
1012 5
                return ("low range beyond object");
1013
1014 135
        return (NULL);
1015 10350
}
1016
1017
/*--------------------------------------------------------------------
1018
 */
1019
1020
stream_close_t
1021 29610
http_DoConnection(struct http *hp, stream_close_t sc_close)
1022
{
1023
        const char *h, *b, *e;
1024
        stream_close_t retval;
1025
        unsigned u, v;
1026
        struct http_hdrflg *f;
1027
1028 29610
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1029 29610
        assert(sc_close == SC_REQ_CLOSE || sc_close == SC_RESP_CLOSE);
1030
1031 29610
        if (hp->protover == 10)
1032 195
                retval = SC_REQ_HTTP10;
1033
        else
1034 29415
                retval = SC_NULL;
1035
1036 29610
        http_CollectHdr(hp, H_Connection);
1037 29610
        if (!http_GetHdr(hp, H_Connection, &h))
1038 28718
                return (retval);
1039 892
        AN(h);
1040 1784
        while (http_split(&h, NULL, ",", &b, &e)) {
1041 907
                u = pdiff(b, e);
1042 907
                if (u == 5 && http_hdr_at(b, "close", u))
1043 731
                        retval = sc_close;
1044 907
                if (u == 10 && http_hdr_at(b, "keep-alive", u))
1045 115
                        retval = SC_NULL;
1046
1047
                /* Refuse removal of well-known-headers if they would pass. */
1048 907
                f = http_hdr_flags(b, e);
1049 907
                if (f != NULL && !(f->flag & HTTPH_R_PASS))
1050 15
                        return (SC_RX_BAD);
1051
1052 4320
                for (v = HTTP_HDR_FIRST; v < hp->nhd; v++) {
1053 3428
                        Tcheck(hp->hd[v]);
1054 3428
                        if (hp->hd[v].e < hp->hd[v].b + u + 1)
1055 155
                                continue;
1056 3273
                        if (hp->hd[v].b[u] != ':')
1057 3023
                                continue;
1058 250
                        if (!http_hdr_at(b, hp->hd[v].b, u))
1059 190
                                continue;
1060 60
                        hp->hdf[v] |= HDF_FILTER;
1061 60
                }
1062
        }
1063 877
        CHECK_OBJ_NOTNULL(retval, STREAM_CLOSE_MAGIC);
1064 877
        return (retval);
1065 29610
}
1066
1067
/*--------------------------------------------------------------------*/
1068
1069
int
1070 58264
http_HdrIs(const struct http *hp, hdr_t hdr, const char *val)
1071
{
1072
        const char *p;
1073
1074 58264
        if (!http_GetHdr(hp, hdr, &p))
1075 55299
                return (0);
1076 2965
        AN(p);
1077 2965
        if (http_tok_eq(p, val))
1078 2835
                return (1);
1079 130
        return (0);
1080 58264
}
1081
1082
/*--------------------------------------------------------------------*/
1083
1084
uint16_t
1085 72841
http_GetStatus(const struct http *hp)
1086
{
1087
1088 72841
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1089 72841
        return (hp->status);
1090
}
1091
1092
int
1093 50511
http_IsStatus(const struct http *hp, int val)
1094
{
1095
1096 50511
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1097 50511
        assert(val >= 100 && val <= 999);
1098 50511
        return (val == (hp->status % 1000));
1099
}
1100
1101
/*--------------------------------------------------------------------
1102
 * Setting the status will also set the Reason appropriately
1103
 */
1104
1105
void
1106 5720
http_SetStatus(struct http *to, uint16_t status, const char *reason)
1107
{
1108
        char buf[4];
1109 5720
        const char *sstr = NULL;
1110
1111 5720
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1112
        /*
1113
         * We allow people to use top digits for internal VCL
1114
         * signalling, but strip them from the ASCII version.
1115
         */
1116 5720
        to->status = status;
1117 5720
        status %= 1000;
1118 5720
        assert(status >= 100);
1119
1120 5720
        if (reason == NULL)
1121 1165
                reason = http_Status2Reason(status, &sstr);
1122
        else
1123 4555
                (void)http_Status2Reason(status, &sstr);
1124
1125 5720
        if (sstr) {
1126 5540
                http_SetH(to, HTTP_HDR_STATUS, sstr);
1127 5540
        } else {
1128 180
                bprintf(buf, "%03d", status);
1129 180
                http_PutField(to, HTTP_HDR_STATUS, buf);
1130
        }
1131 5720
        http_SetH(to, HTTP_HDR_REASON, reason);
1132 5720
}
1133
1134
/*--------------------------------------------------------------------*/
1135
1136
const char *
1137 26598
http_GetMethod(const struct http *hp)
1138
{
1139
1140 26598
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1141 26598
        Tcheck(hp->hd[HTTP_HDR_METHOD]);
1142 26598
        return (hp->hd[HTTP_HDR_METHOD].b);
1143
}
1144
1145
/*--------------------------------------------------------------------
1146
 * Force a particular header field to a particular value
1147
 */
1148
1149
void
1150 39086
http_ForceField(struct http *to, unsigned n, const char *t)
1151
{
1152
        int i;
1153
1154 39086
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1155 39086
        assert(n < HTTP_HDR_FIRST);
1156 39086
        assert(n == HTTP_HDR_METHOD || n == HTTP_HDR_PROTO);
1157 39086
        AN(t);
1158
1159
        /* NB: method names and protocol versions are case-sensitive. */
1160 39086
        if (to->hd[n].b == NULL || strcmp(to->hd[n].b, t)) {
1161 600
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
1162 600
                i += to->logtag;
1163
                /* XXX: this is a dead branch */
1164 600
                if (n >= HTTP_HDR_FIRST)
1165 0
                        VSLbt(to->vsl, (enum VSL_tag_e)i, to->hd[n]);
1166 600
                http_SetH(to, n, t);
1167 600
        }
1168 39086
}
1169
1170
/*--------------------------------------------------------------------*/
1171
1172
void
1173 5220
http_PutResponse(struct http *to, const char *proto, uint16_t status,
1174
    const char *reason)
1175
{
1176
1177 5220
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1178 5220
        if (proto != NULL)
1179 5220
                http_SetH(to, HTTP_HDR_PROTO, proto);
1180 5220
        http_SetStatus(to, status, reason);
1181 5220
}
1182
1183
/*--------------------------------------------------------------------
1184
 * check if header is filtered by the dynamic marker or the static
1185
 * definitions in http_headers.h
1186
 */
1187
1188
static inline int
1189 201756
http_isfiltered(const struct http *fm, unsigned u, unsigned how)
1190
{
1191
        const char *e;
1192
        const struct http_hdrflg *f;
1193
1194 201756
        if (fm->hdf[u] & HDF_FILTER)
1195 85
                return (1);
1196 201671
        if (u < HTTP_HDR_FIRST)
1197 67589
                return (0);
1198 134082
        e = strchr(fm->hd[u].b, ':');
1199 134082
        if (e == NULL)
1200 0
                return (0);
1201 134082
        f = http_hdr_flags(fm->hd[u].b, e);
1202 134082
        return (f != NULL && f->flag & how);
1203 201756
}
1204
1205
int
1206 4196
http_IsFiltered(const struct http *fm, unsigned u, unsigned how)
1207
{
1208
1209 4196
        return (http_isfiltered(fm, u, how));
1210
}
1211
1212
/*--------------------------------------------------------------------
1213
 * Estimate how much workspace we need to Filter this header according
1214
 * to 'how'.
1215
 */
1216
1217
unsigned
1218 11283
http_EstimateWS(const struct http *fm, unsigned how)
1219
{
1220
        unsigned u, l;
1221
1222 11283
        l = 4;
1223 11283
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1224 107961
        for (u = 0; u < fm->nhd; u++) {
1225 96678
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1226 22566
                        continue;
1227 74112
                Tcheck(fm->hd[u]);
1228 74112
                if (http_isfiltered(fm, u, how))
1229 1317
                        continue;
1230 72795
                l += Tlen(fm->hd[u]) + 1L;
1231 72795
        }
1232 11283
        return (PRNDUP(l + 1L));
1233
}
1234
1235
/*--------------------------------------------------------------------
1236
 * Encode http struct as byte string.
1237
 *
1238
 * XXX: We could save considerable special-casing below by encoding also
1239
 * XXX: H__Status, H__Reason and H__Proto into the string, but it would
1240
 * XXX: add 26-30 bytes to all encoded objects to save a little code.
1241
 * XXX: It could possibly be a good idea for later HTTP versions.
1242
 */
1243
1244
void
1245 11255
HTTP_Encode(const struct http *fm, uint8_t *p0, unsigned l, unsigned how)
1246
{
1247
        unsigned u, w;
1248
        uint16_t n;
1249
        uint8_t *p, *e;
1250
1251 11255
        AN(p0);
1252 11255
        AN(l);
1253 11255
        p = p0;
1254 11255
        e = p + l;
1255 11255
        assert(p + 5 <= e);
1256 11255
        assert(fm->nhd <= fm->shd);
1257 11255
        n = HTTP_HDR_FIRST - 3;
1258 11255
        vbe16enc(p + 2, fm->status);
1259 11255
        p += 4;
1260 11255
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1261 107660
        for (u = 0; u < fm->nhd; u++) {
1262 96405
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1263 22510
                        continue;
1264 73895
                Tcheck(fm->hd[u]);
1265 73895
                if (http_isfiltered(fm, u, how))
1266 1317
                        continue;
1267 72578
                http_VSLH(fm, u);
1268 72578
                w = Tlen(fm->hd[u]) + 1L;
1269 72578
                assert(p + w + 1 <= e);
1270 72578
                memcpy(p, fm->hd[u].b, w);
1271 72578
                p += w;
1272 72578
                n++;
1273 72578
        }
1274 11255
        *p++ = '\0';
1275 11255
        assert(p <= e);
1276 11255
        vbe16enc(p0, n + 1);
1277 11255
}
1278
1279
/*--------------------------------------------------------------------
1280
 * Decode byte string into http struct
1281
 */
1282
1283
int
1284 16566
HTTP_Decode(struct http *to, const uint8_t *fm)
1285
{
1286
1287 16566
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1288 16566
        AN(to->vsl);
1289 16566
        AN(fm);
1290 16566
        if (vbe16dec(fm) <= to->shd) {
1291 16559
                to->status = vbe16dec(fm + 2);
1292 16559
                fm += 4;
1293 157065
                for (to->nhd = 0; to->nhd < to->shd; to->nhd++) {
1294 157065
                        if (to->nhd == HTTP_HDR_METHOD ||
1295 140487
                            to->nhd == HTTP_HDR_URL) {
1296 33114
                                to->hd[to->nhd].b = NULL;
1297 33114
                                to->hd[to->nhd].e = NULL;
1298 33114
                                continue;
1299
                        }
1300 123951
                        if (*fm == '\0')
1301 16559
                                return (0);
1302 107392
                        to->hd[to->nhd].b = (const void*)fm;
1303 107392
                        fm = (const void*)strchr((const void*)fm, '\0');
1304 107392
                        to->hd[to->nhd].e = (const void*)fm;
1305 107392
                        fm++;
1306 107392
                        http_VSLH(to, to->nhd);
1307 107392
                }
1308 0
        }
1309 14
        VSLb(to->vsl, SLT_Error,
1310
            "Too many headers to Decode object (%u vs. %u)",
1311 7
            vbe16dec(fm), to->shd);
1312 7
        return (-1);
1313 16566
}
1314
1315
/*--------------------------------------------------------------------*/
1316
1317
uint16_t
1318 165
HTTP_GetStatusPack(struct worker *wrk, struct objcore *oc)
1319
{
1320
        const char *ptr;
1321 165
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1322 165
        AN(ptr);
1323
1324 165
        return (vbe16dec(ptr + 2));
1325
}
1326
1327
/*--------------------------------------------------------------------*/
1328
1329
/* Get the first packed header */
1330
int
1331 4575
HTTP_IterHdrPack(struct worker *wrk, struct objcore *oc, const char **p)
1332
{
1333
        const char *ptr;
1334
1335 4575
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1336 4575
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1337 4575
        AN(p);
1338
1339 4575
        if (*p == NULL) {
1340 1400
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1341 1400
                AN(ptr);
1342 1400
                ptr += 4;       /* Skip nhd and status */
1343 1400
                ptr = strchr(ptr, '\0') + 1;    /* Skip :proto: */
1344 1400
                ptr = strchr(ptr, '\0') + 1;    /* Skip :status: */
1345 1400
                ptr = strchr(ptr, '\0') + 1;    /* Skip :reason: */
1346 1400
                *p = ptr;
1347 1400
        } else {
1348 3175
                *p = strchr(*p, '\0') + 1;      /* Skip to next header */
1349
        }
1350 4575
        if (**p == '\0')
1351 297
                return (0);
1352 4278
        return (1);
1353 4575
}
1354
1355
const char *
1356 1489
HTTP_GetHdrPack(struct worker *wrk, struct objcore *oc, hdr_t hdr)
1357
{
1358
        const char *ptr;
1359
1360 1489
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1361 1489
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1362 1489
        CHECK_HDR(hdr);
1363
1364 1489
        if (hdr->str[0] == ':') {
1365
                /* Special cases */
1366 90
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1367 90
                AN(ptr);
1368 90
                ptr += 4;       /* Skip nhd and status */
1369
1370
                /* XXX: should we also have h2_hdr_eq() ? */
1371 90
                if (!strcmp(hdr->str, ":proto:"))
1372 10
                        return (ptr);
1373 80
                ptr = strchr(ptr, '\0') + 1;
1374 80
                if (!strcmp(hdr->str, ":status:"))
1375 70
                        return (ptr);
1376 10
                ptr = strchr(ptr, '\0') + 1;
1377 10
                if (!strcmp(hdr->str, ":reason:"))
1378 10
                        return (ptr);
1379 0
                WRONG("Unknown magic packed header");
1380 0
        }
1381
1382 4574
        HTTP_FOREACH_PACK(wrk, oc, ptr) {
1383 4277
                if (http_hdr_at(ptr, hdr->str, hdr->len)) {
1384 1102
                        ptr += hdr->len;
1385 2199
                        while (vct_islws(*ptr))
1386 1097
                                ptr++;
1387 1102
                        return (ptr);
1388
                }
1389
        }
1390
1391 297
        return (NULL);
1392 1489
}
1393
1394
/*--------------------------------------------------------------------
1395
 * Merge any headers in the oc->OA_HEADER into the struct http if they
1396
 * are not there already.
1397
 */
1398
1399
void
1400 155
HTTP_Merge(struct worker *wrk, struct objcore *oc, struct http *to)
1401
{
1402
        const char *ptr;
1403
        unsigned u;
1404
        const char *p;
1405
        unsigned nhd_before_merge;
1406
1407 155
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1408 155
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1409 155
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1410
1411 155
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1412 155
        AN(ptr);
1413
1414 155
        to->status = vbe16dec(ptr + 2);
1415 155
        ptr += 4;
1416
1417 930
        for (u = 0; u < HTTP_HDR_FIRST; u++) {
1418 775
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1419 310
                        continue;
1420 465
                http_SetH(to, u, ptr);
1421 465
                ptr = strchr(ptr, '\0') + 1;
1422 465
        }
1423 155
        nhd_before_merge = to->nhd;
1424 925
        while (*ptr != '\0') {
1425 770
                p = strchr(ptr, ':');
1426 770
                AN(p);
1427 770
                u = http_findhdr(to, p - ptr, ptr);
1428 770
                if (u == 0 || u >= nhd_before_merge)
1429 365
                        http_SetHeader(to, ptr);
1430 770
                ptr = strchr(ptr, '\0') + 1;
1431
        }
1432 155
}
1433
1434
/*--------------------------------------------------------------------*/
1435
1436
static void
1437 34648
http_linkh(const struct http *to, const struct http *fm, unsigned n)
1438
{
1439
1440 34648
        assert(n < HTTP_HDR_FIRST);
1441 34648
        Tcheck(fm->hd[n]);
1442 34648
        to->hd[n] = fm->hd[n];
1443 34648
        to->hdf[n] = fm->hdf[n];
1444 34648
        http_VSLH(to, n);
1445 34648
}
1446
1447
/*--------------------------------------------------------------------*/
1448
1449
void
1450 11550
http_FilterReq(struct http *to, const struct http *fm, unsigned how)
1451
{
1452
        unsigned u;
1453
1454 11550
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1455 11550
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1456
1457 11550
        http_linkh(to, fm, HTTP_HDR_METHOD);
1458 11550
        http_linkh(to, fm, HTTP_HDR_URL);
1459 11550
        http_linkh(to, fm, HTTP_HDR_PROTO);
1460 11550
        to->protover = fm->protover;
1461 11550
        to->status = fm->status;
1462
1463 11550
        to->nhd = HTTP_HDR_FIRST;
1464 61094
        for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
1465 49544
                Tcheck(fm->hd[u]);
1466 49544
                if (http_isfiltered(fm, u, how))
1467 575
                        continue;
1468 48969
                assert (to->nhd < to->shd);
1469 48969
                to->hd[to->nhd] = fm->hd[u];
1470 48969
                to->hdf[to->nhd] = 0;
1471 48969
                http_VSLH(to, to->nhd);
1472 48969
                to->nhd++;
1473 48969
        }
1474 11550
}
1475
1476
/*--------------------------------------------------------------------
1477
 * This function copies any header fields which reference foreign
1478
 * storage into our own WS.
1479
 */
1480
1481
void
1482 11400
http_CopyHome(const struct http *hp)
1483
{
1484
        unsigned u, l;
1485
        const char *p;
1486
1487 123953
        for (u = 0; u < hp->nhd; u++) {
1488 112553
                if (hp->hd[u].b == NULL) {
1489 22800
                        assert(u < HTTP_HDR_FIRST);
1490 22800
                        continue;
1491
                }
1492
1493 89753
                l = Tlen(hp->hd[u]);
1494 89753
                if (WS_Allocated(hp->ws, hp->hd[u].b, l))
1495 7250
                        continue;
1496
1497 82503
                p = WS_Copy(hp->ws, hp->hd[u].b, l + 1L);
1498 82503
                if (p == NULL) {
1499 0
                        http_fail(hp);
1500 0
                        VSLbs(hp->vsl, SLT_LostHeader, TOSTRAND(hp->hd[u].b));
1501 0
                        return;
1502
                }
1503 82503
                hp->hd[u].b = p;
1504 82503
                hp->hd[u].e = p + l;
1505 82503
        }
1506 11400
}
1507
1508
/*--------------------------------------------------------------------*/
1509
1510
void
1511 47688
http_SetHeader(struct http *to, const char *header)
1512
{
1513
1514 47688
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1515 47688
        if (to->nhd >= to->shd) {
1516 5
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(header));
1517 5
                http_fail(to);
1518 5
                return;
1519
        }
1520 47683
        http_SetH(to, to->nhd++, header);
1521 47688
}
1522
1523
/*--------------------------------------------------------------------*/
1524
1525
void
1526 21250
http_ForceHeader(struct http *to, hdr_t hdr, const char *val)
1527
{
1528
1529 21250
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1530 21250
        if (http_HdrIs(to, hdr, val))
1531 1930
                return;
1532 19320
        http_Unset(to, hdr);
1533 19320
        http_PrintfHeader(to, "%s %s", hdr->str, val);
1534 21250
}
1535
1536
void
1537 54273
http_AppendHeader(struct http *to, hdr_t hdr, const char *val)
1538
{
1539
        const char *old;
1540
1541 54273
        http_CollectHdr(to, hdr);
1542 54273
        if (http_GetHdr(to, hdr, &old)) {
1543 240
                http_Unset(to, hdr);
1544 240
                http_PrintfHeader(to, "%s %s, %s", hdr->str, old, val);
1545 240
        } else {
1546 54033
                http_PrintfHeader(to, "%s %s", hdr->str, val);
1547
        }
1548 54273
}
1549
1550
void
1551 127654
http_PrintfHeader(struct http *to, const char *fmt, ...)
1552
{
1553
        va_list ap, ap2;
1554
        struct vsb vsb[1];
1555
        size_t sz;
1556
        char *p;
1557
1558 127654
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1559
1560 127654
        va_start(ap, fmt);
1561 127654
        va_copy(ap2, ap);
1562
1563 127654
        WS_VSB_new(vsb, to->ws);
1564 127654
        VSB_vprintf(vsb, fmt, ap);
1565 127654
        p = WS_VSB_finish(vsb, to->ws, &sz);
1566
1567 127654
        if (p == NULL || to->nhd >= to->shd) {
1568 138
                http_fail(to);
1569 138
                VSLbv(to->vsl, SLT_LostHeader, fmt, ap2);
1570 138
        } else {
1571 127516
                http_SetH(to, to->nhd++, p);
1572
        }
1573 127654
        va_end(ap);
1574 127654
        va_end(ap2);
1575 127654
}
1576
1577
void
1578 5260
http_TimeHeader(struct http *to, const char *fmt, vtim_real now)
1579
{
1580
        char *p;
1581
1582 5260
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1583 5260
        if (to->nhd >= to->shd) {
1584 0
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1585 0
                http_fail(to);
1586 0
                return;
1587
        }
1588 5260
        p = WS_Alloc(to->ws, strlen(fmt) + VTIM_FORMAT_SIZE);
1589 5260
        if (p == NULL) {
1590 385
                http_fail(to);
1591 385
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1592 385
                return;
1593
        }
1594 4875
        strcpy(p, fmt);
1595 4875
        VTIM_format(now, strchr(p, '\0'));
1596 4875
        http_SetH(to, to->nhd++, p);
1597 5260
}
1598
1599
const char *
1600 35412
http_ViaHeader(void)
1601
{
1602
1603 35412
        return (via_hdr);
1604
}
1605
1606
/*--------------------------------------------------------------------*/
1607
1608
void
1609 116143
http_Unset(struct http *hp, hdr_t hdr)
1610
{
1611
        uint16_t u, v;
1612
1613 754762
        for (v = u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
1614 638619
                Tcheck(hp->hd[u]);
1615 638619
                if (http_IsHdr(&hp->hd[u], hdr)) {
1616 5190
                        http_VSLH_del(hp, u);
1617 5190
                        continue;
1618
                }
1619 633429
                if (v != u) {
1620 14802
                        memcpy(&hp->hd[v], &hp->hd[u], sizeof *hp->hd);
1621 14802
                        memcpy(&hp->hdf[v], &hp->hdf[u], sizeof *hp->hdf);
1622 14802
                }
1623 633429
                v++;
1624 633429
        }
1625 116143
        hp->nhd = v;
1626 116143
}