varnish-cache/bin/varnishd/cache/cache_vrt.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 *
29
 * Runtime support for compiled VCL programs
30
 */
31
32
#include "config.h"
33
34
#include "cache_varnishd.h"
35
36
#include "cache_objhead.h"
37
#include "vav.h"
38
#include "vcl.h"
39
#include "vrt_obj.h"
40
#include "vsa.h"
41
#include "vtcp.h"
42
#include "vtim.h"
43
44
#include "common/heritage.h"
45
#include "common/vsmw.h"
46
47
const void * const vrt_magic_string_end = &vrt_magic_string_end;
48
const void * const vrt_magic_string_unset = &vrt_magic_string_unset;
49
50
/*--------------------------------------------------------------------*/
51
52
VCL_VOID
53 140
VRT_synth(VRT_CTX, VCL_INT code, VCL_STRING reason)
54
{
55
56 140
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
57 140
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
58 140
        if (code < 100 || code > 65535)
59 0
                code = 503;
60 140
        ctx->req->err_code = (uint16_t)code;
61 280
        ctx->req->err_reason = reason ? reason
62 140
            : http_Status2Reason(ctx->req->err_code % 1000, NULL);
63 140
}
64
65
/*--------------------------------------------------------------------*/
66
67
void
68 28
VRT_acl_log(VRT_CTX, const char *msg)
69
{
70
71 28
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
72 28
        AN(msg);
73 28
        if (ctx->vsl != NULL)
74 27
                VSLb(ctx->vsl, SLT_VCL_acl, "%s", msg);
75
        else
76 1
                VSL(SLT_VCL_acl, 0, "%s", msg);
77 28
}
78
79
int
80 28
VRT_acl_match(VRT_CTX, VCL_ACL acl, VCL_IP ip)
81
{
82
83 28
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
84 28
        CHECK_OBJ_NOTNULL(acl, VRT_ACL_MAGIC);
85 28
        assert(VSA_Sane(ip));
86 28
        return (acl->match(ctx, ip));
87
}
88
89
/*--------------------------------------------------------------------*/
90
91
VCL_VOID
92 11
VRT_hit_for_pass(VRT_CTX, VCL_DURATION d)
93
{
94
        struct objcore *oc;
95
96 11
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
97 11
        if (ctx->bo == NULL) {
98 0
                VSLb(ctx->vsl, SLT_Error,
99
                    "Note: Ignoring DURATION argument to return(pass);");
100 0
                return;
101
        }
102 11
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
103 11
        oc = ctx->bo->fetch_objcore;
104 11
        oc->ttl = d;
105 11
        oc->grace = 0.0;
106 11
        oc->keep = 0.0;
107 44
        VSLb(ctx->vsl, SLT_TTL, "HFP %.0f %.0f %.0f %.0f uncacheable",
108 33
            oc->ttl, oc->grace, oc->keep, oc->t_origin);
109
}
110
111
/*--------------------------------------------------------------------*/
112
113
VCL_HTTP
114 19553
VRT_selecthttp(VRT_CTX, enum gethdr_e where)
115
{
116
        struct http *hp;
117
118 19553
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
119 19553
        switch (where) {
120
        case HDR_REQ:
121 11620
                hp = ctx->http_req;
122 11620
                break;
123
        case HDR_REQ_TOP:
124 4
                hp = ctx->http_req_top;
125 4
                break;
126
        case HDR_BEREQ:
127 136
                hp = ctx->http_bereq;
128 136
                break;
129
        case HDR_BERESP:
130 5671
                hp = ctx->http_beresp;
131 5671
                break;
132
        case HDR_RESP:
133 2122
                hp = ctx->http_resp;
134 2122
                break;
135
        default:
136 0
                WRONG("VRT_selecthttp 'where' invalid");
137
        }
138 19553
        return (hp);
139
}
140
141
/*--------------------------------------------------------------------*/
142
143
VCL_STRING
144 16425
VRT_GetHdr(VRT_CTX, const struct gethdr_s *hs)
145
{
146
        const char *p;
147
        struct http *hp;
148
149 16425
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
150 16425
        if (hs->where == HDR_OBJ) {
151 14
                CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
152 14
                CHECK_OBJ_NOTNULL(ctx->req->objcore, OBJCORE_MAGIC);
153 14
                return(HTTP_GetHdrPack(ctx->req->wrk, ctx->req->objcore,
154
                    hs->what));
155
        }
156 16411
        hp = VRT_selecthttp(ctx, hs->where);
157 16411
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
158 16411
        if (!http_GetHdr(hp, hs->what, &p))
159 8626
                return (NULL);
160 7786
        return (p);
161
}
162
163
/*--------------------------------------------------------------------
164
 * Build STRANDS from what is essentially a STRING_LIST
165
 */
