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 3057472
http_hdr_flags(const char *b, const char *e)
183
{
184
        unsigned u;
185
        struct http_hdrflg *retval;
186
187 3057472
        if (b == NULL || e == NULL)
188 176
                return (NULL);
189 3057348
        u = pdiff(b, e);
190 3057348
        if (u < GPERF_MIN_WORD_LENGTH || u > GPERF_MAX_WORD_LENGTH)
191 1400
                return (NULL);
192 6111896
        u += http_asso_values[(uint8_t)(e[-1])] +
193 3055948
             http_asso_values[(uint8_t)(b[0])];
194 3055948
        if (u > GPERF_MAX_HASH_VALUE)
195 41840
                return (NULL);
196 3014108
        retval = &http_hdrflg[u];
197 3014108
        if (retval->hdr == NULL)
198 11582
                return (NULL);
199 3002526
        AN(*retval->hdr);
200 3002526
        if (!http_hdr_at(*retval->hdr + 1, b, e - b))
201 42440
                return (NULL);
202 2960086
        return (retval);
203 3057348
}
204
205
/*--------------------------------------------------------------------*/
206
207
static void
208 1977560
http_init_hdr(hdr_t hdr, int flg)
209
{
210
        struct http_hdrflg *f;
211
212 1977560
        f = http_hdr_flags(hdr->str, hdr->str + hdr->len - 1);
213 1977560
        AN(f);
214 1977560
        assert(*f->hdr == hdr);
215 1977560
        f->flag = flg;
216 1977560
}
217
218
void
219 38030
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 38030
        AN(vsb);
228
        VSB_printf(vsb, "1.1 %s (Varnish/" PACKAGE_BRANCH ")",
229
            heritage.identity);
230 38030
        AZ(VSB_finish(vsb));
231 38030
        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 5065626
http_VSLH(const struct http *hp, unsigned hdr)
245
{
246
        int i;
247
248 5065626
        if (hp->vsl != NULL) {
249 5065537
                assert(VXID_TAG(hp->vsl->wid));
250 5065537
                i = hdr;
251 5065537
                if (i > HTTP_HDR_FIRST)
252 2667468
                        i = HTTP_HDR_FIRST;
253 5065537
                i += hp->logtag;
254 5065537
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
255 5065537
        }
256 5065792
}
257
258
static void
259 41520
http_VSLH_del(const struct http *hp, unsigned hdr)
260
{
261
        int i;
262
263 41520
        if (hp->vsl != NULL) {
264
                /* We don't support unsetting stuff in the first line */
265 41520
                assert (hdr >= HTTP_HDR_FIRST);
266 41520
                assert(VXID_TAG(hp->vsl->wid));
267 41520
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
268 41520
                i += hp->logtag;
269 41520
                VSLbt(hp->vsl, (enum VSL_tag_e)i, hp->hd[hdr]);
270 41520
        }
271 41520
}
272
273
/*--------------------------------------------------------------------*/
274
275
void
276 235630
http_VSL_log(const struct http *hp)
277
{
278
        unsigned u;
279
280 2058260
        for (u = 0; u < hp->nhd; u++)
281 3174112
                if (hp->hd[u].b != NULL)
282 1351482
                        http_VSLH(hp, u);
283 235630
}
284
285
/*--------------------------------------------------------------------*/
286
287
static void
288 4160
http_fail(const struct http *hp)
289
{
290
        char id[WS_ID_SIZE];
291
292 4160
        VSC_C_main->losthdr++;
293 4160
        WS_Id(hp->ws, id);
294 4160
        VSLb(hp->vsl, SLT_Error, "out of workspace (%s)", id);
295 4160
        WS_MarkOverflow(hp->ws);
296 4160
}
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 59792
http_Status2Reason(unsigned status, const char **sstr)
314
{
315
        struct http_msg *mp;
316
317 59792
        status %= 1000;
318 59792
        assert(status >= 100);
319 1822490
        for (mp = http_msg; mp->nbr != 0 && mp->nbr <= status; mp++)
320 1820690
                if (mp->nbr == status) {
321 57992
                        if (sstr)
322 44314
                                *sstr = mp->status;
323 57992
                        return (mp->txt);
324
                }
325 1800
        return ("Unknown HTTP Status");
326 59792
}
327
328
/*--------------------------------------------------------------------*/
329
330
unsigned
331 215063
HTTP_estimate(unsigned nhttp)
332
{
333
334
        /* XXX: We trust the structs to size-aligned as necessary */
335 215063
        return (PRNDUP(sizeof(struct http) + sizeof(txt) * nhttp + nhttp));
336
}
337
338
struct http *
339 645196
HTTP_create(void *p, uint16_t nhttp, unsigned len)
340
{
341
        struct http *hp;
342
343 645196
        hp = p;
344 645196
        hp->magic = HTTP_MAGIC;
345 645196
        hp->hd = (void*)(hp + 1);
346 645196
        hp->shd = nhttp;
347 645196
        hp->hdf = (void*)(hp->hd + nhttp);
348 645196
        assert((unsigned char*)p + len == hp->hdf + PRNDUP(nhttp));
349 645196
        return (hp);
350
}
351
352
/*--------------------------------------------------------------------*/
353
354
void
355 601701
HTTP_Setup(struct http *hp, struct ws *ws, struct vsl_log *vsl,
356
    enum VSL_tag_e  whence)
