vinyl-cache/bin/vinyld/cache/cache_vrt.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 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
 * Runtime support for compiled VCL programs
31
 */
32
33
#include "config.h"
34
35
#include <stdlib.h>
36
37
#include "cache_int.h"
38
39
#include "cache_objhead.h"
40
#include "vav.h"
41
#include "vcl.h"
42
#include "vct.h"
43
#include "venc.h"
44
#include "vend.h"
45
#include "vrt_obj.h"
46
#include "vsa.h"
47
#include "vsha256.h"
48
#include "vtcp.h"
49
#include "vtim.h"
50
#include "vcc_interface.h"
51
52
#include "common/heritage.h"
53
#include "common/vsmw.h"
54
#include "proxy/cache_proxy.h"
55
56
// NOT using TOSTRANDS() to create a NULL pointer element despite n == 0
57
const struct strands *const vrt_null_strands = &(struct strands){
58
        .magic = STRANDS_MAGIC,
59
        .n = 0,
60
        .p = (const char *[1]){NULL}
61
};
62
const struct vrt_blob *const vrt_null_blob = &(struct vrt_blob){
63
        .magic = VRT_BLOB_MAGIC,
64
        .type = VRT_NULL_BLOB_TYPE,
65
        .len = 0,
66
        .blob = "\0"
67
};
68
69
/*--------------------------------------------------------------------*/
70
71
VCL_VOID
72 1572
VRT_synth(VRT_CTX, VCL_INT code, VCL_STRING reason)
73
{
74
        const char *ret;
75
76 1572
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
77 1572
        assert(ctx->req != NULL || ctx->bo != NULL);
78
79 1572
        ret = ctx->req == NULL ? "error" : "synth";
80 1572
        if (code < 0) {
81 0
                VRT_fail(ctx, "return(%s()) status code (%jd) is negative",
82 0
                    ret, (intmax_t)code);
83 0
                return;
84
        }
85 1572
        if (code > 65535) {
86 0
                VRT_fail(ctx, "return(%s()) status code (%jd) > 65535",
87 0
                    ret, (intmax_t)code);
88 0
                return;
89
        }
90 1572
        if ((code % 1000) < 100) {
91 32
                VRT_fail(ctx,
92
                    "illegal return(%s()) status code (%jd) (..0##)",
93 16
                    ret, (intmax_t)code);
94 16
                return;
95
        }
96
97 1556
        if (ctx->req == NULL) {
98 76
                CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
99 76
                ctx->bo->err_code = (uint16_t)code;
100 76
                ctx->bo->err_reason = reason ? reason
101 40
                    : http_Status2Reason(ctx->bo->err_code % 1000, NULL);
102 76
                return;
103
        }
104
105 1480
        ctx->req->err_code = (uint16_t)code;
106 1480
        ctx->req->err_reason = reason ? reason
107 1080
            : http_Status2Reason(ctx->req->err_code % 1000, NULL);
108 1572
}
109
110
/*--------------------------------------------------------------------*/
111
112
void
113 468
VPI_acl_log(VRT_CTX, const char *msg)
114
{
115
116 468
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
117 468
        AN(msg);
118 468
        if (ctx->vsl != NULL)
119 468
                VSLbs(ctx->vsl, SLT_VCL_acl, TOSTRAND(msg));
120
        else
121 0
                VSL(SLT_VCL_acl, NO_VXID, "%s", msg);
122 468
}
123
124
int
125 385984
VRT_acl_match(VRT_CTX, VCL_ACL acl, VCL_IP ip)
126
{
127
128 385984
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
129 385984
        if (acl == NULL || ip == NULL) {
130 24
                VRT_fail(ctx, "Cannot match a null %s",
131 12
                         acl == NULL ? "ACL" : "IP address");
132 12
                return (0);
133
        }
134 385972
        CHECK_OBJ(acl, VRT_ACL_MAGIC);
135 385972
        assert(VSA_Sane(ip));
136 385972
        return (acl->match(ctx, ip));
137 385984
}
138
139
static int
140 832
acl_tbl_cmp(int fam, const uint8_t *key, const uint8_t *b)
141
{
142
        int rv;
143
144 832
        rv = fam - (int)b[3];
145 832
        if (rv == 0 && b[1] > 0)
146 576
                rv = memcmp(key, b + 4, b[1]);
147 832
        if (rv == 0 && b[2])
148 472
                rv = (int)(key[b[1]] & b[2]) - (int)b[4 + b[1]];
149 832
        return (rv);
150
}
151
152
static const uint8_t *
153 384
bbsearch(int fam, const uint8_t *key, const uint8_t *base0,
154
    size_t nmemb, size_t size)
155
{
156 384
        const uint8_t *base = base0;
157
        size_t lim;
158
        int cmp;
159
        const uint8_t *p;
160
161 1104
        for (lim = nmemb; lim != 0; lim >>= 1) {
162 832
                p = base + (lim >> 1) * size;
163 832
                cmp = acl_tbl_cmp(fam, key, p);
164 832
                if (cmp == 0)
165 112
                        return (p);
166 720
                if (cmp > 0) {
167
                        /* key > p: move right */
168 304
                        base = p + size;
169 304
                        lim--;
170 304
                } /* else move left */
171 720
        }
172 272
        return (NULL);
173 384
}
174
175
int
176 384
VPI_acl_table(VRT_CTX, VCL_IP p, unsigned n, unsigned m, const uint8_t *tbl,
177
    const char * const *str, const char *fin)
