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