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 248
VRT_synth(VRT_CTX, VCL_INT code, VCL_STRING reason)
54
{
55
56 248
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
57 248
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
58 248
        if (code < 100 || code > 65535)
59 0
                code = 503;
60 248
        ctx->req->err_code = (uint16_t)code;
61 496
        ctx->req->err_reason = reason ? reason
62 248
            : http_Status2Reason(ctx->req->err_code % 1000, NULL);
63 248
}
64
65
/*--------------------------------------------------------------------*/
66
67
void
68 56
VRT_acl_log(VRT_CTX, const char *msg)
69
{
70
71 56
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
72 56
        AN(msg);
73 56
        if (ctx->vsl != NULL)
74 54
                VSLb(ctx->vsl, SLT_VCL_acl, "%s", msg);
75
        else
76 2
                VSL(SLT_VCL_acl, 0, "%s", msg);
77 56
}
78
79
int
80 56
VRT_acl_match(VRT_CTX, VCL_ACL acl, VCL_IP ip)
81
{
82
83 56
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
84 56
        CHECK_OBJ_NOTNULL(acl, VRT_ACL_MAGIC);
85 56
        assert(VSA_Sane(ip));
86 56
        return (acl->match(ctx, ip));
87
}
88
89
/*--------------------------------------------------------------------*/
90
91
VCL_VOID
92 22
VRT_hit_for_pass(VRT_CTX, VCL_DURATION d)
93
{
94
        struct objcore *oc;
95
96 22
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
97 22
        if (ctx->bo == NULL) {
98 2
                VSLb(ctx->vsl, SLT_Error,
99
                    "Note: Ignoring DURATION argument to return(pass);");
100 2
                return;
101
        }
102 20
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
103 20
        oc = ctx->bo->fetch_objcore;
104 20
        oc->ttl = d;
105 20
        oc->grace = 0.0;
106 20
        oc->keep = 0.0;
107 80
        VSLb(ctx->vsl, SLT_TTL, "HFP %.0f %.0f %.0f %.0f uncacheable",
108 60
            oc->ttl, oc->grace, oc->keep, oc->t_origin);
109
}
110
111
/*--------------------------------------------------------------------*/
112
113
VCL_HTTP
114 37988
VRT_selecthttp(VRT_CTX, enum gethdr_e where)
115
{
116
        struct http *hp;
117
118 37988
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
119 37988
        switch (where) {
120
        case HDR_REQ:
121 22468
                hp = ctx->http_req;
122 22468
                break;
123
        case HDR_REQ_TOP:
124 8
                hp = ctx->http_req_top;
125 8
                break;
126
        case HDR_BEREQ:
127 266
                hp = ctx->http_bereq;
128 266
                break;
129
        case HDR_BERESP:
130 11324
                hp = ctx->http_beresp;
131 11324
                break;
132
        case HDR_RESP:
133 3922
                hp = ctx->http_resp;
134 3922
                break;
135
        default:
136 0
                WRONG("VRT_selecthttp 'where' invalid");
137
        }
138 37988
        return (hp);
139
}
140
141
/*--------------------------------------------------------------------*/
142
143
VCL_STRING
144 32143
VRT_GetHdr(VRT_CTX, const struct gethdr_s *hs)
145
{
146
        const char *p;
147
        struct http *hp;
148
149 32143
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
150 32143
        if (hs->where == HDR_OBJ) {
151 28
                CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
152 28
                CHECK_OBJ_NOTNULL(ctx->req->objcore, OBJCORE_MAGIC);
153 28
                return(HTTP_GetHdrPack(ctx->req->wrk, ctx->req->objcore,
154
                    hs->what));
155
        }
156 32115
        hp = VRT_selecthttp(ctx, hs->where);
157 32115
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
158 32115
        if (!http_GetHdr(hp, hs->what, &p))
159 17070
                return (NULL);
160 15045
        return (p);
161
}
162
163
/*--------------------------------------------------------------------
164
 * Build STRANDS from what is essentially a STRING_LIST
165
 */