178
{
179
        int fam;
180
        const uint8_t *key;
181
        const uint8_t *ptr;
182
        size_t sz;
183
184 384
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
185 384
        AN(p);
186 384
        AN(n);
187 384
        assert(m == 20);
188 384
        AN(tbl);
189 384
        AN(fin);
190
191 384
        fam = VRT_VSA_GetPtr(ctx, p, &key);
192 384
        ptr = bbsearch(fam, key, tbl, n, m);
193
194 384
        if (ptr != NULL) {
195 112
                sz = ptr - tbl;
196 112
                AZ(sz % m);
197 112
                sz /= m;
198 112
                if (str != NULL)
199 56
                        VPI_acl_log(ctx, str[sz]);
200 112
                return (*ptr);
201
        }
202 272
        if (str != NULL)
203 136
                VPI_acl_log(ctx, fin);
204 272
        return (0);
205 384
}
206
207
/*--------------------------------------------------------------------*/
208
209
VCL_VOID
210 120
VRT_hit_for_pass(VRT_CTX, VCL_DURATION d)
211
{
212
        struct objcore *oc;
213
214 120
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
215 120
        if (ctx->bo == NULL) {
216 0
                VSLb(ctx->vsl, SLT_Error,
217
                    "Note: Ignoring DURATION argument to return(pass);");
218 0
                return;
219
        }
220 120
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
221 120
        oc = ctx->bo->fetch_objcore;
222 120
        oc->ttl = d;
223 120
        oc->grace = 0.0;
224 120
        oc->keep = 0.0;
225 240
        VSLb(ctx->vsl, SLT_TTL, "HFP %.0f %.0f %.0f %.0f uncacheable",
226 120
            oc->ttl, oc->grace, oc->keep, oc->t_origin);
227 120
}
228
229
/*--------------------------------------------------------------------*/
230
231
VCL_HTTP
232 137264
VRT_selecthttp(VRT_CTX, enum gethdr_e where)
233
{
234
        VCL_HTTP hp;
235
236 137264
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
237 137264
        switch (where) {
238
        case HDR_REQ:
239 82336
                hp = ctx->http_req;
240 82336
                break;
241
        case HDR_REQ_TOP:
242 28
                hp = ctx->http_req_top;
243 28
                break;
244
        case HDR_BEREQ:
245 2472
                hp = ctx->http_bereq;
246 2472
                break;
247
        case HDR_BERESP:
248 38072
                hp = ctx->http_beresp;
249 38072
                break;
250
        case HDR_RESP:
251 14352
                hp = ctx->http_resp;
252 14352
                break;
253
        case HDR_OBJ_STALE:
254
        case HDR_OBJ:
255 4
                hp = NULL;
256 4
                break;
257
        default:
258 0
                WRONG("VRT_selecthttp 'where' invalid");
259 0
        }
260 137264
        return (hp);
261
}
262
263
/*--------------------------------------------------------------------*/
264
265
VCL_STRING
266 108063
VRT_GetHdr(VRT_CTX, VCL_HEADER hs)
267
{
268
        VCL_HTTP hp;
269
        const char *p;
270
271 108063
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
272 108063
        if (hs->where == HDR_OBJ) {
273 57
                CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
274 57
                CHECK_OBJ_NOTNULL(ctx->req->objcore, OBJCORE_MAGIC);
275 114
                return (HTTP_GetHdrPack(ctx->req->wrk, ctx->req->objcore,
276 57
                    hs->what));
277
        }
278
279 108006
        if (hs->where == HDR_OBJ_STALE) {
280 4
                CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
281 4
                CHECK_OBJ_NOTNULL(ctx->bo->stale_oc, OBJCORE_MAGIC);
282 8
                return (HTTP_GetHdrPack(ctx->bo->wrk, ctx->bo->stale_oc,
283 4
                    hs->what));
284
        }
285 108002
        hp = VRT_selecthttp(ctx, hs->where);
286 108002
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
287 108002
        if (!http_GetHdr(hp, hs->what, &p))
288 50001
                return (NULL);
289 58001
        return (p);
290 108063
}
291
292
/*--------------------------------------------------------------------
293
 * Alloc Strands with space for n elements on workspace
294
 *
295
 * Error handling is deliberately left to the caller
296
 */
297
298
struct strands *
299 0
VRT_AllocStrandsWS(struct ws *ws, int n)
300
{
301
        struct strands *s;
302
        const char **p;
303
304 0
        s = WS_Alloc(ws, sizeof *s);
305 0
        p = WS_Alloc(ws, n * sizeof *p);
306
307 0
        if (s == NULL || p == NULL)
308 0
                return (NULL);
309
310 0
        s->magic = STRANDS_MAGIC;
311 0
        s->n = n;
312 0
        s->p = p;
313
314 0
        return (s);
315 0
}
316
317
/*--------------------------------------------------------------------
318
 * Compare two STRANDS
319
 */