357
{
358 601701
        http_Teardown(hp);
359 601701
        hp->nhd = HTTP_HDR_FIRST;
360 601701
        hp->logtag = whence;
361 601701
        hp->ws = ws;
362 601701
        hp->vsl = vsl;
363 601701
}
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 939291
http_Teardown(struct http *hp)
373
{
374
375 939291
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
376 939291
        AN(hp->shd);
377 939291
        memset(&hp->nhd, 0, sizeof *hp - offsetof(struct http, nhd));
378 939291
        memset(hp->hd, 0, sizeof *hp->hd * hp->shd);
379 939291
        memset(hp->hdf, 0, sizeof *hp->hdf * hp->shd);
380 939291
}
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 264193
HTTP_Dup(struct http *to, const struct http * fm)
390
{
391
392 264193
        assert(fm->nhd <= to->shd);
393 264193
        memcpy(to->hd, fm->hd, fm->nhd * sizeof *to->hd);
394 264193
        memcpy(to->hdf, fm->hdf, fm->nhd * sizeof *to->hdf);
395 264193
        to->nhd = fm->nhd;
396 264193
        to->logtag = fm->logtag;
397 264193
        to->status = fm->status;
398 264193
        to->protover = fm->protover;
399 264193
}
400
401
402
/*--------------------------------------------------------------------
403
 * Clone the entire http structure, including vsl & ws
404
 */
405
406
void
407 249553
HTTP_Clone(struct http *to, const struct http * const fm)
408
{
409
410 249553
        HTTP_Dup(to, fm);
411 249553
        to->vsl = fm->vsl;
412 249553
        to->ws = fm->ws;
413 249553
}
414
415
/*--------------------------------------------------------------------*/
416
417
void
418 269633
http_Proto(struct http *to)
419
{
420
        const char *fm;
421
422 269633
        fm = to->hd[HTTP_HDR_PROTO].b;
423
424 538911
        if (fm != NULL &&
425 269315
            (fm[0] == 'H' || fm[0] == 'h') &&
426 269279
            (fm[1] == 'T' || fm[1] == 't') &&
427 269277
            (fm[2] == 'T' || fm[2] == 't') &&
428 269277
            (fm[3] == 'P' || fm[3] == 'p') &&
429 269277
            fm[4] == '/' &&
430 269277
            vct_isdigit(fm[5]) &&
431 269277
            fm[6] == '.' &&
432 269277
            vct_isdigit(fm[7]) &&
433 269278
            fm[8] == '\0') {
434 269277
                to->protover = 10 * (fm[5] - '0') + (fm[7] - '0');
435 269277
        } else {
436 360
                to->protover = 0;
437
        }
438 269637
}
439
440
/*--------------------------------------------------------------------*/
441
442
void
443 1606929
http_SetH(struct http *to, unsigned n, const char *header)
444
{
445
446 1606929
        assert(n < to->nhd);
447 1606929
        AN(header);
448 1606929
        to->hd[n].b = TRUST_ME(header);
449 1606929
        to->hd[n].e = strchr(to->hd[n].b, '\0');
450 1606929
        to->hdf[n] = 0;
451 1606929
        http_VSLH(to, n);
452 1606929
        if (n == HTTP_HDR_PROTO)
453 55159
                http_Proto(to);
454 1606929
}
455
456
/*--------------------------------------------------------------------*/
457
458
static void
459 1440
http_PutField(struct http *to, int field, const char *string)
460
{
461
        const char *p;
462
463 1440
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
464 1440
        p = WS_Copy(to->ws, string, -1);
465 1440
        if (p == NULL) {
466 40
                http_fail(to);
467 40
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(string));
468 40
                return;
469
        }
470 1400
        http_SetH(to, field, p);
471 1440
}
472
473
/*--------------------------------------------------------------------*/
474
475
int
476 5867103
http_IsHdr(const txt *hh, hdr_t hdr)
477
{
478
479 5867103
        Tcheck(*hh);
480 5867103
        CHECK_HDR(hdr);
481 5867103
        return (http_hdr_at(hdr->str, hh->b, hdr->len));
482
}
483
484
/*--------------------------------------------------------------------*/
485
486
static unsigned
487 6049267
http_findhdr(const struct http *hp, unsigned l, const char *hdr)
488
{
489
        unsigned u;
490
491 26276821
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
492 21568447
                Tcheck(hp->hd[u]);
493 21568447
                if (hp->hd[u].e < hp->hd[u].b + l + 1)
494 3891838
                        continue;
495 17676609
                if (hp->hd[u].b[l] != ':')
496 14861502
                        continue;
497 2815107
                if (!http_hdr_at(hdr, hp->hd[u].b, l))
498 1474214
                        continue;
499 1340893
                return (u);
500
        }
501 4708374
        return (0);
502 6049267
}
503
504
/*--------------------------------------------------------------------
505
 * Count how many instances we have of this header
506
 */
507
508
unsigned
509 305816
http_CountHdr(const struct http *hp, hdr_t hdr)
510
{
511 305816
        unsigned retval = 0;
512
        unsigned u;
513
514 305816
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
515
516 1019468
        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
517 713652
                Tcheck(hp->hd[u]);
518 713652
                if (http_IsHdr(&hp->hd[u], hdr))
519 151109
                        retval++;
520 713652
        }
521 305816
        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 983791