166
167
VCL_STRANDS
168 508
VRT_BundleStrands(int n, struct strands *s, char const **d, const char *f, ...)
169
{
170
        va_list ap;
171
172 508
        s->n = n;
173 508
        s->p = d;
174 508
        *d++ = f;
175 508
        va_start(ap, f);
176 1440
        while(--n)
177 424
                *d++ = va_arg(ap, const char *);
178 508
        assert(va_arg(ap, const char *) == vrt_magic_string_end);
179 508
        va_end(ap);
180 508
        return (s);
181
}
182
183
/*--------------------------------------------------------------------
184
 * Compare two STRANDS
185
 */
186
187
int
188 254
VRT_CompareStrands(VCL_STRANDS a, VCL_STRANDS b)
189
{
190 254
        const char *pa = NULL, *pb = NULL;
191 254
        int na = 0, nb = 0;
192
193
        while (1) {
194 2026
                if (pa != NULL && *pa == '\0')
195 170
                        pa = NULL;
196 1140
                if (pb != NULL && *pb == '\0')
197 134
                        pb = NULL;
198 1140
                if (pa == NULL && na < a->n)
199 388
                        pa = a->p[na++];
200 752
                else if (pb == NULL && nb < b->n)
201 364
                        pb = b->p[nb++];
202 388
                else if (pa == NULL && pb == NULL)
203 74
                        return (0);
204 314
                else if (pa == NULL)
205 48
                        return (-1);
206 266
                else if (pb == NULL)
207 24
                        return (1);
208 242
                else if (*pa == '\0')
209 0
                        pa = NULL;
210 242
                else if (*pb == '\0')
211 0
                        pb = NULL;
212 242
                else if (*pa != *pb)
213 108
                        return (*pa - *pb);
214
                else {
215 134
                        pa++;
216 134
                        pb++;
217
                }
218
        }
219
}
220
221
/*--------------------------------------------------------------------
222
 * Collapse a STRING_LIST in the space provided, or return NULL
223
 */
224
225
char *
226 5980
VRT_StringList(char *d, unsigned dl, const char *p, va_list ap)
227
{
228
        char *b, *e;
229
        unsigned x;
230
231 5980
        b = d;
232 5980
        e = b + dl;
233 18188
        while (p != vrt_magic_string_end && b < e) {
234 6228
                if (p != NULL && *p != '\0') {
235 5932
                        x = strlen(p);
236 5932
                        if (b + x < e)
237 5874
                                memcpy(b, p, x);
238 5932
                        b += x;
239
                }
240 6228
                p = va_arg(ap, const char *);
241
        }
242 5980
        if (b >= e)
243 182
                return (NULL);
244 5798
        *b++ = '\0';
245 5798
        return (b);
246
}
247
248
/*--------------------------------------------------------------------
249
 * Copy and merge a STRING_LIST into a workspace.
250
 */
251
252
const char *
253 6008
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 6008
        u = WS_Reserve(ws, 0);
261 6008
        e = b = ws->f;
262 6008
        e += u;
263
264 6008
        va_copy(aq, ap);
265
        do
266 6014
                q = va_arg(aq, const char *);
267 6014
        while (q == NULL || (q != vrt_magic_string_end && *q == '\0'));
268
269 6156
        if (h != NULL && p == NULL && q == vrt_magic_string_end &&
270 148
            WS_Inside(ws, h, NULL)) {
271 0
                va_end(aq);
272 0
                WS_Release(ws, 0);
273 0
                return (h);
274
        }
275
276 6202
        if (h == NULL && p != NULL && q == vrt_magic_string_end &&
277 194
            WS_Inside(ws, p, NULL)) {
278 18
                va_end(aq);
279 18
                WS_Release(ws, 0);
280 18
                return (p);
281
        }
282
283 5990
        if (h == NULL && p == NULL) {
284 10
                if (q == vrt_magic_string_end) {
285 8
                        va_end(aq);
286 8
                        WS_Release(ws, 0);
287 8
                        return ("");
288
                }
289
                do
290 2
                        p = va_arg(aq, const char *);
291 2
                while (p == NULL || (p != vrt_magic_string_end && *p == '\0'));
292 2
                if (p == vrt_magic_string_end && WS_Inside(ws, q, NULL)) {
293 2
                        va_end(aq);
294 2
                        WS_Release(ws, 0);
295 2
                        return (q);
296
                }
297 0
                p = NULL;
298 0
                va_end(aq);
299
        }