320
321
int
322 744
VRT_CompareStrands(VCL_STRANDS a, VCL_STRANDS b)
323
{
324 744
        const char *pa = NULL, *pb = NULL;
325 744
        int na = 0, nb = 0;
326
327 744
        CHECK_OBJ_NOTNULL(a, STRANDS_MAGIC);
328 744
        CHECK_OBJ_NOTNULL(b, STRANDS_MAGIC);
329
330 5056
        while (1) {
331 5056
                if (pa != NULL && *pa == '\0')
332 444
                        pa = NULL;
333 5056
                if (pb != NULL && *pb == '\0')
334 596
                        pb = NULL;
335 5056
                if (pa == NULL && na < a->n)
336 1012
                        pa = a->p[na++];
337 4044
                else if (pb == NULL && nb < b->n)
338 1188
                        pb = b->p[nb++];
339 2856
                else if (pa == NULL && pb == NULL)
340 252
                        return (0);
341 2604
                else if (pa == NULL)
342 176
                        return (-1);
343 2428
                else if (pb == NULL)
344 48
                        return (1);
345 2380
                else if (*pa == '\0')
346 0
                        pa = NULL;
347 2380
                else if (*pb == '\0')
348 0
                        pb = NULL;
349 2380
                else if (*pa != *pb)
350 268
                        return (*pa - *pb);
351
                else {
352 2112
                        pa++;
353 2112
                        pb++;
354
                }
355
        }
356 744
}
357
358
/*--------------------------------------------------------------------
359
 * STRANDS to BOOL
360
 */
361
362
VCL_BOOL
363 58524
VRT_Strands2Bool(VCL_STRANDS s)
364
{
365
        int i;
366
367 58524
        CHECK_OBJ_NOTNULL(s, STRANDS_MAGIC);
368 91489
        for (i = 0; i < s->n; i++)
369 58522
                if (s->p[i] != NULL)
370 25557
                        return (1);
371 32967
        return (0);
372 58524
}
373
374
/*--------------------------------------------------------------------
375
 * Hash a STRANDS
376
 */
377
378
uint32_t
379 6904
VRT_HashStrands32(VCL_STRANDS s)
380
{
381
        struct VSHA256Context sha_ctx;
382
        unsigned char sha256[VSHA256_LEN];
383
        const char *p;
384
        int i;
385
386 6904
        CHECK_OBJ_NOTNULL(s, STRANDS_MAGIC);
387 6904
        VSHA256_Init(&sha_ctx);
388 20552
        for (i = 0; i < s->n; i++) {
389 13648
                p = s->p[i];
390 13648
                if (p != NULL && *p != '\0')
391 13632
                        VSHA256_Update(&sha_ctx, p, vstrlen(p));
392 13648
        }
393 6904
        VSHA256_Final(sha256, &sha_ctx);
394
395
        /* NB: for some reason vmod_director's shard director specifically
396
         * relied on little-endian decoding of the last 4 octets. In order
397
         * to maintain a stable hash function to share across consumers we
398
         * need to stick to that.
399
         */
400 6904
        return (vle32dec(sha256 + VSHA256_LEN - 4));
401
}
402
403
404
/*--------------------------------------------------------------------
405
 * Collapse STRANDS into the space provided, or return NULL
406
 */
407
408
char *
409 20255
VRT_Strands(char *d, size_t dl, VCL_STRANDS s)
410
{
411
        char *b;
412
        const char *e;
413
        unsigned x;
414
415 20255
        AN(d);
416 20255
        CHECK_OBJ_NOTNULL(s, STRANDS_MAGIC);
417 20255
        b = d;
418 20255
        e = b + dl;
419 40678
        for (int i = 0; i < s->n; i++)
420 40203
                if (s->p[i] != NULL && *s->p[i] != '\0') {
421 19780
                        x = vstrlen(s->p[i]);
422 19780
                        if (b + x >= e)
423 224
                                return (NULL);
424 19556
                        memcpy(b, s->p[i], x);
425 19556
                        b += x;
426 19556
                }
427 20031
        assert(b < e);
428 20031
        *b++ = '\0';
429 20031
        return (b);
430 20255
}
431
432
/*--------------------------------------------------------------------
433
 * Copy and merge STRANDS into a workspace.
434
 */
435
436
VCL_STRING
437 2096
VRT_StrandsWS(struct ws *ws, const char *h, VCL_STRANDS s)
438
{
439 2096
        const char *q = NULL;
440
        struct vsb vsb[1];
441
        int i;
442
443 2096
        WS_Assert(ws);
444 2096
        CHECK_OBJ_NOTNULL(s, STRANDS_MAGIC);
445
446 2204
        for (i = 0; i < s->n; i++) {
447 2168
                if (s->p[i] != NULL && *s->p[i] != '\0') {
448 2060
                        q = s->p[i];
449 2060
                        break;
450
                }
451 108
        }
452
453 2096
        if (q == NULL && h == NULL)
454 32
                return ("");
455 2064
        if (q == NULL)
456 4
                return (h);
457 2060
        if (h == NULL) {
458 900
                for (i++; i < s->n; i++)
459 348
                        if (s->p[i] != NULL && *s->p[i] != '\0')
460 308
                                break;
461 860
                if (i == s->n)
462 552
                        return (q);
463 308
        }
464
465 1508
        WS_VSB_new(vsb, ws);
466 1508
        if (h != NULL)
467 1200
                VSB_cat(vsb, h);
468 3540
        for (i = 0; i < s->n; i++) {
469 2032
                if (s->p[i] != NULL && *s->p[i] != '\0')
470 1896
                        VSB_cat(vsb, s->p[i]);
471 2032
        }
472 1508
        return (WS_VSB_finish(vsb, ws, NULL));
473 2096
}
474
475
/*--------------------------------------------------------------------
476
 * Copy and merge STRANDS on the current workspace
477
 */
