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