http_CollectHdr(struct http *hp, hdr_t hdr)
531
{
532
533 983791
        http_CollectHdrSep(hp, hdr, NULL);
534 983791
}
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 989835
http_CollectHdrSep(struct http *hp, hdr_t hdr, const char *sep)
544
{
545
        unsigned u, lsep, ml, f, x, d;
546 989835
        char *b = NULL, *e = NULL;
547
        const char *v;
548
549 989835
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
550 989835
        CHECK_HDR(hdr);
551
552 989835
        if (WS_Overflowed(hp->ws))
553 800
                return;
554
555 989035
        if (sep == NULL || *sep == '\0')
556 982985
                sep = ", ";
557 989043
        lsep = strlen(sep);
558
559 989043
        f = http_findhdr(hp, hdr->len - 1, hdr->str);
560 989043
        if (f == 0)
561 972461
                return;
562
563 61033
        for (d = u = f + 1; u < hp->nhd; u++) {
564 44451
                Tcheck(hp->hd[u]);
565 44451
                if (!http_IsHdr(&hp->hd[u], hdr)) {
566 43731
                        if (d != u) {
567 2840
                                hp->hd[d] = hp->hd[u];
568 2840
                                hp->hdf[d] = hp->hdf[u];
569 2840
                        }
570 43731
                        d++;
571 43731
                        continue;
572
                }
573 720
                if (b == NULL) {
574
                        /* Found second header, start our collection */
575 640
                        ml = WS_ReserveAll(hp->ws);
576 640
                        b = WS_Reservation(hp->ws);
577 640
                        e = b + ml;
578 640
                        x = Tlen(hp->hd[f]);
579 640
                        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 640
                        memcpy(b, hp->hd[f].b, x);
587 640
                        b += x;
588 640
                }
589
590 720
                AN(b);
591 720
                AN(e);
592
593
                /* Append the Nth header we found */
594 720
                x = Tlen(hp->hd[u]) - hdr->len;
595
596 720
                v = hp->hd[u].b + hdr->len;
597 1440
                while (vct_issp(*v)) {
598 720
                        v++;
599 720
                        x--;
600
                }
601
602 720
                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 720
                memcpy(b, sep, lsep);
609 720
                b += lsep;
610 720
                memcpy(b, v, x);
611 720
                b += x;
612 720
        }
613 16582
        if (b == NULL)
614 15942
                return;
615 640
        hp->nhd = (uint16_t)d;
616 640
        AN(e);
617 640
        *b = '\0';
618 640
        hp->hd[f].b = WS_Reservation(hp->ws);
619 640
        hp->hd[f].e = b;
620 640
        WS_ReleaseP(hp->ws, b + 1);
621 989843
}
622
623
/*--------------------------------------------------------------------*/
624
625
int
626 5054319
http_GetHdr(const struct http *hp, hdr_t hdr, const char **ptr)
627
{
628
        unsigned u;
629
        const char *p;
630
631 5054319
        CHECK_HDR(hdr);
632 5054319
        u = http_findhdr(hp, hdr->len - 1, hdr->str);
633 5054319
        if (u == 0) {
634 3733301
                if (ptr != NULL)
635 3431683
                        *ptr = NULL;
636 3733301
                return (0);
637
        }
638 1321018
        if (ptr != NULL) {
639 1081040
                p = hp->hd[u].b + hdr->len;
640 2160302
                while (vct_issp(*p))
641 1079262
                        p++;
642 1081040
                *ptr = p;
643 1081040
        }
644 1321018
        return (1);
645 5054319
}
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 99367
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 99367
        AN(src);
661 99367
        AN(*src);
662 99367
        AN(sep);
663 99367
        AN(b);
664 99367
        AN(e);
665
666 99367
        if (stop == NULL)
667 99084
                stop = strchr(*src, '\0');
668
669 170228
        for (p = *src; p < stop && (vct_issp(*p) || strchr(sep, *p)); p++)
670 3480
                continue;
671
672 99367
        if (p >= stop) {
673 35462
                *b = NULL;
674 35462
                *e = NULL;
675 35462
                return (0);
676
        }
677
678 63905
        *b = p;
679 63905
        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 311072
        for (q = p + 1; q < stop && !strchr(sep, *q); q++)
687 247167
                continue;
688 63905
        *src = q;
689 63905
        while (q > p && vct_issp(q[-1]))
690 0
                q--;
691 63901
        *e = q;
692 63901
        return (1);
693 99363
}
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 56399
http_istoken(const char **bp, const char *e, const char *token)
706
{
707 56399
        int fl = strlen(token);
708
        const char *b;
709
710 56399
        AN(bp);
711 56399
        AN(e);
712 56399
        AN(token);
713
714 56399
        b = *bp;
715
716 56399
        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 58039
        if (b + fl <= e && http_tok_at(b, token, fl) &&
722 26440
            (b + fl == e || !vct_istchar(b[fl]))) {
723 26440
                *bp += fl;
724 26440
                return (1);
725
        }
726 29959
        return (0);
727 56399
}
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 603402
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 603402
        if (pb != NULL)
756 455908
                *pb = NULL;
757 603402
        if (pe != NULL)
758 142497
                *pe = NULL;
759 603402
        if (!http_GetHdr(hp, hdr, &h))
760 548483
                return (0);
761 54919
        AN(h);
762
763 84877
        while (http_split(&h, NULL, ",", &b, &e))
764 56398
                if (http_istoken(&b, e, token))
765 26440
                        break;
766 54919
        if (b == NULL)
767 28479
                return (0);
768 26440
        if (pb != NULL) {
769 26280
                for (; vct_islws(*b); b++)
770 200
                        continue;
771 26080
                if (b == e) {
772 24480
                        b = NULL;
773 24480
                        e = NULL;
774 24480
                }
775 26080
                *pb = b;
776 26080
                if (pe != NULL)
777 24200
                        *pe = e;
778 26080
        }
779 26440
        return (1);
780 603402
}
781
782
/*--------------------------------------------------------------------
783
 * Find a given header field's quality value (qvalue).
784
 */
785
786
double
787 142494
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 142494
        i = http_GetHdrToken(hp, hdr, field, &hb, &he);