478
479
VCL_STRING
480 308
VRT_STRANDS_string(VRT_CTX, VCL_STRANDS s)
481
{
482
        const char *b;
483
484 308
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
485 308
        CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
486 308
        b = VRT_StrandsWS(ctx->ws, NULL, s);
487 308
        if (b == NULL)
488 4
                VRT_fail(ctx, "Workspace overflow");
489 308
        return (b);
490
}
491
492
/*--------------------------------------------------------------------
493
 * upper/lower-case STRANDS (onto workspace)
494
 */
495
496
#include <stdio.h>
497
498
VCL_STRING
499 44
VRT_UpperLowerStrands(VRT_CTX, VCL_STRANDS s, int up)
500
{
501
        unsigned u;
502
        char *b, *e, *r;
503 44
        const char *p, *q = NULL;
504 44
        int i, copy = 0, op = 0;
505
506 44
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
507 44
        CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
508 44
        CHECK_OBJ_NOTNULL(s, STRANDS_MAGIC);
509 44
        u = WS_ReserveAll(ctx->ws);
510 44
        r = b = WS_Reservation(ctx->ws);
511 44
        e = b + u;
512 104
        for (i = 0; i < s->n; i++) {
513 60
                if (s->p[i] == NULL || s->p[i][0] == '\0')
514 0
                        continue;
515 60
                if (q != NULL)
516 16
                        copy = 1;
517 336
                for(p = q = s->p[i]; *p != '\0'; p++) {
518 276
                        op = up ? vct_islower(*p) : vct_isupper(*p);
519
520 276
                        if (op)
521 136
                                copy = 1;
522
523 276
                        if (!copy && b == e)
524 0
                                continue;
525 276
                        else if (b == e)
526 0
                                break;
527
528 276
                        if (op)
529 136
                                *b++ = *p ^ 0x20;
530
                        else
531 140
                                *b++ = *p;
532 276
                }
533 60
                if (copy && b == e) {
534 0
                        WS_Release(ctx->ws, 0);
535 0
                        VRT_fail(ctx, "Workspace overflow");
536 0
                        return (NULL);
537
                }
538 60
        }
539 44
        assert(b <= e);
540 44
        if (!copy) {
541 12
                WS_Release(ctx->ws, 0);
542 12
                return (q);
543
        }
544 32
        assert(b < e);
545 32
        *b++ = '\0';
546 32
        assert(b <= e);
547 32
        WS_ReleaseP(ctx->ws, b);
548 32
        return (r);
549 44
}
550
551
552
// rfc9110,l,1585,1589
553
//     field-content  = field-vchar
554
//                      [ 1*( SP / HTAB / field-vchar ) field-vchar ]
555
//     field-vchar    = VCHAR / obs-text
556
//     obs-text       = %x80-FF
557
//
558
// This implementation is less strict, see #4221
559
static inline VCL_BOOL
560 20036
validhdr(const char *p)
561
{
562 20036
        AN(p);
563 770561
        for(;*p != '\0'; p++)
564 750533
                if (! vct_ishdrval(*p))
565 8
                        return (0);
566 20028
        return (1);
567 20036
}
568
569
/*--------------------------------------------------------------------*/
570
VCL_BOOL
571 8
VRT_ValidHdr(VRT_CTX, VCL_STRANDS s)
572
{
573
        int i;
574
575 8
        (void) ctx;
576
577 8
        CHECK_OBJ_NOTNULL(s, STRANDS_MAGIC);
578 12
        for (i = 0; i < s->n; i++) {
579 8
                if (s->p[i] == NULL || s->p[i][0] == '\0')
580 0
                        continue;
581 8
                if (! validhdr(s->p[i]))
582 4
                        return (0);
583 4
        }
584
585 4
        return (1);
586 8
}
587
/*--------------------------------------------------------------------*/
588
589
VCL_VOID
590 8396
VRT_UnsetHdr(VRT_CTX, VCL_HEADER hs)
591
{
592
        VCL_HTTP hp;
593
594 8396
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
595 8396
        AN(hs);
596 8396
        AN(hs->what);
597 8396
        hp = VRT_selecthttp(ctx, hs->where);
598 8396
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
599 8396
        http_Unset(hp, hs->what);
600 8396
}
601
602
VCL_VOID
603 20771
VRT_SetHdr(VRT_CTX, VCL_HEADER hs, const char *pfx, VCL_STRANDS s)
604
{
605
        VCL_HTTP hp;
606
        unsigned u, l, pl;
607
        char *p, *b;
608
609 20771
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
610 20771
        AN(hs);
611 20771
        AN(hs->what);
612 20771
        hp = VRT_selecthttp(ctx, hs->where);
613 20771
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
614
615 20771
        u = WS_ReserveAll(hp->ws);
616 20771
        pl = (pfx == NULL) ? 0 : vstrlen(pfx);
617 20771
        l = hs->what->len + 1 + pl;
618 20771
        if (u <= l) {
619 508
                WS_Release(hp->ws, 0);
620 508
                WS_MarkOverflow(hp->ws);
621 508
                VSLbs(ctx->vsl, SLT_LostHeader, TOSTRAND(hs->what->str));
622 508
                return;
623
        }
624 20263
        b = WS_Reservation(hp->ws);
625 20263
        if (s != NULL) {
626 20231
                p = VRT_Strands(b + l, u - l, s);
627 20231
                if (p == NULL) {
628 224
                        WS_Release(hp->ws, 0);
629 224
                        WS_MarkOverflow(hp->ws);
630 448
                        VSLbs(ctx->vsl, SLT_LostHeader,
631 224
                            TOSTRAND(hs->what->str));
632 224
                        return;
633
                }
634 20007
        } else {
635 32
                b[l] = '\0';
636
        }
637 20039
        p = b;
638 20039
        memcpy(p, hs->what->str, hs->what->len);
639 20039
        p += hs->what->len;
640 20039
        *p++ = ' ';
641 20039
        if (pfx != NULL)
642 40
                memcpy(p, pfx, pl);
643 20039
        p += pl;
644 20039
        if (FEATURE(FEATURE_VALIDATE_HEADERS) && !validhdr(b)) {
645 4
                VRT_fail(ctx, "Bad header %s", b);
646 4
                WS_Release(hp->ws, 0);
647 4
                return;
648
        }
649 20035
        WS_ReleaseP(hp->ws, strchr(p, '\0') + 1);
650 20035
        http_Unset(hp, hs->what);
651 20035
        http_SetHeader(hp, b);
652 20771
}
653
654
/*--------------------------------------------------------------------*/
655
656
VCL_VOID
657 85307
VRT_handling(VRT_CTX, unsigned hand)
658
{
659
660 85307
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
661 85307
        assert(hand != VCL_RET_FAIL);
662 85307
        AN(ctx->vpi);
663 85307
        AZ(ctx->vpi->handling);
664 85307
        assert(hand > 0);
665 85307
        assert(hand < VCL_RET_MAX);
666 85307
        ctx->vpi->handling = hand;
667 85307
}
668
669
unsigned
670 64
VRT_handled(VRT_CTX)
671
{
672 64
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
673 64
        AN(ctx->vpi);
674 64
        return (ctx->vpi->handling);
675
}
676
677
/* the trace value is cached in the VPI for efficiency */
678
VCL_VOID
679 4
VRT_trace(VRT_CTX, VCL_BOOL a)
680
{
681 4
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
682 4
        AN(ctx->vpi);
683 4
        ctx->vpi->trace = a;
684 4
}
685
686
/*--------------------------------------------------------------------*/
687
688
VCL_VOID
689 820
VRT_fail(VRT_CTX, const char *fmt, ...)
690
{
691
        va_list ap;
692
693 820
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
694 820
        assert(ctx->vsl != NULL || ctx->msg != NULL);
695 820
        AN(ctx->vpi);
696 820
        if (ctx->vpi->handling == VCL_RET_FAIL)
697 12
                return;
698 808
        AZ(ctx->vpi->handling);
699 808
        AN(fmt);
700 808
        AZ(strchr(fmt, '\n'));
701 808
        va_start(ap, fmt);
702 808
        if (ctx->vsl != NULL) {
703 644
                VSLbv(ctx->vsl, SLT_VCL_Error, fmt, ap);
704 644
        } else {
705 164
                AN(ctx->msg);
706 164
                VSB_vprintf(ctx->msg, fmt, ap);
707 164
                VSB_putc(ctx->msg, '\n');
708
        }
709 808
        va_end(ap);
710 808
        ctx->vpi->handling = VCL_RET_FAIL;
711 820
}
712
713
/*--------------------------------------------------------------------
714
 * Feed data into the hash calculation
715
 */
