varnish-cache/bin/varnishd/cache/cache_vrt_filter.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2016 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 */
31
32
#include "config.h"
33
34
#include <stdio.h>
35
#include <stdint.h>
36
#include <stdlib.h>
37
38
#include "cache_varnishd.h"
39
#include "cache_vcl.h"
40
#include "vrt_obj.h"
41
42
#include "vct.h"
43
44
#include "cache_filter.h"
45
46
/*--------------------------------------------------------------------
47
 */
48
49
struct vfilter {
50
        unsigned                        magic;
51
#define VFILTER_MAGIC                   0xd40894e9
52
        const struct vfp                *vfp;
53
        const struct vdp                *vdp;
54
        const char                      *name;
55
        int                             nlen;
56
        VTAILQ_ENTRY(vfilter)           list;
57
};
58
59
static struct vfilter_head vrt_filters =
60
    VTAILQ_HEAD_INITIALIZER(vrt_filters);
61
62
static const char *
63 356096
is_dup_filter(const struct vfilter_head *head, const struct vfp * vfp,
64
    const struct vdp *vdp, const char *name)
65
{
66
        struct vfilter *vp;
67 1720072
        VTAILQ_FOREACH(vp, head, list) {
68 1364016
                if (vfp != NULL && vp->vfp != NULL) {
69 417960
                        if (vp->vfp == vfp)
70 40
                                return ("VFP already registered");
71 417920
                        if (!strcasecmp(vp->name, name))
72 0
                                return ("VFP name already used");
73 417920
                }
74 1363976
                if (vdp != NULL && vp->vdp != NULL) {
75 287976
                        if (vp->vdp == vdp)
76 0
                                return ("VDP already registered");
77 287976
                        if (!strcasecmp(vp->name, name))
78 0
                                return ("VDP name already used");
79 287976
                }
80 1363976
        }
81 356056
        return (NULL);
82 356096
}
83
84
static const char *
85 326656
vrt_addfilter(VRT_CTX, const struct vfp *vfp, const struct vdp *vdp)
86
{
87
        struct vfilter *vp;
88 326656
        struct vfilter_head *hd = &vrt_filters;
89 326656
        const char *err, *name = NULL;
90
91 326656
        CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC);
92 326656
        assert(vfp != NULL || vdp != NULL);
93 326656
        assert(vfp == NULL || vfp->name != NULL);
94 326656
        assert(vdp == NULL || vdp->name != NULL);
95 326656
        assert(vfp == NULL || vdp == NULL || !strcasecmp(vfp->name, vdp->name));
96 326656
        if (vfp != NULL)
97 194200
                name = vfp->name;
98 132456
        else if (vdp != NULL)
99 132456
                name = vdp->name;
100 326656
        AN(name);
101
102 326656
        err = is_dup_filter(hd, vfp, vdp, name);
103 326656
        if (err != NULL) {
104 0
                if (ctx != NULL)
105 0
                        VRT_fail(ctx, "%s: %s (global)", name, err);
106 0
                return (err);
107
        }
108 326656
        if (ctx != NULL) {
109 29440
                ASSERT_CLI();
110 29440
                CHECK_OBJ_NOTNULL(ctx->vcl, VCL_MAGIC);
111 29440
                hd = &ctx->vcl->filters;
112 29440
                err = is_dup_filter(hd, vfp, vdp, name);
113 29440
                if (err != NULL) {
114 40
                        VRT_fail(ctx, "%s: %s (per-vcl)", name, err);
115 40
                        return (err);
116
                }
117 29400
        }
118
119 326616
        ALLOC_OBJ(vp, VFILTER_MAGIC);
120 326616
        AN(vp);
121 326616
        vp->vfp = vfp;
122 326616
        vp->vdp = vdp;
123 326616
        vp->name = name;
124 326616
        vp->nlen = strlen(name);
125 326616
        VTAILQ_INSERT_TAIL(hd, vp, list);
126 326616
        return (err);
