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