166
167
VCL_STRANDS
168 762
VRT_BundleStrands(int n, struct strands *s, char const **d, const char *f, ...)
169
{
170
        va_list ap;
171
172 762
        s->n = n;
173 762
        s->p = d;
174 762
        *d++ = f;
175 762
        va_start(ap, f);
176 2044
        while(--n)
177 520
                *d++ = va_arg(ap, const char *);
178 762
        assert(va_arg(ap, const char *) == vrt_magic_string_end);
179 762
        va_end(ap);
180 762
        return (s);
181
}
182
183
/*--------------------------------------------------------------------
184
 * Compare two STRANDS
185
 */
186
187
int
188 127
VRT_CompareStrands(VCL_STRANDS a, VCL_STRANDS b)
189
{
190 127
        const char *pa = NULL, *pb = NULL;
191 127
        int na = 0, nb = 0;
192
193
        while (1) {
194 1013
                if (pa != NULL && *pa == '\0')
195 85
                        pa = NULL;
196 570
                if (pb != NULL && *pb == '\0')
197 67
                        pb = NULL;
198 570
                if (pa == NULL && na < a->n)
199 194
                        pa = a->p[na++];
200 376
                else if (pb == NULL && nb < b->n)
201 182
                        pb = b->p[nb++];
202 194
                else if (pa == NULL && pb == NULL)
203 37
                        return (0);
204 157
                else if (pa == NULL)
205 24
                        return (-1);
206 133
                else if (pb == NULL)
207 12
                        return (1);
208 121
                else if (*pa == '\0')
209 0
                        pa = NULL;
210 121
                else if (*pb == '\0')
211 0
                        pb = NULL;
212 121
                else if (*pa != *pb)
213 54
                        return (*pa - *pb);
214
                else {
215 67
                        pa++;
216 67
                        pb++;
217
                }
218
        }
219
}
220
221
/*--------------------------------------------------------------------
222
 * Collapse a STRING_LIST in the space provided, or return NULL
223
 */
224
225
char *
226 3190
VRT_StringList(char *d, unsigned dl, const char *p, va_list ap)
227
{
228
        char *b, *e;
229
        unsigned x;
230
231 3190
        b = d;
232 3190
        e = b + dl;
233 9682
        while (p != vrt_magic_string_end && b < e) {
234 3302
                if (p != NULL && *p != '\0') {
235 3147
                        x = strlen(p);
236 3147
                        if (b + x < e)
237 3118
                                memcpy(b, p, x);
238 3147
                        b += x;
239
                }
240 3302
                p = va_arg(ap, const char *);
241
        }
242 3190
        if (b >= e)
243 103
                return (NULL);
244 3087
        *b++ = '\0';
245 3087
        return (b);
246
}
247
248
/*--------------------------------------------------------------------
249
 * Copy and merge a STRING_LIST into a workspace.
250
 */