127 326656
}
128
129
const char *
130 29440
VRT_AddFilter(VRT_CTX, const struct vfp *vfp, const struct vdp *vdp)
131
{
132
133 29440
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
134 29440
        return (vrt_addfilter(ctx, vfp, vdp));
135
}
136
137
void
138 0
VRT_AddVFP(VRT_CTX, const struct vfp *filter)
139
{
140 0
        AZ(VRT_AddFilter(ctx, filter, NULL));
141 0
}
142
143
void
144 0
VRT_AddVDP(VRT_CTX, const struct vdp *filter)
145
{
146 0
        AZ(VRT_AddFilter(ctx, NULL, filter));
147 0
}
148
149
void
150 6440
VRT_RemoveFilter(VRT_CTX, const struct vfp *vfp, const struct vdp *vdp)
151
{
152
        struct vfilter *vp;
153
        struct vfilter_head *hd;
154
155 6440
        CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
156 6440
        CHECK_OBJ_NOTNULL(ctx->vcl, VCL_MAGIC);
157 6440
        hd = &ctx->vcl->filters;
158 6440
        assert(vfp != NULL || vdp != NULL);
159 6440
        assert(vfp == NULL || vfp->name != NULL);
160 6440
        assert(vdp == NULL || vdp->name != NULL);
161 6440
        assert(vfp == NULL || vdp == NULL || !strcasecmp(vfp->name, vdp->name));
162
163 6440
        ASSERT_CLI();
164 9200
        VTAILQ_FOREACH(vp, hd, list) {
165 9200
                CHECK_OBJ_NOTNULL(vp, VFILTER_MAGIC);
166 9200
                if (vp->vfp == vfp && vp->vdp == vdp)
167 6440
                        break;
168 2760
        }
169 6440
        AN(vp);
170 6440
        assert(vfp == NULL || !strcasecmp(vfp->name, vp->name));
171 6440
        assert(vdp == NULL || !strcasecmp(vdp->name, vp->name));
172 6440
        VTAILQ_REMOVE(hd, vp, list);
173 6440
        FREE_OBJ(vp);
174 6440
}
175
176
void
177 0
VRT_RemoveVFP(VRT_CTX, const struct vfp *filter)
178
{
179
180 0
        VRT_RemoveFilter(ctx, filter, NULL);
181 0
}
182
183
void
184 0
VRT_RemoveVDP(VRT_CTX, const struct vdp *filter)
185
{
186
187 0
        VRT_RemoveFilter(ctx, NULL, filter);
188 0
}
189
190
static const struct vfilter vfilter_error[1] = {{0}};
191
192
static const struct vfilter *
193 262124
vcl_filter_list_iter(int want_vfp, const struct vfilter_head *h1,
194
    const struct vfilter_head *h2, const char **flp)
195
{
196
        const char *fl, *q;
197
        const struct vfilter *vp;
198
199 262124
        AN(h1);
200 262124
        AN(h2);
201 262124
        AN(flp);
202
203 262124
        fl = *flp;
204 262124
        AN(fl);
205
206 305479
        while (vct_isspace(*fl))
207 43355
                fl++;
208 262124
        if (*fl == '\0') {
209 217164
                *flp = NULL;
210 217164
                return (NULL);
211
        }
212 372495
        for (q = fl; *q && !vct_isspace(*q); q++)
213 327535
                continue;
214 44960
        *flp = q;
215 265110
        VTAILQ_FOREACH(vp, h1, list) {
216 252790
                if (want_vfp && vp->vfp == NULL)
217 1560
                        continue;
218 251230
                else if (!want_vfp && vp->vdp == NULL)
219 126590
                        continue;
220 124640
                if (vp->nlen == q - fl && !memcmp(fl, vp->name, vp->nlen))
221 32640
                        return (vp);
222 92000
        }
223 26440
        VTAILQ_FOREACH(vp, h2, list) {
224 26320
                if (want_vfp && vp->vfp == NULL)
225 400
                        continue;
226 25920
                else if (!want_vfp && vp->vdp == NULL)
227 0
                        continue;
228 25920
                if (vp->nlen == q - fl && !memcmp(fl, vp->name, vp->nlen))
229 12200
                        return (vp);
230 13720
        }
231 120
        *flp = fl;
232 120
        return (vfilter_error);
233 262124
}
234
235
int
236 76796
VCL_StackVFP(struct vfp_ctx *vc, const struct vcl *vcl, const char *fl)
237
{
238
        const struct vfilter *vp;
239
240 76796
        AN(fl);
241 76796
        VSLbs(vc->wrk->vsl, SLT_Filters, TOSTRAND(fl));
242
243 95476
        while (1) {
244 95476
                vp = vcl_filter_list_iter(1, &vrt_filters, &vcl->filters, &fl);
245 95476
                if (vp == NULL)
246 75836
                        return (0);
247 19640
                if (vp == vfilter_error)
248 80
                        return (VFP_Error(vc, "Filter '...%s' not found", fl));
249 19560
                if (VFP_Push(vc, vp->vfp) == NULL)
250 880
                        return (-1);
251
        }
252 76796
}
253
254
int
255 143849
VCL_StackVDP(struct vdp_ctx *vdc, const struct vcl *vcl, const char *fl,
256
    struct req *req, struct busyobj *bo)
257
{
258
        const struct vfilter *vp;
259
        struct vrt_ctx ctx[1];
260
261 143849
        CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC);
262 143849
        AN(vcl);
263 143849
        AN(fl);
264
265 143849
        CHECK_OBJ_ORNULL(req, REQ_MAGIC);
