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