716
717
VCL_VOID
718 30533
VRT_hashdata(VRT_CTX, VCL_STRANDS s)
719
{
720
        int i;
721
722 30533
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
723 30533
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
724 30533
        AN(ctx->specific);
725 30533
        CHECK_OBJ_NOTNULL(s, STRANDS_MAGIC);
726 61079
        for (i = 0; i < s->n; i++)
727 30546
                HSH_AddString(ctx->req, ctx->specific, s->p[i]);
728
        /*
729
         * Add a 'field-separator' to make it more difficult to
730
         * manipulate the hash.
731
         */
732 30533
        HSH_AddString(ctx->req, ctx->specific, NULL);
733 30533
}
734
735
/*--------------------------------------------------------------------*/
736
737
VCL_TIME
738 652
VRT_r_now(VRT_CTX)
739
{
740 652
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
741 652
        return (ctx->now);
742
}
743
744
/*--------------------------------------------------------------------*/
745
746
VCL_STRING v_matchproto_()
747 1005
VRT_IP_string(VRT_CTX, VCL_IP ip)
748
{
749
        char buf[VTCP_ADDRBUFSIZE];
750
751 1005
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
752 1005
        if (ip == NULL) {
753 0
                VRT_fail(ctx, "%s: Illegal IP", __func__);
754 0
                return (NULL);
755
        }
756 1005
        VTCP_name(ip, buf, sizeof buf, NULL, 0);
757 1005
        return (WS_Copy(ctx->ws, buf, -1));
758 1005
}
759
760
int
761 11643
VRT_INT_is_valid(VCL_INT arg)
762
{
763 11643
        return (arg >= VRT_INTEGER_MIN && arg <= VRT_INTEGER_MAX);
764
}
765
766
767
VCL_STRING v_matchproto_()
768 11643
VRT_INT_string(VRT_CTX, VCL_INT num)
769
{
770
771 11643
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
772 11643
        if (!VRT_INT_is_valid(num))
773 8
                VRT_fail(ctx, "INT overflow converting to string (0x%jx)",
774 4
                    (intmax_t)num);
775 11643
        return (WS_Printf(ctx->ws, "%jd", (intmax_t)num));
776
}
777
778
int
779 968
VRT_REAL_is_valid(VCL_REAL arg)
780
{
781 968
        return (!isnan(arg) && arg >= VRT_DECIMAL_MIN && arg <= VRT_DECIMAL_MAX);
782
}
783
784
VCL_STRING v_matchproto_()
785 968
VRT_REAL_string(VRT_CTX, VCL_REAL num)
786
{
787
788 968
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
789 968
        if (!VRT_REAL_is_valid(num))
790 4
                VRT_fail(ctx, "REAL overflow converting to string (%e)", num);
791 968
        return (WS_Printf(ctx->ws, "%.3f", num));
792
}
793
794
VCL_STRING v_matchproto_()
795 324
VRT_TIME_string(VRT_CTX, VCL_TIME t)
796
{
797
        char *p;
798
799 324
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
800 324
        p = WS_Alloc(ctx->ws, VTIM_FORMAT_SIZE);
801 324
        if (p == NULL) {
802 0
                VRT_fail(ctx, "Workspace overflow");
803 0
                return (NULL);
804
        }
805 324
        VTIM_format(t, p);
806 324
        if (*p == '\0') {
807 4
                VRT_fail(ctx, "Unformattable VCL_TIME");
808 4
                return (NULL);
809
        }
810 320
        return (p);
811 324
}
812
813
VCL_STRING v_matchproto_()
814 19062
VRT_BACKEND_string(VCL_BACKEND d)
815
{
816 19062
        if (d == NULL)
817 0
                return (NULL);
818 19062
        CHECK_OBJ(d, DIRECTOR_MAGIC);
819 19062
        return (d->vcl_name);
820 19062
}
821
822
VCL_STRING v_matchproto_()
823 8
VRT_PROBE_string(VCL_PROBE p)
824
{
825 8
        if (p == NULL)
826 0
                return (NULL);
827 8
        CHECK_OBJ(p, VRT_BACKEND_PROBE_MAGIC);
828 8
        return (p->vcl_name);
829 8
}
830
831
VCL_STRING v_matchproto_()
832 2588
VRT_BOOL_string(VCL_BOOL val)
833
{
834
835 2588
        return (val ? "true" : "false");
836
}
837
838
VCL_STRING v_matchproto_()
839 68
VRT_BLOB_string(VRT_CTX, VCL_BLOB val)
840
{
841
        struct vsb vsb[1];
842
        const char *s;
843
844 68
        if (val == NULL)
845 0
                return (NULL);
846 68
        WS_VSB_new(vsb, ctx->ws);
847 68
        VSB_putc(vsb, ':');
848 68
        VENC_Encode_Base64(vsb, val->blob, val->len);
849 68
        VSB_putc(vsb, ':');
850 68
        s = WS_VSB_finish(vsb, ctx->ws, NULL);
851 68
        return (s);
852 68
}
853
854
/*--------------------------------------------------------------------*/
855
856
VCL_VOID
857 92
VRT_Rollback(VRT_CTX, VCL_HTTP hp)
858
{
859
860 92
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
861 92
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
862 92
        if (ctx->method & VCL_MET_PIPE) {
863 0
                VRT_fail(ctx, "Cannot rollback in vcl_pipe {}");
864 0
                return;
865
        }
866 92
        if (hp == ctx->http_req) {
867 56
                CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
868 56
                Req_Rollback(ctx);
869 56
                if (ctx->method & VCL_MET_DELIVER)
870 36
                        XXXAZ(Resp_Setup_Deliver(ctx->req));
871 56
                if (ctx->method & VCL_MET_SYNTH)
872 8
                        Resp_Setup_Synth(ctx->req);
873 92
        } else if (hp == ctx->http_bereq) {
874 36
                Bereq_Rollback(ctx);
875 36
        } else
876 0
                WRONG("VRT_Rollback 'hp' invalid");
877 92
}
878
879
/*--------------------------------------------------------------------*/
880
881
static VCL_STRING
882 84
vrt_ban_error(VRT_CTX, VCL_STRING err)
883
{
884 84
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
885 84
        AN(ctx->vsl);
886 84
        AN(err);
887
888 84
        VSLb(ctx->vsl, SLT_VCL_Error, "ban(): %s", err);
889 84
        return (err);
890
}
891
892
VCL_STRING
893 156
VRT_ban_string(VRT_CTX, VCL_STRING str)
894
{
895
        char *a1, *a2, *a3;
896
        char **av;
897
        struct ban_proto *bp;
898 156
        const char *err = NULL, *berr = NULL;
899
        int i;
900
901 156
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
902
903 156
        if (str == NULL)
904 8
                return (vrt_ban_error(ctx, "Null argument"));
905
906 148
        bp = BAN_Build();
907 148
        if (bp == NULL)
908 0
                return (vrt_ban_error(ctx, "Out of Memory"));
909
910 148
        av = VAV_Parse(str, NULL, ARGV_NOESC);
911 148
        AN(av);
912 148
        if (av[0] != NULL) {
913 0
                err = av[0];
914 0
                VAV_Free(av);
915 0
                BAN_Abandon(bp);
916 0
                return (vrt_ban_error(ctx, err));
917
        }
918 168
        for (i = 0; ;) {
919 168
                a1 = av[++i];
920 168
                if (a1 == NULL) {
921 8
                        err = "No ban conditions found.";
922 8
                        break;
923
                }
924 160
                a2 = av[++i];
925 160
                if (a2 == NULL) {
926 8
                        err = "Expected comparison operator.";
927 8
                        break;
928
                }
929 152
                a3 = av[++i];
930 152
                if (a3 == NULL) {
931 8
                        err = "Expected second operand.";
932 8
                        break;
933
                }
934 144
                berr = BAN_AddTest(bp, a1, a2, a3);
935 144
                if (berr != NULL)
936 44
                        break;
937
938 100
                if (av[++i] == NULL) {
939 72
                        berr = BAN_Commit(bp);
940 72
                        if (berr == NULL)
941 72
                                bp = NULL;
942 72
                        break;
943
                }
944 28
                if (vstrcmp(av[i], "&&")) {
945 16
                        err = WS_Printf(ctx->ws, "Expected && between "
946 8
                            "conditions, found \"%s\"", av[i]);
947 8
                        if (err == NULL)
948 0
                                err = "Expected && between conditions "
949
                                    "(workspace overflow)";
950 8
                        break;
951
                }
952
        }
953 148
        if (berr != NULL) {
954 44
                AZ(err);
955 44
                err = WS_Copy(ctx->ws, berr, -1);
956 44
                if (err == NULL)
957 0
                        err = "Unknown error (workspace overflow)";
958 44
                berr = NULL;
959 44
        }
960 148
        AZ(berr);
961 148
        if (bp != NULL)
962 76
                BAN_Abandon(bp);
963 148
        VAV_Free(av);
964 148
        if (err == NULL)
965 72
                return (NULL);
966 76
        return (vrt_ban_error(ctx, err));
967 156
}
968
969
VCL_BYTES
970 168
VRT_CacheReqBody(VRT_CTX, VCL_BYTES maxsize)
971
{
972 168
        const char * const err = "req.body can only be cached in vcl_recv{}";
973
974 168
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
975 168
        if (ctx->method != VCL_MET_RECV) {
976 0
                if (ctx->vsl != NULL) {
977 0
                        VSLbs(ctx->vsl, SLT_VCL_Error, TOSTRAND(err));
978 0
                } else {
979 0
                        AN(ctx->msg);
980 0
                        VSB_printf(ctx->msg, "%s\n", err);
981
                };
982 0
                return (-1);
983
        }
984 168
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
985 168
        return (VRB_Cache(ctx->req, maxsize));
986 168
}
987
988
/*--------------------------------------------------------------------
989
 * purges
990
 */