794 142494
        if (!i)
795 118295
                return (0.);
796
797 24199
        if (hb == NULL)
798 23919
                return (1.);
799 280
        while (http_split(&hb, he, ";", &b, &e)) {
800 280
                if (*b != 'q')
801 0
                        continue;
802 280
                for (b++; b < e && vct_issp(*b); b++)
803 0
                        continue;
804 280
                if (b == e || *b != '=')
805 0
                        continue;
806 280
                break;
807
        }
808 280
        if (b == NULL)
809 0
                return (1.);
810 280
        for (b++; b < e && vct_issp(*b); b++)
811 0
                continue;
812 280
        if (b == e || (*b != '.' && !vct_isdigit(*b)))
813 40
                return (0.);
814 240
        a = 0;
815 480
        while (b < e && vct_isdigit(*b)) {
816 240
                a *= 10.;
817 240
                a += *b - '0';
818 240
                b++;
819
        }
820 240
        if (b == e || *b++ != '.')
821 40
                return (a);
822 200
        f = .1;
823 640
        while (b < e && vct_isdigit(*b)) {
824 440
                a += f * (*b - '0');
825 440
                f *= .1;
826 440
                b++;
827
        }
828 200
        return (a);
829 142494
}
830
831
/*--------------------------------------------------------------------
832
 * Find a given header field's value.
833
 */
834
835
int
836 313444
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 313444
        if (ptr != NULL)
843 159557
                *ptr = NULL;
844
845 313444
        h = NULL;
846 313444
        i = http_GetHdrToken(hp, hdr, field, &h, NULL);
847 313444
        if (!i)
848 311564
                return (i);
849
850 1880
        if (ptr != NULL && h != NULL) {
851
                /* Skip whitespace, looking for '=' */
852 1320
                while (*h && vct_issp(*h))
853 0
                        h++;
854 1320
                if (*h == '=') {
855 1320
                        h++;
856 1480
                        while (*h && vct_issp(*h))
857 160
                                h++;
858 1320
                        *ptr = h;
859 1320
                }
860 1320
        }
861 1880
        return (i);
862 313444
}
863
864
/*--------------------------------------------------------------------*/
865
866
ssize_t
867 450576
http_GetContentLength(const struct http *hp)
868
{
869
        ssize_t cl;
870
        const char *b;
871
872 450576
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
873
874 450576
        if (!http_GetHdr(hp, H_Content_Length, &b))
875 176955
                return (-1);
876 273621
        cl = VNUM_uint(b, NULL, &b);
877 273621
        if (cl < 0)
878 160
                return (-2);
879 273461
        while (vct_islws(*b))
880 0
                b++;
881 273461
        if (*b != '\0')
882 0
                return (-2);
883 273461
        return (cl);
884 450576
}
885
886
ssize_t
887 80839
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 80839
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
893
894 80839
        if (lo == NULL)
895 0
                lo = &tmp;
896 80839
        if (hi == NULL)
897 0
                hi = &tmp;
898
899 80839
        *lo = *hi = -1;
900
901 80839
        if (!http_GetHdr(hp, H_Content_Range, &b))
902 80439
                return (-1);
903
904 400
        t = strchr(b, ' ');
905 400
        if (t == NULL)
906 40
                return (-2);            // Missing space after range unit
907
908 360
        if (!http_range_at(b, bytes, t - b))
909 40
                return (-1);            // Unknown range unit, ignore
910 320
        b = t + 1;
911
912 320
        if (*b == '*') {                // Content-Range: bytes */123
913 120
                *lo = *hi = -1;
914 120
                b++;
915 120
        } else {                        // Content-Range: bytes 1-2/3
916 200
                *lo = VNUM_uint(b, NULL, &b);
917 200
                if (*lo < 0)
918 0
                        return (-2);
919 200
                if (*b != '-')
920 0
                        return (-2);
921 200
                *hi = VNUM_uint(b + 1, NULL, &b);
922 200
                if (*hi < 0)
923 0
                        return (-2);
924
        }
925 320
        if (*b != '/')
926 0
                return (-2);
927 320
        if (b[1] == '*') {              // Content-Range: bytes 1-2/*
928 40
                cl = -1;
929 40
                b += 2;
930 40
        } else {
931 280
                cl = VNUM_uint(b + 1, NULL, &b);
932 280
                if (cl <= 0)
933 0
                        return (-2);
934
        }
935 320
        while (vct_islws(*b))
936 0
                b++;
937 320
        if (*b != '\0')
938 0
                return (-2);
939 320
        if (*lo > *hi)
940 0
                return (-2);
941 320
        assert(cl >= -1);
942 320
        if (*lo >= cl || *hi >= cl)
943 40
                return (-2);
944 280
        AN(cl);
945 280
        return (cl);
946 80839
}
947
948
const char *
949 82798
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 82798
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
955
956 82798
        if (lo == NULL)
957 0
                lo = &tmp_lo;
958 82798
        if (hi == NULL)
959 0
                hi = &tmp_hi;
960
961 82798
        *lo = *hi = -1;
962
963 82798
        if (!http_GetHdr(hp, H_Range, &b))
964 80598
                return (NULL);
965
966 2200
        t = strchr(b, '=');
967 2200
        if (t == NULL)
968 80
                return ("Missing '='");
969
970 2120
        if (!http_range_at(b, bytes, t - b))
971 120
                return ("Not Bytes");
972 2000
        b = t + 1;
973
974 2000
        *lo = VNUM_uint(b, NULL, &b);
975 2000
        if (*lo == -2)
976 0
                return ("Low number too big");