251
252
const char *
253 3204
VRT_String(struct ws *ws, const char *h, const char *p, va_list ap)
254
{
255
        char *b, *e;
256
        const char *q;
257
        unsigned u, x;
258
        va_list aq;
259
260 3204
        u = WS_Reserve(ws, 0);
261 3204
        e = b = ws->f;
262 3204
        e += u;
263
264 3204
        va_copy(aq, ap);
265
        do
266 3207
                q = va_arg(aq, const char *);
267 3207
        while (q == NULL || (q != vrt_magic_string_end && *q == '\0'));
268
269 3295
        if (h != NULL && p == NULL && q == vrt_magic_string_end &&
270 91
            WS_Inside(ws, h, NULL)) {
271 0
                va_end(aq);
272 0
                WS_Release(ws, 0);
273 0
                return (h);
274
        }
275
276 3304
        if (h == NULL && p != NULL && q == vrt_magic_string_end &&
277 100
            WS_Inside(ws, p, NULL)) {
278 9
                va_end(aq);
279 9
                WS_Release(ws, 0);
280 9
                return (p);
281
        }
282
283 3195
        if (h == NULL && p == NULL) {
284 5
                if (q == vrt_magic_string_end) {
285 4
                        va_end(aq);
286 4
                        WS_Release(ws, 0);
287 4
                        return ("");
288
                }
289
                do
290 1
                        p = va_arg(aq, const char *);
291 1
                while (p == NULL || (p != vrt_magic_string_end && *p == '\0'));
292 1
                if (p == vrt_magic_string_end && WS_Inside(ws, q, NULL)) {
293 1
                        va_end(aq);
294 1
                        WS_Release(ws, 0);
295 1
                        return (q);
296
                }
297 0
                p = NULL;
298 0
                va_end(aq);
299
        }
300
301 3190
        if (h != NULL) {
302 3061
                x = strlen(h);
303 3061
                if (b + x < e)
304 2999
                        memcpy(b, h, x);
305 3061
                b += x;
306 3061
                if (b < e)
307 2999
                        *b = ' ';
308 3061
                b++;
309
        }
310 3190
        b = VRT_StringList(b, e > b ? e - b : 0, p, ap);
311 3190
        if (b == NULL || b == e) {
312 103
                WS_MarkOverflow(ws);
313 103
                WS_Release(ws, 0);
314 103
                return (NULL);
315
        }
316 3087
        e = b;
317 3087
        b = ws->f;
318 3087
        WS_Release(ws, e - b);
319 3087
        return (b);
320
}
321
322
/*--------------------------------------------------------------------
323
 * Copy and merge a STRING_LIST on the current workspace
324
 */
325
326
VCL_STRING
327 27
VRT_CollectString(VRT_CTX, const char *p, ...)
328
{
329
        va_list ap;
330
        const char *b;
331
332 27
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
333 27
        CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
334 27
        va_start(ap, p);
335 27
        b = VRT_String(ctx->ws, NULL, p, ap);
336 27
        va_end(ap);
337 27
        if (b == NULL)
338 0
                VRT_fail(ctx, "Workspace overflow");
339 27
        return (b);
340
}
341
342
/*--------------------------------------------------------------------
343
 * Collapse STRANDS into the space provided, or return NULL
344
 */
345
346
char *
347 22
VRT_Strands(char *d, size_t dl, VCL_STRANDS s)
348
{
349
        char *b;
350
        const char *e;
351
        unsigned x;
352
353 22
        AN(d);
354 22
        AN(s);
355 22
        b = d;
356 22
        e = b + dl;
357 99
        for (int i = 0; i < s->n; i++)
358 79
                if (s->p[i] != NULL && *s->p[i] != '\0') {
359 42
                        x = strlen(s->p[i]);
360 42
                        if (b + x >= e)
361 2
                                return(NULL);
362 40
                        memcpy(b, s->p[i], x);
363 40
                        b += x;
364
                }
365 20
        assert(b < e);
366 20
        *b++ = '\0';
367 20
        return (b);
368
}
369
370
/*--------------------------------------------------------------------
371
 * Copy and merge STRANDS into a workspace.
372
 */