991
992
VCL_INT
993 56
VRT_purge(VRT_CTX, VCL_DURATION ttl, VCL_DURATION grace, VCL_DURATION keep)
994
{
995
996 56
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
997
998 56
        if ((ctx->method & (VCL_MET_HIT|VCL_MET_MISS)) == 0) {
999 0
                VRT_fail(ctx,
1000
                    "purge can only happen in vcl_hit{} or vcl_miss{}");
1001 0
                return (0);
1002
        }
1003
1004 56
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
1005 56
        CHECK_OBJ_NOTNULL(ctx->req->wrk, WORKER_MAGIC);
1006 112
        return (HSH_Purge(ctx->req->wrk, ctx->req->objcore->objhead,
1007 56
            ctx->req->t_req, ttl, grace, keep));
1008 56
}
1009
1010
/*--------------------------------------------------------------------
1011
 */
1012
1013
struct vsmw_cluster * v_matchproto_()
1014 5056
VRT_VSM_Cluster_New(VRT_CTX, size_t sz)
1015
{
1016
        struct vsmw_cluster *vc;
1017
1018 5056
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1019 5056
        assert(sz > 0);
1020 5056
        AN(vsc_lock);
1021 5056
        AN(vsc_unlock);
1022 5056
        AN(heritage.proc_vsmw);
1023 5056
        vsc_lock();
1024 5056
        vc = VSMW_NewCluster(heritage.proc_vsmw, sz, "VSC_cluster");
1025 5056
        vsc_unlock();
1026 5056
        return (vc);
1027
}
1028
1029
void v_matchproto_()
1030 312
VRT_VSM_Cluster_Destroy(VRT_CTX, struct vsmw_cluster **vsmcp)
1031
{
1032
1033 312
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1034 312
        AN(vsmcp);
1035 312
        VSMW_DestroyCluster(heritage.proc_vsmw, vsmcp);
1036 312
}
1037
1038
/*--------------------------------------------------------------------
1039
 * Simple stuff
1040
 */