266 143849
        CHECK_OBJ_ORNULL(bo, BUSYOBJ_MAGIC);
267
268 143849
        assert((req ? 1 : 0) ^ (bo ? 1 : 0));
269
270 143849
        VSLbs(vdc->vsl, SLT_Filters, TOSTRAND(fl));
271 143849
        INIT_OBJ(ctx, VRT_CTX_MAGIC);
272
273 143849
        if (req)
274 143569
                VCL_Req2Ctx(ctx, req);
275
        else
276 280
                VCL_Bo2Ctx(ctx, bo);
277
278 166648
        while (1) {
279 166648
                vp = vcl_filter_list_iter(0, &vrt_filters, &vcl->filters, &fl);
280 166648
                if (vp == NULL)
281 141329
                        return (0);
282 25319
                if (vp == vfilter_error) {
283 80
                        VSLb(ctx->vsl, SLT_Error,
284 40
                            "Filter '...%s' not found", fl);
285 40
                        return (-1);
286
                }
287 25279
                if (VDP_Push(ctx, vdc, ctx->ws, vp->vdp, NULL))
288 2480
                        return (-1);
289
        }
290 143849
}
291
292
void
293 37152
VCL_VRT_Init(void)
294
{
295 37152
        AZ(vrt_addfilter(NULL, &VFP_testgunzip, NULL));
296 37152
        AZ(vrt_addfilter(NULL, &VFP_gunzip, NULL));
297 37152
        AZ(vrt_addfilter(NULL, &VFP_gzip, NULL));
298 37152
        AZ(vrt_addfilter(NULL, &VFP_esi, NULL));
299 37152
        AZ(vrt_addfilter(NULL, &VFP_esi_gzip, NULL));
300 37152
        AZ(vrt_addfilter(NULL, NULL, &VDP_esi));
301 37152
        AZ(vrt_addfilter(NULL, NULL, &VDP_gunzip));
302 37152
        AZ(vrt_addfilter(NULL, NULL, &VDP_range));
303 37152
}
304
305
/*--------------------------------------------------------------------
306
 */
307
308
typedef void filter_list_t(void *, struct vsb *vsb);
309
310
static const char *
311 192118
filter_on_ws(struct ws *ws, filter_list_t *func, void *arg)
312
{
313
        struct vsb vsb[1];
314
        const char *p;
315
316 192118
        AN(func);
317 192118
        AN(arg);
318 192118
        WS_VSB_new(vsb, ws);
319 192118
        func(arg, vsb);
320 192118
        p = WS_VSB_finish(vsb, ws, NULL);
321 192118
        if (p == NULL)
322 920
                p = "";
323 192118
        return (p);
324
}
325
326
/*--------------------------------------------------------------------
327
 */
328
329
static void v_matchproto_(filter_list_t)
330 47797
vbf_default_filter_list(void *arg, struct vsb *vsb)
331
{
332
        const struct busyobj *bo;
333
        const char *p;
334 47797
        int do_gzip, do_gunzip, is_gzip = 0, is_gunzip = 0;
335
336 47797
        CAST_OBJ_NOTNULL(bo, arg, BUSYOBJ_MAGIC);
337
338 47797
        do_gzip = bo->do_gzip;
339 47797
        do_gunzip = bo->do_gunzip;
340
341
        /*
342
         * The VCL variables beresp.do_g[un]zip tells us how we want the
343
         * object processed before it is stored.
344
         *
345
         * The backend Content-Encoding header tells us what we are going
346
         * to receive, which we classify in the following three classes:
347
         *
348
         *      "Content-Encoding: gzip"        --> object is gzipped.
349
         *      no Content-Encoding             --> object is not gzipped.
350
         *      anything else                   --> do nothing wrt gzip
351
         */
352
353
        /* No body -> done */
354 47797
        if (bo->htc->body_status == BS_NONE || bo->htc->content_length == 0)
355 4
                return;
356
357 47795
        if (!cache_param->http_gzip_support)
358 160
                do_gzip = do_gunzip = 0;
359
360 47795
        if (http_GetHdr(bo->beresp, H_Content_Encoding, &p))
361 8000
                is_gzip = !strcasecmp(p, "gzip");
362
        else
363 39795
                is_gunzip = 1;
364
365
        /* We won't gunzip unless it is gzipped */
366 47795
        if (do_gunzip && !is_gzip)
367 80
                do_gunzip = 0;
368
369
        /* We wont gzip unless if it already is gzipped */
370 47795
        if (do_gzip && !is_gunzip)
371 0
                do_gzip = 0;
372
373 47795
        if (do_gunzip || (is_gzip && bo->do_esi))
374 6360
                VSB_cat(vsb, " gunzip");
375
376 47795
        if (bo->do_esi && (do_gzip || (is_gzip && !do_gunzip))) {
377 6480
                VSB_cat(vsb, " esi_gzip");
378 6480
                return;
379
        }
380
381 41315
        if (bo->do_esi) {
382 6000
                VSB_cat(vsb, " esi");
383 6000
                return;
384
        }
385
386 35315
        if (do_gzip)
387 640
                VSB_cat(vsb, " gzip");
388
389 35315
        if (is_gzip && !do_gunzip)
390 1640
                VSB_cat(vsb, " testgunzip");
391 47795
}
392
393
const char *
394 47796
VBF_Get_Filter_List(struct busyobj *bo)
395
{
396
397 47796
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
398 47796
        return (filter_on_ws(bo->ws, vbf_default_filter_list, bo));
399
}
400
401
static const char *
402 40
bereq_Empty_Filter(struct busyobj *bo)
403
{
404
405 40
        CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
406 40
        return ("");
407
}
408
409
/*--------------------------------------------------------------------
410
 */