373
374
VCL_STRING
375 28
VRT_StrandsWS(struct ws *ws, const char *h, VCL_STRANDS s)
376
{
377
        char *b;
378 28
        const char *q = NULL, *e;
379
        VCL_STRING r;
380
        unsigned u, x;
381
        int i;
382
383 28
        AN(s);
384 28
        u = WS_Reserve(ws, 0);
385
386 43
        for (i = 0; i < s->n; i++)
387 40
                if (s->p[i] != NULL && *s->p[i] != '\0') {
388 25
                        q = s->p[i];
389 25
                        break;
390
                }
391
392 28
        if (h != NULL && q == NULL && WS_Inside(ws, h, NULL)) {
393 0
                WS_Release(ws, 0);
394 0
                return (h);
395
        }
396
397 28
        if (h == NULL) {
398 20
                if (q == NULL) {
399 2
                        WS_Release(ws, 0);
400 2
                        return ("");
401
                }
402 18
                if (WS_Inside(ws, q, NULL)) {
403 24
                        for (i++; i < s->n; i++)
404 18
                                if (s->p[i] != NULL && *s->p[i] != '\0')
405 8
                                        break;
406 14
                        if (i == s->n) {
407 6
                                WS_Release(ws, 0);
408 6
                                return (q);
409
                        }
410
                }
411
        }
412
413 20
        b = WS_Front(ws);
414 20
        e = b + u;
415
416 20
        if (h != NULL) {
417 8
                x = strlen(h);
418 8
                if (b + x < e)
419 8
                        memcpy(b, h, x);
420 8
                b += x;
421 8
                if (b < e)
422 8
                        *b = ' ';
423 8
                b++;
424
        }
425 20
        r = VRT_Strands(b, e > b ? e - b : 0, s);
426 20
        if (r == NULL || r == e) {
427 2
                WS_MarkOverflow(ws);
428 2
                WS_Release(ws, 0);
429 2
                return (NULL);
430
        }
431 18
        b = WS_Front(ws);
432 18
        WS_Release(ws, r - b);
433 18
        return (b);
434
}
435
436
/*--------------------------------------------------------------------
437
 * Copy and merge STRANDS on the current workspace
438
 */
439
440
VCL_STRING
441 12
VRT_CollectStrands(VRT_CTX, VCL_STRANDS s)
442
{
443
        const char *b;
444
445 12
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
446 12
        CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
447 12
        b = VRT_StrandsWS(ctx->ws, NULL, s);
448 12
        if (b == NULL)
449 1
                VRT_fail(ctx, "Workspace overflow");
450 12
        return (b);
451
}
452
453
/*--------------------------------------------------------------------*/
454
455
VCL_VOID
456 3124
VRT_SetHdr(VRT_CTX , const struct gethdr_s *hs,
457
    const char *p, ...)
458
{
459
        struct http *hp;
460
        va_list ap;
461
        const char *b;
462
463 3124
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
464 3124
        AN(hs);
465 3124
        AN(hs->what);
466 3124
        hp = VRT_selecthttp(ctx, hs->where);
467 3124
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
468 3124
        va_start(ap, p);
469 3124
        if (p == vrt_magic_string_unset) {
470 66
                http_Unset(hp, hs->what);
471
        } else {
472 3058
                b = VRT_String(hp->ws, hs->what + 1, p, ap);
473 3058
                if (b == NULL) {
474 103
                        VSLb(ctx->vsl, SLT_LostHeader, "%s", hs->what + 1);
475
                } else {
476 2955
                        http_Unset(hp, hs->what);
477 2955
                        http_SetHeader(hp, b);
478
                }
479
        }
480 3124
        va_end(ap);
481 3124
}
482
483
/*--------------------------------------------------------------------*/
484
485
VCL_VOID
486 14060
VRT_handling(VRT_CTX, unsigned hand)
487
{
488
489 14060
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
490 14060
        if (ctx->handling == NULL)
491 0
                return;
492 14060
        assert(hand > 0);
493 14060
        assert(hand < VCL_RET_MAX);
494
        // XXX:NOTYET assert(*ctx->handling == 0);
495 14060
        *ctx->handling = hand;
496
}
497
498
/*--------------------------------------------------------------------*/
499
500
VCL_VOID
501 133
VRT_fail(VRT_CTX, const char *fmt, ...)
502
{
503
        va_list ap;
504
505 133
        assert(ctx->vsl != NULL || ctx->msg != NULL);
506 133
        AZ(strchr(fmt, '\n'));
507 133
        va_start(ap, fmt);
508 133
        if (ctx->vsl != NULL)
509 96
                VSLbv(ctx->vsl, SLT_VCL_Error, fmt, ap);
510
        else {
511 37
                VSB_vprintf(ctx->msg, fmt, ap);
512 37
                VSB_putc(ctx->msg, '\n');
513
        }
514 133
        va_end(ap);
515 133
        VRT_handling(ctx, VCL_RET_FAIL);
516 133
}
517
518
/*--------------------------------------------------------------------
519
 * Feed data into the hash calculation
520
 */