1041
1042
int
1043 65497
VRT_strcmp(const char *s1, const char *s2)
1044
{
1045 65497
        if (s1 == NULL || s2 == NULL)
1046 4924
                return (1);
1047 60573
        return (vstrcmp(s1, s2));
1048 65497
}
1049
1050
void
1051 0
VRT_memmove(void *dst, const void *src, unsigned len)
1052
{
1053
1054 0
        (void)memmove(dst, src, len);
1055 0
}
1056
1057
VCL_BOOL
1058 92
VRT_ipcmp(VRT_CTX, VCL_IP sua1, VCL_IP sua2)
1059
{
1060
1061 92
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1062
1063 92
        if (sua1 == NULL || sua2 == NULL) {
1064 0
                VRT_fail(ctx, "%s: Illegal IP", __func__);
1065 0
                return (1);
1066
        }
1067 92
        return (VSA_Compare_IP(sua1, sua2));
1068 92
}
1069
1070
/*
1071
 * the pointer passed as src must have at least VCL_TASK lifetime
1072
 */
1073
VCL_BLOB
1074 988
VRT_blob(VRT_CTX, const char *err, const void *src, size_t len, unsigned type)
1075
{
1076
        struct vrt_blob *p;
1077
1078 988
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1079 988
        CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
1080
1081 988
        if (src == NULL || len == 0)
1082 8
                return (vrt_null_blob);
1083
1084 980
        p = (void *)WS_Alloc(ctx->ws, sizeof *p);
1085 980
        if (p == NULL) {
1086 24
                VRT_fail(ctx, "Workspace overflow (%s)", err);
1087 24
                return (NULL);
1088
        }
1089
1090 956
        INIT_OBJ(p, VRT_BLOB_MAGIC);
1091 956
        p->type = type;
1092 956
        p->len = len;
1093 956
        p->blob = src;
1094
1095 956
        return (p);
1096 988
}
1097
1098
int
1099 386356
VRT_VSA_GetPtr(VRT_CTX, const struct suckaddr *sua, const unsigned char ** dst)
1100
{
1101
1102 386356
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1103 386356
        AN(dst);
1104
1105 386356
        if (sua == NULL) {
1106 0
                VRT_fail(ctx, "%s: Illegal IP", __func__);
1107 0
                *dst = NULL;
1108 0
                return (-1);
1109
        }
1110 386356
        return (VSA_GetPtr(sua, dst));
1111 386356
}
1112
1113
void
1114 8
VRT_Format_Proxy(struct vsb *vsb, VCL_INT version, VCL_IP sac, VCL_IP sas,
1115
    VCL_STRING auth)