300
301 5980
        if (h != NULL) {
302 5728
                x = strlen(h);
303 5728
                if (b + x < e)
304 5604
                        memcpy(b, h, x);
305 5728
                b += x;
306 5728
                if (b < e)
307 5604
                        *b = ' ';
308 5728
                b++;
309
        }
310 5980
        b = VRT_StringList(b, e > b ? e - b : 0, p, ap);
311 5980
        if (b == NULL || b == e) {
312 182
                WS_MarkOverflow(ws);
313 182
                WS_Release(ws, 0);
314 182
                return (NULL);
315
        }
316 5798
        e = b;
317 5798
        b = ws->f;
318 5798
        WS_Release(ws, e - b);
319 5798
        return (b);
320
}
321
322
/*--------------------------------------------------------------------
323
 * Copy and merge a STRING_LIST on the current workspace
324
 */
325
326
VCL_STRING
327 54
VRT_CollectString(VRT_CTX, const char *p, ...)
328
{
329
        va_list ap;
330
        const char *b;
331
332 54
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
333 54
        CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
334 54
        va_start(ap, p);
335 54
        b = VRT_String(ctx->ws, NULL, p, ap);
336 54
        va_end(ap);
337 54
        if (b == NULL)
338 0
                VRT_fail(ctx, "Workspace overflow");
339 54
        return (b);
340
}
341
342
/*--------------------------------------------------------------------*/
343
344
VCL_VOID
345 5854
VRT_SetHdr(VRT_CTX , const struct gethdr_s *hs,
346
    const char *p, ...)
347
{
348
        struct http *hp;
349
        va_list ap;
350
        const char *b;
351
352 5854
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
353 5854
        AN(hs);
354 5854
        AN(hs->what);
355 5854
        hp = VRT_selecthttp(ctx, hs->where);
356 5854
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
357 5854
        va_start(ap, p);
358 5854
        if (p == vrt_magic_string_unset) {
359 132
                http_Unset(hp, hs->what);
360
        } else {
361 5722
                b = VRT_String(hp->ws, hs->what + 1, p, ap);
362 5722
                if (b == NULL) {
363 182
                        VSLb(ctx->vsl, SLT_LostHeader, "%s", hs->what + 1);
364
                } else {
365 5540
                        http_Unset(hp, hs->what);
366 5540
                        http_SetHeader(hp, b);
367
                }
368
        }
369 5854
        va_end(ap);
370 5854
}
371
372
/*--------------------------------------------------------------------*/
373
374
VCL_VOID
375 27709
VRT_handling(VRT_CTX, unsigned hand)
376
{
377
378 27709
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
379 27709
        if (ctx->handling == NULL)
380 0
                return;
381 27709
        assert(hand > 0);
382 27709
        assert(hand < VCL_RET_MAX);
383
        // XXX:NOTYET assert(*ctx->handling == 0);
384 27709
        *ctx->handling = hand;
385
}
386
387
/*--------------------------------------------------------------------*/
388
389
VCL_VOID
390 226
VRT_fail(VRT_CTX, const char *fmt, ...)
391
{
392
        va_list ap;
393
394 226
        assert(ctx->vsl != NULL || ctx->msg != NULL);
395 226
        AZ(strchr(fmt, '\n'));
396 226
        va_start(ap, fmt);
397 226
        if (ctx->vsl != NULL)
398 156
                VSLbv(ctx->vsl, SLT_VCL_Error, fmt, ap);
399
        else {
400 70
                VSB_vprintf(ctx->msg, fmt, ap);
401 70
                VSB_putc(ctx->msg, '\n');
402
        }
403 226
        va_end(ap);
404 226
        VRT_handling(ctx, VCL_RET_FAIL);
405 226
}
406
407
/*--------------------------------------------------------------------
408
 * Feed data into the hash calculation
409
 */