521
522
VCL_VOID
523 4927
VRT_hashdata(VRT_CTX, const char *str, ...)
524
{
525
        va_list ap;
526
        const char *p;
527
528 4927
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
529 4927
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
530 4927
        AN(ctx->specific);
531 4927
        HSH_AddString(ctx->req, ctx->specific, str);
532 4927
        va_start(ap, str);
533
        while (1) {
534 4935
                p = va_arg(ap, const char *);
535 4931
                if (p == vrt_magic_string_end)
536 4927
                        break;
537 4
                HSH_AddString(ctx->req, ctx->specific, p);
538
        }
539 4927
        va_end(ap);
540
        /*
541
         * Add a 'field-separator' to make it more difficult to
542
         * manipulate the hash.
543
         */
544 4927
        HSH_AddString(ctx->req, ctx->specific, NULL);
545 4927
}
546
547
/*--------------------------------------------------------------------*/
548
549
VCL_TIME
550 115
VRT_r_now(VRT_CTX)
551
{
552 115
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
553 115
        return (ctx->now);
554
}
555
556
/*--------------------------------------------------------------------*/
557
558
VCL_STRING v_matchproto_()
559 153
VRT_IP_string(VRT_CTX, VCL_IP ip)
560
{
561
        char *p;
562
        unsigned len;
563
564 153
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
565 153
        if (ip == NULL)
566 0
                return (NULL);
567 153
        len = WS_Reserve(ctx->ws, 0);
568 153
        if (len == 0) {
569 2
                WS_Release(ctx->ws, 0);
570 2
                return (NULL);
571
        }
572 151
        p = ctx->ws->f;
573 151
        VTCP_name(ip, p, len, NULL, 0);
574 151
        WS_Release(ctx->ws, strlen(p) + 1);
575 151
        return (p);
576
}
577
578
VCL_STRING v_matchproto_()
579 987
VRT_INT_string(VRT_CTX, VCL_INT num)
580
{
581
582 987
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
583 987
        return (WS_Printf(ctx->ws, "%jd", (intmax_t)num));
584
}
585
586
VCL_STRING v_matchproto_()
587 193
VRT_REAL_string(VRT_CTX, VCL_REAL num)
588
{
589
590 193
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
591 193
        return (WS_Printf(ctx->ws, "%.3f", num));
592
}
593
594
VCL_STRING v_matchproto_()
595 27
VRT_TIME_string(VRT_CTX, VCL_TIME t)
596
{
597
        char *p;
598
599 27
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
600 27
        p = WS_Alloc(ctx->ws, VTIM_FORMAT_SIZE);
601 27
        if (p != NULL)
602 27
                VTIM_format(t, p);
603 27
        return (p);
604
}
605
606
VCL_STRING v_matchproto_()
607 3417
VRT_BACKEND_string(VCL_BACKEND d)
608
{
609 3417
        if (d == NULL)
610 0
                return (NULL);
611 3417
        CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
612 3417
        return (d->vcl_name);
613
}
614
615
VCL_STRING v_matchproto_()
616 383
VRT_BOOL_string(VCL_BOOL val)
617
{
618
619 383
        return (val ? "true" : "false");
620
}
621
622
/*--------------------------------------------------------------------*/
623
624
VCL_VOID
625 4
VRT_Rollback(VRT_CTX, VCL_HTTP hp)
626
{
627
628 4
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
629 4
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
630 4
        if (hp == ctx->http_req) {
631 3
                CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
632 3
                Req_Rollback(ctx->req);
633 1
        } else if (hp == ctx->http_bereq) {
634 1
                CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
635
                // -> VBO_Rollback ?
636 1
                VCL_TaskLeave(ctx->bo->vcl, ctx->bo->privs);
637 1
                VCL_TaskEnter(ctx->bo->vcl, ctx->bo->privs);
638 1
                HTTP_Copy(ctx->bo->bereq, ctx->bo->bereq0);
639 1
                WS_Reset(ctx->bo->bereq->ws, ctx->bo->ws_bo);
640 1
                WS_Reset(ctx->bo->ws, ctx->bo->ws_bo);
641
        } else
642 0
                WRONG("VRT_Rollback 'hp' invalid");
643 4
}
644
645
/*--------------------------------------------------------------------*/
646
647
VCL_VOID
648 1
VRT_synth_page(VRT_CTX, const char *str, ...)
649
{
650
        va_list ap;
651
        const char *p;
652
        struct vsb *vsb;
653
654 1
        CAST_OBJ_NOTNULL(vsb, ctx->specific, VSB_MAGIC);
655 1
        va_start(ap, str);
656 1
        p = str;
657 3
        while (p != vrt_magic_string_end) {
658 1
                if (p == NULL)
659 1
                        p = "(null)";
660 1
                if (VSB_cat(vsb, p)) {
661 0
                        VRT_fail(ctx, "synthetic(): %s",
662
                                 strerror(VSB_error(vsb)));
663 0
                        break;
664
                }
665 1
                p = va_arg(ap, const char *);
666
        }
667 1
        va_end(ap);
668 1
}
669
670
/*--------------------------------------------------------------------*/
671
672
VCL_VOID
673 24
VRT_ban_string(VRT_CTX, VCL_STRING str)
674
{
675
        char *a1, *a2, *a3;
676
        char **av;
677
        struct ban_proto *bp;
678
        const char *err;
679
        int i;
680
681 24
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
682 24
        AN(ctx->vsl);
683
684 24
        if (str == NULL) {
685 1
                VSLb(ctx->vsl, SLT_VCL_Error, "ban(): Null argument");
686 1
                return;
687
        }
688
689 23
        bp = BAN_Build();
690 23
        if (bp == NULL) {
691 0
                VSLb(ctx->vsl, SLT_VCL_Error, "ban(): Out of Memory");
692 0
                return;
693
        }
694 23
        av = VAV_Parse(str, NULL, ARGV_NOESC);
695 23
        AN(av);
696 23
        if (av[0] != NULL) {
697 0
                VSLb(ctx->vsl, SLT_VCL_Error, "ban(): %s", av[0]);
698 0
                VAV_Free(av);
699 0
                BAN_Abandon(bp);
700 0
                return;
701
        }
702 23
        for (i = 0; ;) {
703 29
                a1 = av[++i];
704 26
                if (a1 == NULL) {
705 1
                        VSLb(ctx->vsl, SLT_VCL_Error,
706
                            "ban(): No ban conditions found.");
707 1
                        break;
708
                }
709 25
                a2 = av[++i];
710 25
                if (a2 == NULL) {
711 1
                        VSLb(ctx->vsl, SLT_VCL_Error,
712
                            "ban(): Expected comparison operator.");
713 1
                        break;
714
                }
715 24
                a3 = av[++i];
716 24
                if (a3 == NULL) {
717 1
                        VSLb(ctx->vsl, SLT_VCL_Error,
718
                            "ban(): Expected second operand.");
719 1
                        break;
720
                }
721 23
                err = BAN_AddTest(bp, a1, a2, a3);
722 23
                if (err) {
723 2
                        VSLb(ctx->vsl, SLT_VCL_Error, "ban(): %s", err);
724 2
                        break;
725
                }
726 21
                if (av[++i] == NULL) {
727 17
                        err = BAN_Commit(bp);
728 17
                        if (err == NULL)
729 17
                                bp = NULL;
730
                        else
731 0
                                VSLb(ctx->vsl, SLT_VCL_Error, "ban(): %s", err);
732 17
                        break;
733
                }
734 4
                if (strcmp(av[i], "&&")) {
735 1
                        VSLb(ctx->vsl, SLT_VCL_Error,
736
                            "ban(): Expected && between conditions,"
737 1
                            " found \"%s\"", av[i]);
738 1
                        break;
739
                }
740
        }
741 23
        if (bp != NULL)
742 6
                BAN_Abandon(bp);
743 23
        VAV_Free(av);
744
}
745
746
VCL_BYTES
747 11
VRT_CacheReqBody(VRT_CTX, VCL_BYTES maxsize)
748
{
749
750 11
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
751 11
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
752 11
        if (ctx->method != VCL_MET_RECV) {
753 0
                VSLb(ctx->vsl, SLT_VCL_Error,
754
                    "req.body can only be cached in vcl_recv{}");
755 0
                return (-1);
756
        }
757 11
        return (VRB_Cache(ctx->req, maxsize));
758
}
759
760
/*--------------------------------------------------------------------
761
 * purges
762
 */