1116
{
1117 8
        VPX_Format_Proxy(vsb, (int)version, sac, sas, auth);
1118 8
}
1119
1120
/*
1121
 * Clone a struct vrt_endpoint in a single malloc() allocation
1122
 */
1123
1124
//lint -e{662}  Possible of out-of-bounds pointer (___ beyond end of data)
1125
//lint -e{826}  Suspicious pointer-to-pointer conversion (area to o small
1126
struct vrt_endpoint *
1127 10952
VRT_Endpoint_Clone(const struct vrt_endpoint * const vep)
1128
{
1129
        size_t sz;
1130
        struct vrt_endpoint *nvep;
1131 10952
        struct vrt_blob *blob = NULL;
1132
        struct suckaddr *sa;
1133 10952
        size_t uds_len = 0;
1134
        char *p, *e;
1135
1136 10952
        CHECK_OBJ_NOTNULL(vep, VRT_ENDPOINT_MAGIC);
1137 10952
        sz = sizeof *nvep;
1138 10952
        if (vep->ipv4)
1139 10548
                sz += vsa_suckaddr_len;
1140 10952
        if (vep->ipv6)
1141 48
                sz += vsa_suckaddr_len;
1142 10952
        if (vep->uds_path != NULL) {
1143 372
                uds_len = vstrlen(vep->uds_path) + 1;
1144 372
                sz += uds_len;
1145 372
        }
1146 10952
        if (vep->preamble != NULL && vep->preamble->len) {
1147 72
                sz += sizeof(*blob);
1148 72
                sz += vep->preamble->len;
1149 72
        }
1150 10952
        p = calloc(1, sz);
1151 10952
        AN(p);
1152 10952
        e = p + sz;
1153 10952
        nvep = (void*)p;
1154 10952
        p += sizeof *nvep;
1155 10952
        INIT_OBJ(nvep, VRT_ENDPOINT_MAGIC);
1156 10952
        if (vep->ipv4) {
1157 10548
                sa = (void*)p;
1158 10548
                memcpy(sa, vep->ipv4, vsa_suckaddr_len);
1159 10548
                nvep->ipv4 = sa;
1160 10548
                p += vsa_suckaddr_len;
1161 10548
        }
1162 10952
        if (vep->ipv6) {
1163 48
                sa = (void*)p;
1164 48
                memcpy(sa, vep->ipv6, vsa_suckaddr_len);
1165 48
                nvep->ipv6 = sa;
1166 48
                p += vsa_suckaddr_len;
1167 48
        }
1168 10952
        if (vep->preamble != NULL && vep->preamble->len) {
1169
                /* Before uds because we need p to be aligned still */
1170 72
                blob = (void*)p;
1171 72
                INIT_OBJ(blob, VRT_BLOB_MAGIC);
1172 72
                p += sizeof(*blob);
1173 72
                nvep->preamble = blob;
1174 72
                memcpy(p, vep->preamble->blob, vep->preamble->len);
1175 72
                blob->type = 0x70ea5b1e;
1176 72
                blob->len = vep->preamble->len;
1177 72
                blob->blob = p;
1178 72
                p += vep->preamble->len;
1179 72
        }
1180 10952
        if (uds_len) {
1181 372
                memcpy(p, vep->uds_path, uds_len);
1182 372
                nvep->uds_path = p;
1183 372
                p += uds_len;
1184 372
        }
1185 10952
        assert(p == e);
1186 10952
        return (nvep);
1187
}