410
411
VCL_VOID
412 9666
VRT_hashdata(VRT_CTX, const char *str, ...)
413
{
414
        va_list ap;
415
        const char *p;
416
417 9666
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
418 9666
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
419 9666
        AN(ctx->specific);
420 9666
        HSH_AddString(ctx->req, ctx->specific, str);
421 9666
        va_start(ap, str);
422
        while (1) {
423 9682
                p = va_arg(ap, const char *);
424 9674
                if (p == vrt_magic_string_end)
425 9666
                        break;
426 8
                HSH_AddString(ctx->req, ctx->specific, p);
427
        }
428 9666
        va_end(ap);
429
        /*
430
         * Add a 'field-separator' to make it more difficult to
431
         * manipulate the hash.
432
         */
433 9666
        HSH_AddString(ctx->req, ctx->specific, NULL);
434 9666
}
435
436
/*--------------------------------------------------------------------*/
437
438
VCL_TIME
439 228
VRT_r_now(VRT_CTX)
440
{
441 228
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
442 228
        return (ctx->now);
443
}
444
445
/*--------------------------------------------------------------------*/
446
447
VCL_STRING v_matchproto_()
448 290
VRT_IP_string(VRT_CTX, VCL_IP ip)
449
{
450
        char *p;
451
        unsigned len;
452
453 290
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
454 290
        if (ip == NULL)
455 0
                return (NULL);
456 290
        len = WS_Reserve(ctx->ws, 0);
457 290
        if (len == 0) {
458 4
                WS_Release(ctx->ws, 0);
459 4
                return (NULL);
460
        }
461 286
        p = ctx->ws->f;
462 286
        VTCP_name(ip, p, len, NULL, 0);
463 286
        WS_Release(ctx->ws, strlen(p) + 1);
464 286
        return (p);
465
}
466
467
VCL_STRING v_matchproto_()
468 1816
VRT_INT_string(VRT_CTX, VCL_INT num)
469
{
470
471 1816
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
472 1816
        return (WS_Printf(ctx->ws, "%jd", (intmax_t)num));
473
}
474
475
VCL_STRING v_matchproto_()
476 386
VRT_REAL_string(VRT_CTX, VCL_REAL num)
477
{
478
479 386
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
480 386
        return (WS_Printf(ctx->ws, "%.3f", num));
481
}
482
483
VCL_STRING v_matchproto_()
484 52
VRT_TIME_string(VRT_CTX, VCL_TIME t)
485
{
486
        char *p;
487
488 52
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
489 52
        p = WS_Alloc(ctx->ws, VTIM_FORMAT_SIZE);
490 52
        if (p != NULL)
491 52
                VTIM_format(t, p);
492 52
        return (p);
493
}
494
495
VCL_STRING v_matchproto_()
496 6806
VRT_BACKEND_string(VCL_BACKEND d)
497
{
498 6806
        if (d == NULL)
499 0
                return (NULL);
500 6806
        CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
501 6806
        return (d->vcl_name);
502
}
503
504
VCL_STRING v_matchproto_()
505 642
VRT_BOOL_string(VCL_BOOL val)
506
{
507
508 642
        return (val ? "true" : "false");
509
}
510
511
/*--------------------------------------------------------------------*/
512
513
VCL_VOID
514 8
VRT_Rollback(VRT_CTX, VCL_HTTP hp)
515
{
516
517 8
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
518 8
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
519 8
        if (hp == ctx->http_req) {
520 6
                CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
521 6
                Req_Rollback(ctx->req);
522 2
        } else if (hp == ctx->http_bereq) {
523 2
                CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
524
                // -> VBO_Rollback ?
525 2
                VRTPRIV_dynamic_kill(ctx->bo->privs, (uintptr_t)ctx->bo);
526 2
                HTTP_Copy(ctx->bo->bereq, ctx->bo->bereq0);
527 2
                WS_Reset(ctx->bo->bereq->ws, ctx->bo->ws_bo);
528 2
                WS_Reset(ctx->bo->ws, ctx->bo->ws_bo);
529
        } else
530 0
                WRONG("VRT_Rollback 'hp' invalid");
531 8
}
532
533
/*--------------------------------------------------------------------*/
534
535
VCL_VOID
536 2
VRT_synth_page(VRT_CTX, const char *str, ...)
537
{
538
        va_list ap;
539
        const char *p;
540
        struct vsb *vsb;
541
542 2
        CAST_OBJ_NOTNULL(vsb, ctx->specific, VSB_MAGIC);
543 2
        va_start(ap, str);
544 2
        p = str;
545 6
        while (p != vrt_magic_string_end) {
546 2
                if (p == NULL)
547 2
                        p = "(null)";
548 2
                if (VSB_cat(vsb, p)) {
549 0
                        VRT_fail(ctx, "synthetic(): %s",
550
                                 strerror(VSB_error(vsb)));
551 0
                        break;
552
                }
553 2
                p = va_arg(ap, const char *);
554
        }
555 2
        va_end(ap);
556 2
}
557
558
/*--------------------------------------------------------------------*/
559
560
static struct VSC_main *
561 34
vrt_stats(VRT_CTX)
562
{
563
        struct worker *wrk;
564
565 34
        if (ctx->req) {
566 34
                CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
567 34
                wrk = ctx->req->wrk;
568 0
        } else if (ctx->bo) {
569 0
                CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
570 0
                wrk = ctx->bo->wrk;
571
        } else {
572
                // XXX
573 0
                return (VSC_C_main);
574
        }
575
576 34
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
577 34
        return (wrk->stats);
578
}
579
580
VCL_VOID
581 48
VRT_ban_string(VRT_CTX, VCL_STRING str)
582
{
583
        char *a1, *a2, *a3;
584
        char **av;
585
        struct ban_proto *bp;
586
        const char *err;
587
        int i;
588
589 48
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
590 48
        AN(ctx->vsl);
591
592 48
        if (str == NULL) {
593 2
                VSLb(ctx->vsl, SLT_VCL_Error, "ban(): Null argument");
594 2
                return;
595
        }
596
597 46
        bp = BAN_Build();
598 46
        if (bp == NULL) {
599 0
                VSLb(ctx->vsl, SLT_VCL_Error, "ban(): Out of Memory");
600 0
                return;
601
        }
602 46
        av = VAV_Parse(str, NULL, ARGV_NOESC);
603 46
        AN(av);
604 46
        if (av[0] != NULL) {
605 0
                VSLb(ctx->vsl, SLT_VCL_Error, "ban(): %s", av[0]);
606 0
                VAV_Free(av);
607 0
                BAN_Abandon(bp);
608 0
                return;
609
        }
610 46
        for (i = 0; ;) {
611 58
                a1 = av[++i];
612 52
                if (a1 == NULL) {
613 2
                        VSLb(ctx->vsl, SLT_VCL_Error,
614
                            "ban(): No ban conditions found.");
615 2
                        break;
616
                }
617 50
                a2 = av[++i];
618 50
                if (a2 == NULL) {
619 2
                        VSLb(ctx->vsl, SLT_VCL_Error,
620
                            "ban(): Expected comparison operator.");
621 2
                        break;
622
                }
623 48
                a3 = av[++i];
624 48
                if (a3 == NULL) {
625 2
                        VSLb(ctx->vsl, SLT_VCL_Error,
626
                            "ban(): Expected second operand.");
627 2
                        break;
628
                }
629 46
                err = BAN_AddTest(bp, a1, a2, a3);
630 46
                if (err) {
631 4
                        VSLb(ctx->vsl, SLT_VCL_Error, "ban(): %s", err);
632 4
                        break;
633
                }
634 42
                if (av[++i] == NULL) {
635 34
                        err = BAN_Commit(bp, vrt_stats(ctx));
636 34
                        if (err == NULL)
637 34
                                bp = NULL;
638
                        else
639 0
                                VSLb(ctx->vsl, SLT_VCL_Error, "ban(): %s", err);
640 34
                        break;
641
                }
642 8
                if (strcmp(av[i], "&&")) {
643 2
                        VSLb(ctx->vsl, SLT_VCL_Error,
644
                            "ban(): Expected && between conditions,"
645 2
                            " found \"%s\"", av[i]);
646 2
                        break;
647
                }
648
        }
649 46
        if (bp != NULL)
650 12
                BAN_Abandon(bp);
651 46
        VAV_Free(av);
652
}
653
654
VCL_BYTES
655 22
VRT_CacheReqBody(VRT_CTX, VCL_BYTES maxsize)
656
{
657
658 22
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
659 22
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
660 22
        if (ctx->method != VCL_MET_RECV) {
661 0
                VSLb(ctx->vsl, SLT_VCL_Error,
662
                    "req.body can only be cached in vcl_recv{}");
663 0
                return (-1);
664
        }
665 22
        return (VRB_Cache(ctx->req, maxsize));
666
}
667
668
/*--------------------------------------------------------------------
669
 * purges
670
 */