763
764
VCL_INT
765 14
VRT_purge(VRT_CTX, VCL_DURATION ttl, VCL_DURATION grace, VCL_DURATION keep)
766
{
767
768 14
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
769
770 14
        if ((ctx->method & (VCL_MET_HIT|VCL_MET_MISS)) == 0) {
771 9
                VSLb(ctx->vsl, SLT_VCL_Error,
772
                    "purge can only happen in vcl_hit{} or vcl_miss{}");
773 9
                VRT_handling(ctx, VCL_RET_FAIL);
774 9
                return (0);
775
        }
776
777 5
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
778 5
        CHECK_OBJ_NOTNULL(ctx->req->wrk, WORKER_MAGIC);
779 5
        return (HSH_Purge(ctx->req->wrk, ctx->req->objcore->objhead,
780 5
            ctx->req->t_req, ttl, grace, keep));
781
}
782
783
/*--------------------------------------------------------------------
784
 */
785
786
struct vsmw_cluster * v_matchproto_()
787 856
VRT_VSM_Cluster_New(VRT_CTX, size_t sz)
788
{
789
        struct vsmw_cluster *vc;
790
791 856
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
792 856
        assert(sz > 0);
793 856
        AN(vsc_lock);
794 856
        AN(vsc_unlock);
795 856
        AN(heritage.proc_vsmw);
796 856
        vsc_lock();
797 856
        vc = VSMW_NewCluster(heritage.proc_vsmw, sz, "VSC_cluster");
798 856
        vsc_unlock();
799 856
        return (vc);
800
}
801
802
void v_matchproto_()
803 62
VRT_VSM_Cluster_Destroy(VRT_CTX, struct vsmw_cluster **vsmcp)
804
{
805
806 62
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
807 62
        AN(vsmcp);
808 62
        VSMW_DestroyCluster(heritage.proc_vsmw, vsmcp);
809 62
}
810
811
/*--------------------------------------------------------------------
812
 * Simple stuff
813
 */