411
412
static void v_matchproto_(filter_list_t)
413 144326
resp_default_filter_list(void *arg, struct vsb *vsb)
414
{
415
        struct req *req;
416
417 144326
        CAST_OBJ_NOTNULL(req, arg, REQ_MAGIC);
418
419 144326
        if (!req->disable_esi && req->objcore != NULL &&
420 143730
            ObjHasAttr(req->wrk, req->objcore, OA_ESIDATA))
421 8999
                VSB_cat(vsb, " esi");
422
423 154686
        if (cache_param->http_gzip_support &&
424 144007
            req->objcore != NULL &&
425 143927
            ObjCheckFlag(req->wrk, req->objcore, OF_GZIPED) &&
426 10360
            !RFC2616_Req_Gzip(req->http))
427 3440
                VSB_cat(vsb, " gunzip");
428
429 263855
        if (cache_param->http_range_support &&
430 144167
            http_GetStatus(req->resp) == 200 &&
431 119529
            http_GetHdr(req->http, H_Range, NULL))
432 2280
                VSB_cat(vsb, " range");
433 144326
}
434
435
const char *
436 144336
resp_Get_Filter_List(struct req *req)
437
{
438
439 144336
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
440 144336
        return (filter_on_ws(req->ws, resp_default_filter_list, req));
441
}
442
443
static const char *
444 80
req_Empty_Filter(struct req *req)
445
{
446
447 80
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
448 80
        return ("");
449
}
450
451
/*--------------------------------------------------------------------
452
 * control if "set req.filters" is allowed
453
 *
454
 * req.body (conversely to other body object) is one where VCL has control over
455
 * when it gets processed by means of std.cache_req_body(): Filters act on the
456
 * received body when that function is called, so confusion could be caused if
457
 * people expect filters to have an effect when set/changed after the req.body
458
 * is already cached.
459
 */
460
461
static int
462 400
req_filter_can(struct req *req)
463
{
464
465 400
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
466 400
        return (req->req_body_status->avail == 1);
467
}
468
469
/*--------------------------------------------------------------------*/
470
471
//lint -emacro(506, FILTER_VAR) constant value boolean
472
//lint -emacro(774, FILTER_VAR) if always evaluates to false
473
#define FILTER_VAR(vcl, in, func, cond, fld)                            \
474
        VCL_STRING                                                      \
475
        VRT_r_##vcl##_filters(VRT_CTX)                                  \
476
        {                                                               \
477
                                                                        \
478
                CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
479
                if (ctx->in->fld != NULL)                               \
480
                        return(ctx->in->fld);                           \
481
                return (func(ctx->in));                                 \
482
        }                                                               \
483
                                                                        \
484
        VCL_VOID                                                        \
485
        VRT_l_##vcl##_filters(VRT_CTX, const char *str, VCL_STRANDS s)  \
486
        {                                                               \
487
                const char *b;                                          \
488
                                                                        \
489
                (void)str;                                              \
490
                CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);                  \
491
                if (! (cond)) {                                         \
492
                        VRT_fail(ctx, #vcl ".filters not settable");    \
493
                        return;                                         \
494
                }                                                       \
495
                b = VRT_StrandsWS(ctx->in->ws, str, s);                 \
496
                if (b == NULL)                                          \
497
                        WS_MarkOverflow(ctx->in->ws);                   \
498
                else                                                    \
499
                        ctx->in->fld = b;                               \
500
        }
501
502 320
FILTER_VAR(bereq, bo, bereq_Empty_Filter, 1, vdp_filter_list)
503 1680
FILTER_VAR(beresp, bo, VBF_Get_Filter_List, 1, vfp_filter_list)
504 480
FILTER_VAR(req, req, req_Empty_Filter, req_filter_can(ctx->req), vfp_filter_list)
505 22560
FILTER_VAR(resp, req, resp_Get_Filter_List, 1, vdp_filter_list)