977 2000
        if (*b++ != '-')
978 0
                return ("Missing hyphen");
979
980 2000
        *hi = VNUM_uint(b, NULL, &b);
981 2000
        if (*hi == -2)
982 0
                return ("High number too big");
983 2000
        if (*lo == -1 && *hi == -1)
984 40
                return ("Neither high nor low");
985 1960
        if (*lo == -1 && *hi == 0)
986 40
                return ("No low, high is zero");
987 1920
        if (*hi >= 0 && *hi < *lo)
988 40
                return ("high smaller than low");
989
990 1920
        while (vct_islws(*b))
991 40
                b++;
992 1880
        if (*b != '\0')
993 40
                return ("Trailing stuff");
994
995 1840
        assert(*lo >= -1);
996 1840
        assert(*hi >= -1);
997
998 1840
        if (*lo < 0) {
999 160
                assert(*hi > 0);
1000 160
                *lo = len - *hi;
1001 160
                if (*lo < 0)
1002 80
                        *lo = 0;
1003 160
                *hi = len - 1;
1004 1840
        } else if (len >= 0 && (*hi >= len || *hi < 0)) {
1005 360
                *hi = len - 1;
1006 360
        }
1007
1008 1840
        if (len <= 0)
1009 720
                return (NULL);                  // Allow 200 response
1010
1011 1120
        if (*lo >= len)
1012 40
                return ("low range beyond object");
1013
1014 1080
        return (NULL);
1015 82798
}
1016
1017
/*--------------------------------------------------------------------
1018
 */
1019
1020
stream_close_t
1021 236851
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 236851
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1029 236851
        assert(sc_close == SC_REQ_CLOSE || sc_close == SC_RESP_CLOSE);
1030
1031 236851
        if (hp->protover == 10)
1032 1556
                retval = SC_REQ_HTTP10;
1033
        else
1034 235295
                retval = SC_NULL;
1035
1036 236851
        http_CollectHdr(hp, H_Connection);
1037 236851
        if (!http_GetHdr(hp, H_Connection, &h))
1038 229748
                return (retval);
1039 7103
        AN(h);
1040 14206
        while (http_split(&h, NULL, ",", &b, &e)) {
1041 7223
                u = pdiff(b, e);
1042 7223
                if (u == 5 && http_hdr_at(b, "close", u))
1043 5823
                        retval = sc_close;
1044 7223
                if (u == 10 && http_hdr_at(b, "keep-alive", u))
1045 920
                        retval = SC_NULL;
1046
1047
                /* Refuse removal of well-known-headers if they would pass. */
1048 7223
                f = http_hdr_flags(b, e);
1049 7223
                if (f != NULL && !(f->flag & HTTPH_R_PASS))
1050 120
                        return (SC_RX_BAD);
1051
1052 34427
                for (v = HTTP_HDR_FIRST; v < hp->nhd; v++) {
1053 27324
                        Tcheck(hp->hd[v]);
1054 27324
                        if (hp->hd[v].e < hp->hd[v].b + u + 1)
1055 1240
                                continue;
1056 26084
                        if (hp->hd[v].b[u] != ':')
1057 24084
                                continue;
1058 2000
                        if (!http_hdr_at(b, hp->hd[v].b, u))
1059 1520
                                continue;
1060 480
                        hp->hdf[v] |= HDF_FILTER;
1061 480
                }
1062
        }
1063 6983
        CHECK_OBJ_NOTNULL(retval, STREAM_CLOSE_MAGIC);
1064 6983
        return (retval);
1065 236851
}
1066
1067
/*--------------------------------------------------------------------*/
1068
1069
int
1070 465985
http_HdrIs(const struct http *hp, hdr_t hdr, const char *val)
1071
{
1072
        const char *p;
1073
1074 465985
        if (!http_GetHdr(hp, hdr, &p))
1075 442249
                return (0);
1076 23736
        AN(p);
1077 23736
        if (http_tok_eq(p, val))
1078 22696
                return (1);
1079 1040
        return (0);
1080 465985
}
1081
1082
/*--------------------------------------------------------------------*/
1083
1084
uint16_t
1085 582666
http_GetStatus(const struct http *hp)
1086
{
1087
1088 582666
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1089 582666
        return (hp->status);
1090
}
1091
1092
int
1093 404023
http_IsStatus(const struct http *hp, int val)
1094
{
1095
1096 404023
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1097 404023
        assert(val >= 100 && val <= 999);
1098 404023
        return (val == (hp->status % 1000));
1099
}
1100
1101
/*--------------------------------------------------------------------
1102
 * Setting the status will also set the Reason appropriately
1103
 */