671
672
VCL_INT
673 28
VRT_purge(VRT_CTX, VCL_DURATION ttl, VCL_DURATION grace, VCL_DURATION keep)
674
{
675
676 28
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
677
678 28
        if ((ctx->method & (VCL_MET_HIT|VCL_MET_MISS)) == 0) {
679 18
                VSLb(ctx->vsl, SLT_VCL_Error,
680
                    "purge can only happen in vcl_hit{} or vcl_miss{}");
681 18
                VRT_handling(ctx, VCL_RET_FAIL);
682 18
                return (0);
683
        }
684
685 10
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
686 10
        CHECK_OBJ_NOTNULL(ctx->req->wrk, WORKER_MAGIC);
687 10
        return (HSH_Purge(ctx->req->wrk, ctx->req->objcore->objhead,
688 10
            ctx->req->t_req, ttl, grace, keep));
689
}
690
691
/*--------------------------------------------------------------------
692
 */
693
694
struct vsmw_cluster * v_matchproto_()
695 1680
VRT_VSM_Cluster_New(VRT_CTX, size_t sz)
696
{
697
        struct vsmw_cluster *vc;
698
699 1680
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
700 1680
        assert(sz > 0);
701 1680
        AN(vsc_lock);
702 1680
        AN(vsc_unlock);
703 1680
        AN(heritage.proc_vsmw);
704 1680
        vsc_lock();
705 1680
        vc = VSMW_NewCluster(heritage.proc_vsmw, sz, "VSC_cluster");
706 1680
        vsc_unlock();
707 1680
        return (vc);
708
}
709
710
void v_matchproto_()
711 116
VRT_VSM_Cluster_Destroy(VRT_CTX, struct vsmw_cluster **vsmcp)
712
{
713
714 116
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
715 116
        AN(vsmcp);
716 116
        VSMW_DestroyCluster(heritage.proc_vsmw, vsmcp);
717 116
}
718
719
/*--------------------------------------------------------------------
720
 * Simple stuff
721
 */
