varnish-cache/bin/varnishd/cache/cache_vrt_var.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
#include "config.h"
32
33
#include <stdio.h>
34
35
#include "cache_varnishd.h"
36
#include "common/heritage.h"
37
38
#include "vcl.h"
39
40
#include "vrt_obj.h"
41
42
static char vrt_hostname[255] = "";
43
44
/*--------------------------------------------------------------------
45
 * VRT variables relating to first line of HTTP/1.1 req/resp
46
 */
47
48
static void
49 135
vrt_do_string(VRT_CTX, struct http *hp, int fld,
50
    const char *err, const char *p, va_list ap)
51
{
52
        const char *b;
53
54 135
        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
55
56 135
        b = VRT_String(hp->ws, NULL, p, ap);
57 135
        if (b == NULL) {
58 0
                VRT_fail(ctx, "Workspace overflow (%s)", err);
59 0
                WS_MarkOverflow(hp->ws);
60 0
                return;
61
        }
62 135
        if (*b == '\0') {
63 9
                VRT_fail(ctx, "Setting %s to empty string", err);
64 9
                return;
65
        }
66 126
        http_SetH(hp, fld, b);
67
}
68
69
#define VRT_HDR_L(obj, hdr, fld)                                        \
70
VCL_VOID                                                                \
71
VRT_l_##obj##_##hdr(VRT_CTX, const char *p, ...)                        \
72
{                                                                       \
73
        va_list ap;                                                     \
74
                                                                        \
75
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
76
        va_start(ap, p);                                                \
77
        vrt_do_string(ctx, ctx->http_##obj, fld, #obj "." #hdr, p, ap); \
78
        va_end(ap);                                                     \
79
}
80
81
#define VRT_HDR_R(obj, hdr, fld)                                        \
82
VCL_STRING                                                              \
83
VRT_r_##obj##_##hdr(VRT_CTX)                                            \
84
{                                                                       \
85
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
86
        CHECK_OBJ_NOTNULL(ctx->http_##obj, HTTP_MAGIC);                 \
87
        return (ctx->http_##obj->hd[fld].b);                            \
88
}
89
90
#define VRT_HDR_LR(obj, hdr, fld)                                       \
91
        VRT_HDR_L(obj, hdr, fld)                                        \
92
        VRT_HDR_R(obj, hdr, fld)
93
94
#define VRT_STATUS_L(obj)                                               \
95
VCL_VOID                                                                \
96
VRT_l_##obj##_status(VRT_CTX, VCL_INT num)                              \
97
{                                                                       \
98
                                                                        \
99
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
100
        CHECK_OBJ_NOTNULL(ctx->http_##obj, HTTP_MAGIC);                 \
101
        if (num < 0)                                                    \
102
                VRT_fail(ctx, "%s.status (%jd) is negative",            \
103
                    #obj, (intmax_t)num);                               \
104
        else if (num > 65535)                                           \
105
                VRT_fail(ctx, "%s.status (%jd) > 65535",                \
106
                    #obj, (intmax_t)num);                               \
107
        else if ((num % 1000) < 100)                                    \
108
                VRT_fail(ctx, "illegal %s.status (%jd) (..0##)",        \
109
                    #obj, (intmax_t)num);                               \
110
        else                                                            \
111
                http_SetStatus(ctx->http_##obj, (uint16_t)num);         \
112
}
113
114
#define VRT_STATUS_R(obj)                                               \
115
VCL_INT                                                                 \
116
VRT_r_##obj##_status(VRT_CTX)                                           \
117
{                                                                       \
118
                                                                        \
119
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
120
        CHECK_OBJ_NOTNULL(ctx->http_##obj, HTTP_MAGIC);                 \
121
        return (ctx->http_##obj->status);                               \
122
}
123
124 16065
VRT_HDR_LR(req,    method,      HTTP_HDR_METHOD)
125 9624
VRT_HDR_LR(req,    url,         HTTP_HDR_URL)
126 174
VRT_HDR_LR(req,    proto,       HTTP_HDR_PROTO)
127
128 12
VRT_HDR_R(req_top,    method,   HTTP_HDR_METHOD)
129 12
VRT_HDR_R(req_top,    url,      HTTP_HDR_URL)
130 12
VRT_HDR_R(req_top,    proto,    HTTP_HDR_PROTO)
131
132 6
VRT_HDR_LR(resp,   proto,       HTTP_HDR_PROTO)
133 1995
VRT_HDR_LR(resp,   reason,      HTTP_HDR_REASON)
134 45
VRT_STATUS_L(resp)
135 1392
VRT_STATUS_R(resp)
136
137 4965
VRT_HDR_LR(bereq,  method,      HTTP_HDR_METHOD)
138 1323
VRT_HDR_LR(bereq,  url,         HTTP_HDR_URL)
139 9
VRT_HDR_LR(bereq,  proto,       HTTP_HDR_PROTO)
140 6
VRT_HDR_LR(beresp, proto,       HTTP_HDR_PROTO)
141 1209
VRT_HDR_LR(beresp, reason,      HTTP_HDR_REASON)
142 48
VRT_STATUS_L(beresp)
143 897
VRT_STATUS_R(beresp)
144
145
/*--------------------------------------------------------------------
146
 * Pulling things out of the packed object->http
147
 */
148
149
VCL_INT
150 3
VRT_r_obj_status(VRT_CTX)
151
{
152 3
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
153 3
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
154 3
        CHECK_OBJ_NOTNULL(ctx->req->objcore, OBJCORE_MAGIC);
155
156 3
        return (HTTP_GetStatusPack(ctx->req->wrk, ctx->req->objcore));
157
}
158
159
VCL_STRING
160 3
VRT_r_obj_proto(VRT_CTX)
161
{
162 3
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
163 3
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
164 3
        CHECK_OBJ_NOTNULL(ctx->req->objcore, OBJCORE_MAGIC);
165
166 3
        return (HTTP_GetHdrPack(ctx->req->wrk, ctx->req->objcore,
167
            H__Proto));
168
}
169
170
VCL_STRING
171 3
VRT_r_obj_reason(VRT_CTX)
172
{
173 3
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
174 3
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
175 3
        CHECK_OBJ_NOTNULL(ctx->req->objcore, OBJCORE_MAGIC);
176
177 3
        return (HTTP_GetHdrPack(ctx->req->wrk, ctx->req->objcore,
178
            H__Reason));
179
}
180
181
/*--------------------------------------------------------------------
182
 * bool-fields (.do_*)
183
 */
184
185
#define VBERESPW0(field)
186
#define VBERESPW1(field)                                                \
187
void                                                                    \
188
VRT_l_beresp_##field(VRT_CTX, VCL_BOOL a)                               \
189
{                                                                       \
190
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
191
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);                      \
192
        ctx->bo->field = a ? 1 : 0;                                     \
193
}
194
195
#define VBERESPR0(field)
196
#define VBERESPR1(field)                                                \
197
VCL_BOOL                                                                \
198
VRT_r_beresp_##field(VRT_CTX)                                           \
199
{                                                                       \
200
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
201
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);                      \
202
        return (ctx->bo->field);                                        \
203
}
204
205
#define BO_FLAG(l, r, w, d) \
206
        VBERESPR##r(l) \
207
        VBERESPW##w(l)
208
#include "tbl/bo_flags.h"
209
210
/*--------------------------------------------------------------------*/
211
212
VCL_BOOL
213 9
VRT_r_bereq_is_bgfetch(VRT_CTX)
214
{
215 9
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
216 9
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
217 9
        return (ctx->bo->is_bgfetch);
218
}
219
220
VCL_BOOL
221 4442
VRT_r_bereq_uncacheable(VRT_CTX)
222
{
223 4442
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
224 4442
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
225 4442
        return (ctx->bo->do_pass);
226
}
227
228
VCL_VOID
229 156
VRT_l_beresp_uncacheable(VRT_CTX, VCL_BOOL a)
230
{
231
        struct objcore *oc;
232
233 156
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
234 156
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
235 156
        CHECK_OBJ_NOTNULL(ctx->bo->fetch_objcore, OBJCORE_MAGIC);
236
237 156
        if (ctx->bo->uncacheable && !a) {
238 0
                VSLb(ctx->vsl, SLT_VCL_Error,
239
                    "Ignoring attempt to reset beresp.uncacheable");
240 156
        } else if (a) {
241 153
                ctx->bo->uncacheable = 1;
242
        }
243 156
        oc = ctx->bo->fetch_objcore;
244
245 624
        VSLb(ctx->vsl, SLT_TTL, "VCL %.0f %.0f %.0f %.0f %s",   \
246 468
            oc->ttl, oc->grace, oc->keep, oc->t_origin,         \
247 156
            ctx->bo->uncacheable ? "uncacheable" : "cacheable");\
248
}
249
250
VCL_BOOL
251 3
VRT_r_beresp_uncacheable(VRT_CTX)
252
{
253 3
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
254 3
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
255 3
        return (ctx->bo->uncacheable);
256
}
257
258
/*--------------------------------------------------------------------*/
259
260
VCL_STRING
261 12
VRT_r_client_identity(VRT_CTX)
262
{
263 12
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
264 12
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
265 12
        if (ctx->req->client_identity != NULL)
266 9
                return (ctx->req->client_identity);
267 3
        return (SES_Get_String_Attr(ctx->req->sp, SA_CLIENT_IP));
268
}
269
270
VCL_VOID
271 9
VRT_l_client_identity(VRT_CTX, const char *str, ...)
272
{
273
        va_list ap;
274
        const char *b;
275
276 9
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
277 9
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
278 9
        va_start(ap, str);
279 9
        b = VRT_String(ctx->req->http->ws, NULL, str, ap);
280 9
        va_end(ap);
281 9
        if (b == NULL) {
282 0
                VSLb(ctx->vsl, SLT_LostHeader, "client.identity");
283 0
                WS_MarkOverflow(ctx->req->http->ws);
284 0
                return;
285
        }
286 9
        ctx->req->client_identity = b;
287
}
288
289
/*--------------------------------------------------------------------*/
290
291
#define BEREQ_TIMEOUT(which)                                    \
292
VCL_VOID                                                        \
293
VRT_l_bereq_##which(VRT_CTX, VCL_DURATION num)                  \
294
{                                                               \
295
                                                                \
296
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
297
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);              \
298
        ctx->bo->which = (num > 0.0 ? num : 0.0);               \
299
}                                                               \
300
                                                                \
301
VCL_DURATION                                                    \
302
VRT_r_bereq_##which(VRT_CTX)                                    \
303
{                                                               \
304
                                                                \
305
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
306
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);              \
307
        return (ctx->bo->which);                                \
308
}
309
310 6
BEREQ_TIMEOUT(connect_timeout)
311 12
BEREQ_TIMEOUT(first_byte_timeout)
312 24
BEREQ_TIMEOUT(between_bytes_timeout)
313
314
/*--------------------------------------------------------------------*/
315
316
VCL_STRING
317 3
VRT_r_beresp_backend_name(VRT_CTX)
318
{
319
320 3
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
321 3
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
322 3
        if (ctx->bo->director_resp != NULL)
323 3
                return (ctx->bo->director_resp->vcl_name);
324 0
        return (NULL);
325
}
326
327
/*--------------------------------------------------------------------
328
 * Backends do not in general have a IP number (any more) and this
329
 * variable is really not about the backend, but the backend connection.
330
 * XXX: we may need a more general beresp.backend.{details|ident}
331
 */
332
333
VCL_IP
334 3
VRT_r_beresp_backend_ip(VRT_CTX)
335
{
336
337 3
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
338 3
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
339 3
        return (VDI_GetIP(ctx->bo));
340
}
341
342
/*--------------------------------------------------------------------*/
343
344
VCL_STEVEDORE
345 3
VRT_r_req_storage(VRT_CTX)
346
{
347 3
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
348 3
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
349 3
        return (ctx->req->storage);
350
}
351
352
VCL_VOID
353 6
VRT_l_req_storage(VRT_CTX, VCL_STEVEDORE stv)
354
{
355 6
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
356 6
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
357 6
        ctx->req->storage = stv;
358 6
}
359
360
/*--------------------------------------------------------------------*/
361
362
VCL_STEVEDORE
363 30
VRT_r_beresp_storage(VRT_CTX)
364
{
365 30
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
366 30
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
367 30
        return (ctx->bo->storage);
368
}
369
370
VCL_VOID
371 57
VRT_l_beresp_storage(VRT_CTX, VCL_STEVEDORE stv)
372
{
373 57
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
374 57
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
375 57
        ctx->bo->storage = stv;
376 57
}
377
378
/*--------------------------------------------------------------------
379
 * VCL <= 4.0 ONLY
380
 */
381
382
#include "storage/storage.h"
383
384
VCL_STRING
385 21
VRT_r_beresp_storage_hint(VRT_CTX)
386
{
387 21
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
388 21
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
389 21
        if (ctx->bo->storage == NULL)
390 3
                return (NULL);
391 18
        CHECK_OBJ_NOTNULL(ctx->bo->storage, STEVEDORE_MAGIC);
392 18
        return (ctx->bo->storage->vclname);
393
}
394
395
VCL_VOID
396 3
VRT_l_beresp_storage_hint(VRT_CTX, const char *str, ...)
397
{
398
        const char *p;
399
        va_list ap;
400
        uintptr_t sn;
401
        VCL_STEVEDORE stv;
402
403 3
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
404 3
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
405
406 3
        sn = WS_Snapshot(ctx->ws);
407 3
        va_start(ap, str);
408 3
        p = VRT_String(ctx->ws, NULL, str, ap);
409 3
        va_end(ap);
410
411 3
        if (p == NULL) {
412 0
                VSLb(ctx->vsl, SLT_LostHeader, "storage_hint");
413 0
                WS_Reset(ctx->ws, sn);
414 0
                WS_MarkOverflow(ctx->ws);
415 0
                return;
416
        }
417
418 3
        stv = VRT_stevedore(p);
419 3
        if (stv != NULL)
420 3
                ctx->bo->storage = stv;
421
422 3
        WS_Reset(ctx->ws, sn);
423
}
424
425
/*--------------------------------------------------------------------*/
426
427
VCL_STEVEDORE
428 12
VRT_r_obj_storage(VRT_CTX)
429
{
430 12
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
431 12
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
432 12
        return (ctx->req->objcore->stobj->stevedore);
433
}
434
435
/*--------------------------------------------------------------------*/
436
437
#define REQ_VAR_L(nm, elem, type, extra)                                \
438
                                                                        \
439
VCL_VOID                                                                \
440
VRT_l_req_##nm(VRT_CTX, type arg)                                       \
441
{                                                                       \
442
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
443
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);                         \
444
        extra;                                                          \
445
        ctx->req->elem = arg;                                           \
446
}
447
448
#define REQ_VAR_R(nm, elem, type)                                       \
449
                                                                        \
450
type                                                                    \
451
VRT_r_req_##nm(VRT_CTX)                                                 \
452
{                                                                       \
453
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
454
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);                         \
455
        return (ctx->req->elem);                                        \
456
}
457
458 330
REQ_VAR_L(backend_hint, director_hint, VCL_BACKEND,)
459 27
REQ_VAR_R(backend_hint, director_hint, VCL_BACKEND)
460 15
REQ_VAR_L(ttl, d_ttl, VCL_DURATION, if (!(arg>0.0)) arg = 0;)
461 18
REQ_VAR_R(ttl, d_ttl, VCL_DURATION)
462 6
REQ_VAR_L(grace, d_grace, VCL_DURATION, if (!(arg>0.0)) arg = 0;)
463 9
REQ_VAR_R(grace, d_grace, VCL_DURATION)
464
465
/*--------------------------------------------------------------------*/
466
467
VCL_VOID
468 665
VRT_l_bereq_backend(VRT_CTX, VCL_BACKEND be)
469
{
470
471 665
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
472 665
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
473 665
        ctx->bo->director_req = be;
474 665
}
475
476
VCL_BACKEND
477 105
VRT_r_bereq_backend(VRT_CTX)
478
{
479
480 105
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
481 105
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
482 105
        return (ctx->bo->director_req);
483
}
484
485
VCL_BACKEND
486 87
VRT_r_beresp_backend(VRT_CTX)
487
{
488
489 87
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
490 87
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
491 87
        return (ctx->bo->director_resp);
492
}
493
494
/*--------------------------------------------------------------------*/
495
496
VCL_VOID
497 4830
VRT_u_bereq_body(VRT_CTX)
498
{
499 4830
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
500 4830
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
501 4830
        if (ctx->bo->req != NULL) {
502 12
                CHECK_OBJ_NOTNULL(ctx->bo->req, REQ_MAGIC);
503 12
                ctx->bo->req = NULL;
504 12
                ObjSetState(ctx->bo->wrk,
505 12
                    ctx->bo->fetch_objcore, BOS_REQ_DONE);
506 12
                http_Unset(ctx->bo->bereq, H_Content_Length);
507
        }
508 4830
}
509
510
/*--------------------------------------------------------------------*/
511
512
VCL_VOID
513 33
VRT_l_req_esi(VRT_CTX, VCL_BOOL process_esi)
514
{
515
516 33
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
517 33
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
518 33
        assert(ctx->syntax <= 40);
519
        /*
520
         * Only allow you to turn of esi in the main request
521
         * else everything gets confused
522
         */
523 33
        if (ctx->req->esi_level == 0)
524 21
                ctx->req->disable_esi = !process_esi;
525 33
}
526
527
VCL_BOOL
528 9
VRT_r_req_esi(VRT_CTX)
529
{
530
531 9
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
532 9
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
533 9
        assert(ctx->syntax <= 40);
534 9
        return (!ctx->req->disable_esi);
535
}
536
537
VCL_INT
538 234
VRT_r_req_esi_level(VRT_CTX)
539
{
540
541 234
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
542 234
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
543 234
        return (ctx->req->esi_level);
544
}
545
546
/*--------------------------------------------------------------------*/
547
548
VCL_BOOL
549 24
VRT_r_req_can_gzip(VRT_CTX)
550
{
551
552 24
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
553 24
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
554 24
        return (RFC2616_Req_Gzip(ctx->req->http));      // XXX ?
555
}
556
557
/*--------------------------------------------------------------------*/
558
559
VCL_INT
560 204
VRT_r_req_restarts(VRT_CTX)
561
{
562
563 204
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
564 204
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
565 204
        return (ctx->req->restarts);
566
}
567
568
VCL_INT
569 114
VRT_r_bereq_retries(VRT_CTX)
570
{
571
572 114
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
573 114
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
574 114
        return (ctx->bo->retries);
575
}
576
577
/*--------------------------------------------------------------------
578
 * In exp.*:
579
 *      t_origin is absolute
580
 *      ttl is relative to t_origin
581
 *      grace&keep are relative to ttl
582
 * In VCL:
583
 *      ttl is relative to "ttl_now", which is t_req on the client
584
 *      side, except in vcl_deliver, where it is ctx->now. On the
585
 *      fetch side "ttl_now" is ctx->now (which is bo->t_prev).
586
 *      grace&keep are relative to ttl
587
 */
588
589
static double
590 5448
ttl_now(VRT_CTX)
591
{
592 5448
        if (ctx->bo) {
593 3471
                return (ctx->now);
594
        } else {
595 1977
                CHECK_OBJ(ctx->req, REQ_MAGIC);
596 1977
                return (ctx->method == VCL_MET_DELIVER
597 1977
                    ? ctx->now : ctx->req->t_req);
598
        }
599
}
600
601
#define VRT_DO_EXP_L(which, oc, fld, offset)                    \
602
                                                                \
603
VCL_VOID                                                        \
604
VRT_l_##which##_##fld(VRT_CTX, VCL_DURATION a)                  \
605
{                                                               \
606
                                                                \
607
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
608
        a += (offset);                                          \
609
        if (a < 0.0)                                            \
610
                a = 0.0;                                        \
611
        oc->fld = a;                                            \
612
        VSLb(ctx->vsl, SLT_TTL, "VCL %.0f %.0f %.0f %.0f %s",   \
613
            oc->ttl, oc->grace, oc->keep, oc->t_origin,         \
614
            ctx->bo->uncacheable ? "uncacheable" : "cacheable");\
615
}
616
617
#define VRT_DO_EXP_R(which, oc, fld, offset)                    \
618
                                                                \
619
VCL_DURATION                                                    \
620
VRT_r_##which##_##fld(VRT_CTX)                                  \
621
{                                                               \
622
        double d;                                               \
623
                                                                \
624
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
625
        d = oc->fld;                                            \
626
        if (d <= 0.0)                                           \
627
                d = 0.0;                                        \
628
        d -= (offset);                                          \
629
        return (d);                                             \
630
}
631
632 1953
VRT_DO_EXP_R(obj, ctx->req->objcore, ttl,
633
    ttl_now(ctx) - ctx->req->objcore->t_origin)
634 84
VRT_DO_EXP_R(obj, ctx->req->objcore, grace, 0)
635 21
VRT_DO_EXP_R(obj, ctx->req->objcore, keep, 0)
636 378
VRT_DO_EXP_L(beresp, ctx->bo->fetch_objcore, ttl,
637
    ttl_now(ctx) - ctx->bo->fetch_objcore->t_origin)
638 3090
VRT_DO_EXP_R(beresp, ctx->bo->fetch_objcore, ttl,
639
    ttl_now(ctx) - ctx->bo->fetch_objcore->t_origin)
640
641 195
VRT_DO_EXP_L(beresp, ctx->bo->fetch_objcore, grace, 0)
642 15
VRT_DO_EXP_R(beresp, ctx->bo->fetch_objcore, grace, 0)
643 138
VRT_DO_EXP_L(beresp, ctx->bo->fetch_objcore, keep, 0)
644 3
VRT_DO_EXP_R(beresp, ctx->bo->fetch_objcore, keep, 0)
645
646
/*--------------------------------------------------------------------
647
 */
648
649
#define VRT_DO_AGE_R(which, oc)                                 \
650
                                                                \
651
VCL_DURATION                                                    \
652
VRT_r_##which##_##age(VRT_CTX)                                  \
653
{                                                               \
654
                                                                \
655
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
656
        return (ttl_now(ctx) - oc->t_origin);                   \
657
}
658
659 24
VRT_DO_AGE_R(obj, ctx->req->objcore)
660 3
VRT_DO_AGE_R(beresp, ctx->bo->fetch_objcore)
661
662
/*--------------------------------------------------------------------
663
 * [[be]req|sess].xid
664
 */
665
666
VCL_STRING
667 951
VRT_r_req_xid(VRT_CTX)
668
{
669
670 951
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
671 951
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
672
673 951
        return (WS_Printf(ctx->req->http->ws, "%u",
674 951
            VXID(ctx->req->vsl->wid)));
675
}
676
677
VCL_STRING
678 714
VRT_r_bereq_xid(VRT_CTX)
679
{
680
681 714
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
682 714
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
683
684 714
        return (WS_Printf(ctx->bo->bereq->ws, "%u",
685 714
            VXID(ctx->bo->vsl->wid)));
686
}
687
688
VCL_STRING
689 18
VRT_r_sess_xid(VRT_CTX)
690
{
691 18
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
692
693 18
        if (VALID_OBJ(ctx->req, REQ_MAGIC))
694 9
                return (WS_Printf(ctx->req->http->ws, "%u",
695 9
                    VXID(ctx->req->sp->vxid)));
696
697 9
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
698 9
        return (WS_Printf(ctx->bo->bereq->ws, "%u",
699 9
            VXID(ctx->bo->sp->vxid)));
700
}
701
702
/*--------------------------------------------------------------------
703
 * req fields
704
 */
705
706
#define VREQW0(field)
707
#define VREQW1(field)                                                   \
708
VCL_VOID                                                                \
709
VRT_l_req_##field(VRT_CTX, VCL_BOOL a)                                  \
710
{                                                                       \
711
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
712
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);                         \
713
        ctx->req->field = a ? 1 : 0;                                    \
714
}
715
716
#define VREQR0(field)
717
#define VREQR1(field)                                                   \
718
VCL_BOOL                                                                \
719
VRT_r_req_##field(VRT_CTX)                                              \
720
{                                                                       \
721
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                          \
722
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);                         \
723
        return (ctx->req->field);                                       \
724
}
725
726
#define REQ_FLAG(l, r, w, d) \
727
        VREQR##r(l) \
728
        VREQW##w(l)
729
#include "tbl/req_flags.h"
730
731
/*--------------------------------------------------------------------*/
732
733
#define GIP(fld)                                                \
734
        VCL_IP                                                  \
735
        VRT_r_##fld##_ip(VRT_CTX)                               \
736
        {                                                       \
737
                struct suckaddr *sa;                            \
738
                                                                \
739
                CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);          \
740
                CHECK_OBJ_NOTNULL(ctx->sp, SESS_MAGIC);         \
741
                AZ(SES_Get_##fld##_addr(ctx->sp, &sa));         \
742
                return (sa);                                    \
743
        }
744
745 111
GIP(local)
746 114
GIP(remote)
747 207
GIP(client)
748 336
GIP(server)
749
#undef GIP
750
751
/*--------------------------------------------------------------------
752
 * local.[endpoint|socket]
753
 */
754
755
#define LOC(var,fld)                                            \
756
VCL_STRING                                                      \
757
VRT_r_local_##var(VRT_CTX)                                      \
758
{                                                               \
759
        struct sess *sp;                                        \
760
                                                                \
761
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
762
        if (VALID_OBJ(ctx->req, REQ_MAGIC))                     \
763
                sp = ctx->req->sp;                              \
764
        else {                                                  \
765
                CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);      \
766
                sp = ctx->bo->sp;                               \
767
        }                                                       \
768
                                                                \
769
        CHECK_OBJ_NOTNULL(sp->listen_sock, LISTEN_SOCK_MAGIC);  \
770
        AN(sp->listen_sock->fld);                               \
771
        return (sp->listen_sock->fld);                          \
772
}
773
774 21
LOC(endpoint, endpoint)
775 21
LOC(socket, name)
776
#undef LOC
777
778
/*--------------------------------------------------------------------*/
779
780
VCL_STRING
781 24
VRT_r_server_identity(VRT_CTX)
782
{
783
784 24
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
785 24
        if (heritage.identity != NULL)
786 24
                return (heritage.identity);
787
        else
788 0
                return ("varnishd");
789
}
790
791
VCL_STRING
792 6
VRT_r_server_hostname(VRT_CTX)
793
{
794
795 6
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
796 6
        if (vrt_hostname[0] == '\0')
797 3
                AZ(gethostname(vrt_hostname, sizeof(vrt_hostname)));
798 6
        return (vrt_hostname);
799
}
800
801
/*--------------------------------------------------------------------*/
802
803
VCL_INT
804 72
VRT_r_obj_hits(VRT_CTX)
805
{
806 72
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
807 72
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
808 72
        CHECK_OBJ_NOTNULL(ctx->req->objcore, OBJCORE_MAGIC);
809 72
        return (ctx->req->is_hit ? ctx->req->objcore->hits : 0);
810
}
811
812
VCL_BOOL
813 18
VRT_r_obj_uncacheable(VRT_CTX)
814
{
815
816 18
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
817 18
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
818 18
        CHECK_OBJ_NOTNULL(ctx->req->objcore, OBJCORE_MAGIC);
819 18
        return (ctx->req->objcore->flags & OC_F_PASS ? 1 : 0);
820
}
821
822
/*--------------------------------------------------------------------*/
823
824
VCL_BOOL
825 18
VRT_r_resp_is_streaming(VRT_CTX)
826
{
827 18
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
828 18
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
829 18
        if (ctx->req->objcore == NULL)
830 6
                return (0);     /* When called from vcl_synth */
831 12
        CHECK_OBJ_NOTNULL(ctx->req->objcore, OBJCORE_MAGIC);
832 12
        return (ctx->req->objcore->boc == NULL ? 0 : 1);
833
}
834
835
/*--------------------------------------------------------------------*/
836
837
VCL_VOID
838 3
VRT_l_resp_do_esi(VRT_CTX, VCL_BOOL process_esi)
839
{
840
841 3
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
842 3
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
843 3
        assert(ctx->syntax >= 41);
844
        /*
845
         * Only allow you to turn of esi in the main request
846
         * else everything gets confused
847
         */
848 3
        ctx->req->disable_esi = !process_esi;
849 3
}
850
851
VCL_BOOL
852 9
VRT_r_resp_do_esi(VRT_CTX)
853
{
854
855 9
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
856 9
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
857 9
        assert(ctx->syntax >= 41);
858 9
        return (!ctx->req->disable_esi);
859
}
860
861
/*--------------------------------------------------------------------*/
862
863
#define VRT_BODY_L(which)                                       \
864
VCL_VOID                                                        \
865
VRT_l_##which##_body(VRT_CTX, const char *str, ...)             \
866
{                                                               \
867
        va_list ap;                                             \
868
        const char *p;                                          \
869
        struct vsb *vsb;                                        \
870
                                                                \
871
        CAST_OBJ_NOTNULL(vsb, ctx->specific, VSB_MAGIC);        \
872
        va_start(ap, str);                                      \
873
        p = str;                                                \
874
        while (p != vrt_magic_string_end) {                     \
875
                if (p == NULL)                                  \
876
                        p = "(null)";                           \
877
                VSB_cat(vsb, p);                                \
878
                p = va_arg(ap, const char *);                   \
879
        }                                                       \
880
        va_end(ap);                                             \
881
}
882
883 408
VRT_BODY_L(beresp)
884 675
VRT_BODY_L(resp)
885
886
/*--------------------------------------------------------------------*/
887
888
VCL_BLOB
889 21
VRT_r_req_hash(VRT_CTX)
890
{
891 21
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
892 21
        CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
893 21
        return (VRT_blob(ctx, "req.hash", ctx->req->digest, DIGEST_LEN));
894
}
895
896
VCL_BLOB
897 36
VRT_r_bereq_hash(VRT_CTX)
898
{
899 36
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
900 36
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
901 36
        return (VRT_blob(ctx, "bereq.hash", ctx->bo->digest, DIGEST_LEN));
902
}
903
904
/*--------------------------------------------------------------------*/
905
906
#define HTTP_VAR(x)                                             \
907
VCL_HTTP                                                        \
908
VRT_r_##x(VRT_CTX)                                              \
909
{                                                               \
910
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
911
        CHECK_OBJ_NOTNULL(ctx->http_##x, HTTP_MAGIC);           \
912
        return (ctx->http_##x);                                 \
913
}
914
915 12
HTTP_VAR(req)
916 3
HTTP_VAR(resp)
917 3
HTTP_VAR(bereq)
918 0
HTTP_VAR(beresp)
919
920
/*--------------------------------------------------------------------*/
921
922
VCL_STRING
923 78
VRT_r_beresp_filters(VRT_CTX)
924
{
925
926 78
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
927 78
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
928 78
        if (ctx->bo->filter_list != NULL)
929 0
                return(ctx->bo->filter_list);
930
        /* We do not set bo->filter_list yet, things might still change */
931 78
        return (VBF_Get_Filter_List(ctx->bo));
932
}
933
934
VCL_VOID
935 6
VRT_l_beresp_filters(VRT_CTX, const char *str, ...)
936
{
937
        va_list ap;
938
        const char *b;
939
940 6
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
941 6
        CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
942 6
        va_start(ap, str);
943 6
        b = VRT_String(ctx->bo->ws, NULL, str, ap);
944 6
        va_end(ap);
945 6
        if (b == NULL) {
946 0
                WS_MarkOverflow(ctx->bo->ws);
947 0
                return;
948
        }
949 6
        ctx->bo->filter_list = b;
950
}