1104
1105
void
1106 45756
http_SetStatus(struct http *to, uint16_t status, const char *reason)
1107
{
1108
        char buf[4];
1109 45756
        const char *sstr = NULL;
1110
1111 45756
        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 45756
        to->status = status;
1117 45756
        status %= 1000;
1118 45756
        assert(status >= 100);
1119
1120 45756
        if (reason == NULL)
1121 9320
                reason = http_Status2Reason(status, &sstr);
1122
        else
1123 36436
                (void)http_Status2Reason(status, &sstr);
1124
1125 45756
        if (sstr) {
1126 44316
                http_SetH(to, HTTP_HDR_STATUS, sstr);
1127 44316
        } else {
1128 1440
                bprintf(buf, "%03d", status);
1129 1440
                http_PutField(to, HTTP_HDR_STATUS, buf);
1130
        }
1131 45756
        http_SetH(to, HTTP_HDR_REASON, reason);
1132 45756
}
1133
1134
/*--------------------------------------------------------------------*/
1135
1136
const char *
1137 212758
http_GetMethod(const struct http *hp)
1138
{
1139
1140 212758
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
1141 212758
        Tcheck(hp->hd[HTTP_HDR_METHOD]);
1142 212758
        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 312674
http_ForceField(struct http *to, unsigned n, const char *t)
1151
{
1152
        int i;
1153
1154 312674
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1155 312674
        assert(n < HTTP_HDR_FIRST);
1156 312674
        assert(n == HTTP_HDR_METHOD || n == HTTP_HDR_PROTO);
1157 312674
        AN(t);
1158
1159
        /* NB: method names and protocol versions are case-sensitive. */
1160 312674
        if (to->hd[n].b == NULL || strcmp(to->hd[n].b, t)) {
1161 4800
                i = (HTTP_HDR_UNSET - HTTP_HDR_METHOD);
1162 4800
                i += to->logtag;
1163
                /* XXX: this is a dead branch */
1164 4800
                if (n >= HTTP_HDR_FIRST)
1165 0
                        VSLbt(to->vsl, (enum VSL_tag_e)i, to->hd[n]);
1166 4800
                http_SetH(to, n, t);
1167 4800
        }
1168 312682
}
1169
1170
/*--------------------------------------------------------------------*/
1171
1172
void
1173 41758
http_PutResponse(struct http *to, const char *proto, uint16_t status,
1174
    const char *reason)
1175
{
1176
1177 41758
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1178 41758
        if (proto != NULL)
1179 41758
                http_SetH(to, HTTP_HDR_PROTO, proto);
1180 41760
        http_SetStatus(to, status, reason);
1181 41760
}
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 1614069
http_isfiltered(const struct http *fm, unsigned u, unsigned how)
1190
{
1191
        const char *e;
1192
        const struct http_hdrflg *f;
1193
1194 1614069
        if (fm->hdf[u] & HDF_FILTER)
1195 680
                return (1);
1196 1613389
        if (u < HTTP_HDR_FIRST)
1197 540831
                return (0);
1198 1072558
        e = strchr(fm->hd[u].b, ':');
1199 1072558
        if (e == NULL)
1200 0
                return (0);
1201 1072558
        f = http_hdr_flags(fm->hd[u].b, e);
1202 1072558
        return (f != NULL && f->flag & how);
1203 1614069
}
1204
1205
int
1206 33582
http_IsFiltered(const struct http *fm, unsigned u, unsigned how)
1207
{
1208
1209 33582
        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 90273
http_EstimateWS(const struct http *fm, unsigned how)
1219
{
1220
        unsigned u, l;
1221
1222 90273
        l = 4;
1223 90273
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1224 863791
        for (u = 0; u < fm->nhd; u++) {
1225 773518
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1226 180550
                        continue;
1227 592968
                Tcheck(fm->hd[u]);
1228 592968
                if (http_isfiltered(fm, u, how))
1229 10524
                        continue;
1230 582444
                l += Tlen(fm->hd[u]) + 1L;
1231 582444
        }
1232 90273
        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 90032
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 90032
        AN(p0);
1252 90032
        AN(l);
1253 90032
        p = p0;
1254 90032
        e = p + l;
1255 90032
        assert(p + 5 <= e);
1256 90032
        assert(fm->nhd <= fm->shd);
1257 90032
        n = HTTP_HDR_FIRST - 3;
1258 90032
        vbe16enc(p + 2, fm->status);
1259 90032
        p += 4;
1260 90032
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1261 861252
        for (u = 0; u < fm->nhd; u++) {
1262 771220
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1263 180068
                        continue;
1264 591152
                Tcheck(fm->hd[u]);
1265 591152
                if (http_isfiltered(fm, u, how))
1266 10523
                        continue;
1267 580629
                http_VSLH(fm, u);
1268 580629
                w = Tlen(fm->hd[u]) + 1L;
1269 580629
                assert(p + w + 1 <= e);
1270 580629
                memcpy(p, fm->hd[u].b, w);
1271 580629
                p += w;
1272 580629
                n++;
1273 580629
        }
1274 90032
        *p++ = '\0';
1275 90032
        assert(p <= e);
1276 90032
        vbe16enc(p0, n + 1);
1277 90032
}
1278
1279
/*--------------------------------------------------------------------
1280
 * Decode byte string into http struct
1281
 */
1282
1283
int
1284 132524
HTTP_Decode(struct http *to, const uint8_t *fm)
1285
{
1286
1287 132524
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1288 132524
        AN(to->vsl);
1289 132524
        AN(fm);
1290 132524
        if (vbe16dec(fm) <= to->shd) {
1291 132446
                to->status = vbe16dec(fm + 2);
1292 132446
                fm += 4;
1293 1256327
                for (to->nhd = 0; to->nhd < to->shd; to->nhd++) {
1294 1256327
                        if (to->nhd == HTTP_HDR_METHOD ||
1295 1123698
                            to->nhd == HTTP_HDR_URL) {
1296 264878
                                to->hd[to->nhd].b = NULL;
1297 264878
                                to->hd[to->nhd].e = NULL;
1298 264878
                                continue;
1299
                        }
1300 991449
                        if (*fm == '\0')
1301 132446
                                return (0);
1302 859003
                        to->hd[to->nhd].b = (const void*)fm;
1303 859003
                        fm = (const void*)strchr((const void*)fm, '\0');
1304 859003
                        to->hd[to->nhd].e = (const void*)fm;
1305 859003
                        fm++;
1306 859003
                        http_VSLH(to, to->nhd);
1307 859003
                }
1308 0
        }
1309 156
        VSLb(to->vsl, SLT_Error,
1310
            "Too many headers to Decode object (%u vs. %u)",
1311 78
            vbe16dec(fm), to->shd);
1312 78
        return (-1);
1313 132524
}
1314
1315
/*--------------------------------------------------------------------*/
1316
1317
uint16_t
1318 1320
HTTP_GetStatusPack(struct worker *wrk, struct objcore *oc)
1319
{
1320
        const char *ptr;
1321 1320
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1322 1320
        AN(ptr);
1323
1324 1320
        return (vbe16dec(ptr + 2));
1325
}
1326
1327
/*--------------------------------------------------------------------*/
1328
1329
/* Get the first packed header */
1330
int
1331 36124
HTTP_IterHdrPack(struct worker *wrk, struct objcore *oc, const char **p)
1332
{
1333
        const char *ptr;
1334
1335 36124
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1336 36124
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1337 36124
        AN(p);
1338
1339 36124
        if (*p == NULL) {
1340 11099
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1341 11099
                AN(ptr);
1342 11099
                ptr += 4;       /* Skip nhd and status */
1343 11099
                ptr = strchr(ptr, '\0') + 1;    /* Skip :proto: */
1344 11099
                ptr = strchr(ptr, '\0') + 1;    /* Skip :status: */
1345 11099
                ptr = strchr(ptr, '\0') + 1;    /* Skip :reason: */
1346 11099
                *p = ptr;
1347 11099
        } else {
1348 25025
                *p = strchr(*p, '\0') + 1;      /* Skip to next header */
1349
        }
1350 36124
        if (**p == '\0')
1351 2334
                return (0);
1352 33790
        return (1);
1353 36124
}
1354
1355
const char *
1356 11817
HTTP_GetHdrPack(struct worker *wrk, struct objcore *oc, hdr_t hdr)
1357
{
1358
        const char *ptr;
1359
1360 11817
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1361 11817
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1362 11817
        CHECK_HDR(hdr);
1363
1364 11817
        if (hdr->str[0] == ':') {
1365
                /* Special cases */
1366 720
                ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1367 720
                AN(ptr);
1368 720
                ptr += 4;       /* Skip nhd and status */
1369
1370
                /* XXX: should we also have h2_hdr_eq() ? */
1371 720
                if (!strcmp(hdr->str, ":proto:"))
1372 80
                        return (ptr);
1373 640
                ptr = strchr(ptr, '\0') + 1;
1374 640
                if (!strcmp(hdr->str, ":status:"))
1375 560
                        return (ptr);
1376 80
                ptr = strchr(ptr, '\0') + 1;
1377 80
                if (!strcmp(hdr->str, ":reason:"))
1378 80
                        return (ptr);
1379 0
                WRONG("Unknown magic packed header");
1380 0
        }
1381
1382 36121
        HTTP_FOREACH_PACK(wrk, oc, ptr) {
1383 33787
                if (http_hdr_at(ptr, hdr->str, hdr->len)) {
1384 8763
                        ptr += hdr->len;
1385 17485
                        while (vct_islws(*ptr))
1386 8722
                                ptr++;
1387 8763
                        return (ptr);
1388
                }
1389
        }
1390
1391 2334
        return (NULL);
1392 11817
}
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 1240
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 1240
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1408 1240
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1409 1240
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1410
1411 1240
        ptr = ObjGetAttr(wrk, oc, OA_HEADERS, NULL);
1412 1240
        AN(ptr);
1413
1414 1240
        to->status = vbe16dec(ptr + 2);
1415 1240
        ptr += 4;
1416
1417 7440
        for (u = 0; u < HTTP_HDR_FIRST; u++) {
1418 6200
                if (u == HTTP_HDR_METHOD || u == HTTP_HDR_URL)
1419 2480
                        continue;
1420 3720
                http_SetH(to, u, ptr);
1421 3720
                ptr = strchr(ptr, '\0') + 1;
1422 3720
        }
1423 1240
        nhd_before_merge = to->nhd;
1424 7400
        while (*ptr != '\0') {
1425 6160
                p = strchr(ptr, ':');
1426 6160
                AN(p);
1427 6160
                u = http_findhdr(to, p - ptr, ptr);
1428 6160
                if (u == 0 || u >= nhd_before_merge)
1429 2920
                        http_SetHeader(to, ptr);
1430 6160
                ptr = strchr(ptr, '\0') + 1;
1431
        }
1432 1240
}
1433
1434
/*--------------------------------------------------------------------*/
1435
1436
static void
1437 277187
http_linkh(const struct http *to, const struct http *fm, unsigned n)
1438
{
1439
1440 277187
        assert(n < HTTP_HDR_FIRST);
1441 277187
        Tcheck(fm->hd[n]);
1442 277187
        to->hd[n] = fm->hd[n];
1443 277187
        to->hdf[n] = fm->hdf[n];
1444 277187
        http_VSLH(to, n);
1445 277187
}
1446
1447
/*--------------------------------------------------------------------*/
1448
1449
void
1450 92397
http_FilterReq(struct http *to, const struct http *fm, unsigned how)
1451
{
1452
        unsigned u;
1453
1454 92397
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1455 92397
        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
1456
1457 92397
        http_linkh(to, fm, HTTP_HDR_METHOD);
1458 92397
        http_linkh(to, fm, HTTP_HDR_URL);
1459 92397
        http_linkh(to, fm, HTTP_HDR_PROTO);
1460 92397
        to->protover = fm->protover;
1461 92397
        to->status = fm->status;
1462
1463 92397
        to->nhd = HTTP_HDR_FIRST;
1464 488775
        for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
1465 396378
                Tcheck(fm->hd[u]);
1466 396378
                if (http_isfiltered(fm, u, how))
1467 4600
                        continue;
1468 391778
                assert (to->nhd < to->shd);
1469 391778
                to->hd[to->nhd] = fm->hd[u];
1470 391778
                to->hdf[to->nhd] = 0;
1471 391778
                http_VSLH(to, to->nhd);
1472 391778
                to->nhd++;
1473 391778
        }
1474 92397
}
1475
1476
/*--------------------------------------------------------------------
1477
 * This function copies any header fields which reference foreign
1478
 * storage into our own WS.
1479
 */
