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