814
815
int
816 9119
VRT_strcmp(const char *s1, const char *s2)
817
{
818 9119
        if (s1 == NULL || s2 == NULL)
819 948
                return(1);
820 8171
        return (strcmp(s1, s2));
821
}
822
823
void
824 0
VRT_memmove(void *dst, const void *src, unsigned len)
825
{
826
827 0
        (void)memmove(dst, src, len);
828 0
}
829
830
VCL_BOOL
831 23
VRT_ipcmp(VCL_IP sua1, VCL_IP sua2)
832
{
833 23
        if (sua1 == NULL || sua2 == NULL)
834 0
                return(1);
835 23
        return (VSA_Compare_IP(sua1, sua2));
836
}
837
838
VCL_BLOB
839 19
VRT_blob(VRT_CTX, const char *err, const void *src, size_t len)
840
{
841
        struct vmod_priv *p;
842
        void *d;
843
844 19
        p = (void *)WS_Alloc(ctx->ws, sizeof *p);
845 19
        d = WS_Copy(ctx->ws, src, len);
846 19
        if (p == NULL || d == NULL) {
847 0
                VRT_fail(ctx, "Workspace overflow (%s)", err);
848 0
                return (NULL);
849
        }
850 19
        memset(p, 0, sizeof *p);
851 19
        p->len = len;
852 19
        p->priv = d;
853 19
        return (p);
854
}
855
856
int
857 28
VRT_VSA_GetPtr(const struct suckaddr *sua, const unsigned char ** dst)
858
{
859 28
        return (VSA_GetPtr(sua, dst));
860
}