1480
1481
void
1482 91190
http_CopyHome(const struct http *hp)
1483
{
1484
        unsigned u, l;
1485
        const char *p;
1486
1487 991598
        for (u = 0; u < hp->nhd; u++) {
1488 900408
                if (hp->hd[u].b == NULL) {
1489 182385
                        assert(u < HTTP_HDR_FIRST);
1490 182385
                        continue;
1491
                }
1492
1493 718023
                l = Tlen(hp->hd[u]);
1494 718023
                if (WS_Allocated(hp->ws, hp->hd[u].b, l))
1495 57984
                        continue;
1496
1497 660039
                p = WS_Copy(hp->ws, hp->hd[u].b, l + 1L);
1498 660039
                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 660039
                hp->hd[u].b = p;
1504 660039
                hp->hd[u].e = p + l;
1505 660039
        }
1506 91190
}
1507
1508
/*--------------------------------------------------------------------*/
1509
1510
void
1511 381451
http_SetHeader(struct http *to, const char *header)
1512
{
1513
1514 381451
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1515 381451
        if (to->nhd >= to->shd) {
1516 40
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(header));
1517 40
                http_fail(to);
1518 40
                return;
1519
        }
1520 381411
        http_SetH(to, to->nhd++, header);
1521 381451
}
1522
1523
/*--------------------------------------------------------------------*/
1524
1525
void
1526 169969
http_ForceHeader(struct http *to, hdr_t hdr, const char *val)
1527
{
1528
1529 169969
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1530 169969
        if (http_HdrIs(to, hdr, val))
1531 15456
                return;
1532 154513
        http_Unset(to, hdr);
1533 154513
        http_PrintfHeader(to, "%s %s", hdr->str, val);
1534 169969
}
1535
1536
void
1537 434088
http_AppendHeader(struct http *to, hdr_t hdr, const char *val)
1538
{
1539
        const char *old;
1540
1541 434088
        http_CollectHdr(to, hdr);
1542 434088
        if (http_GetHdr(to, hdr, &old)) {
1543 1920
                http_Unset(to, hdr);
1544 1920
                http_PrintfHeader(to, "%s %s, %s", hdr->str, old, val);
1545 1920
        } else {
1546 432168
                http_PrintfHeader(to, "%s %s", hdr->str, val);
1547
        }
1548 434088
}
1549
1550
void
1551 1021084
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 1021084
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1559
1560 1021084
        va_start(ap, fmt);