722
723
int
724 18028
VRT_strcmp(const char *s1, const char *s2)
725
{
726 18028
        if (s1 == NULL || s2 == NULL)
727 1894
                return(1);
728 16134
        return (strcmp(s1, s2));
729
}
730
731
void
732 0
VRT_memmove(void *dst, const void *src, unsigned len)
733
{
734
735 0
        (void)memmove(dst, src, len);
736 0
}
737
738
VCL_BOOL
739 46
VRT_ipcmp(VCL_IP sua1, VCL_IP sua2)
740
{
741 46
        if (sua1 == NULL || sua2 == NULL)
742 0
                return(1);
743 46
        return (VSA_Compare_IP(sua1, sua2));
744
}
745
746
VCL_BLOB
747 26
VRT_blob(VRT_CTX, const char *err, const void *src, size_t len)
748
{
749
        struct vmod_priv *p;
750
        void *d;
751
752 26
        p = (void *)WS_Alloc(ctx->ws, sizeof *p);
753 26
        d = WS_Copy(ctx->ws, src, len);
754 26
        if (p == NULL || d == NULL) {
755 0
                VRT_fail(ctx, "Workspace overflow (%s)", err);
756 0
                return (NULL);
757
        }
758 26
        memset(p, 0, sizeof *p);
759 26
        p->len = len;
760 26
        p->priv = d;
761 26
        return (p);
762
}