1561 1021084
        va_copy(ap2, ap);
1562
1563 1021084
        WS_VSB_new(vsb, to->ws);
1564 1021084
        VSB_vprintf(vsb, fmt, ap);
1565 1021084
        p = WS_VSB_finish(vsb, to->ws, &sz);
1566
1567 1021084
        if (p == NULL || to->nhd >= to->shd) {
1568 1133
                http_fail(to);
1569 1133
                VSLbv(to->vsl, SLT_LostHeader, fmt, ap2);
1570 1133
        } else {
1571 1019985
                http_SetH(to, to->nhd++, p);
1572
        }
1573 1021118
        va_end(ap);
1574 1021118
        va_end(ap2);
1575 1021118
}
1576
1577
void
1578 42079
http_TimeHeader(struct http *to, const char *fmt, vtim_real now)
1579
{
1580
        char *p;
1581
1582 42079
        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
1583 42079
        if (to->nhd >= to->shd) {
1584 0
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1585 0
                http_fail(to);
1586 0
                return;
1587
        }
1588 42079
        p = WS_Alloc(to->ws, strlen(fmt) + VTIM_FORMAT_SIZE);
1589 42079
        if (p == NULL) {
1590 3080
                http_fail(to);
1591 3080
                VSLbs(to->vsl, SLT_LostHeader, TOSTRAND(fmt));
1592 3080
                return;
1593
        }
1594 38999
        strcpy(p, fmt);
1595 38999
        VTIM_format(now, strchr(p, '\0'));
1596 38999
        http_SetH(to, to->nhd++, p);
1597 42079
}
1598
1599
const char *
1600 283267
http_ViaHeader(void)
1601
{
1602
1603 283267
        return (via_hdr);
1604
}
1605
1606
/*--------------------------------------------------------------------*/
1607
1608
void
1609 929174
http_Unset(struct http *hp, hdr_t hdr)
1610
{
1611
        uint16_t u, v;
1612
1613 6038014
        for (v = u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
1614 5108840
                Tcheck(hp->hd[u]);
1615 5108840
                if (http_IsHdr(&hp->hd[u], hdr)) {
1616 41520
                        http_VSLH_del(hp, u);
1617 41520
                        continue;
1618
                }
1619 5067320
                if (v != u) {
1620 118432
                        memcpy(&hp->hd[v], &hp->hd[u], sizeof *hp->hd);
1621 118432
                        memcpy(&hp->hdf[v], &hp->hdf[u], sizeof *hp->hdf);
1622 118432
                }
1623 5067320
                v++;
1624 5067320
        }
1625 929174
        hp->nhd = v;
1626 929174
}