varnish-cache/lib/libvarnishapi/vsl.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
 * Author: Martin Blix Grydeland <martin@varnish-software.com>
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
#include "config.h"
32
33
#include <errno.h>
34
#include <stdarg.h>
35
#include <stdint.h>
36
#include <stdio.h>
37
38
#include "vdef.h"
39
#include "vas.h"
40
#include "miniobj.h"
41
42
#include "vbm.h"
43
#include "vqueue.h"
44
#include "vre.h"
45
#include "vsb.h"
46
47
#include "vapi/vsl.h"
48
49
#include "vsl_api.h"
50
51
/*--------------------------------------------------------------------*/
52
53
const char * const VSL_tags[SLT__MAX] = {
54
#  define SLTM(foo,flags,sdesc,ldesc)       [SLT_##foo] = #foo,
55
#  include "tbl/vsl_tags.h"
56
};
57
58
const unsigned VSL_tagflags[SLT__MAX] = {
59
#  define SLTM(foo, flags, sdesc, ldesc)        [SLT_##foo] = flags,
60
#  include "tbl/vsl_tags.h"
61
#  undef SLTM
62
};
63
64
int
65 97820
vsl_diag(struct VSL_data *vsl, const char *fmt, ...)
66
{
67
        va_list ap;
68
69 97820
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
70 97820
        AN(fmt);
71
72 97820
        if (vsl->diag == NULL)
73 97820
                vsl->diag = VSB_new_auto();
74 97820
        AN(vsl->diag);
75 97820
        VSB_clear(vsl->diag);
76 97820
        va_start(ap, fmt);
77 97820
        VSB_vprintf(vsl->diag, fmt, ap);
78 97820
        va_end(ap);
79 97820
        AZ(VSB_finish(vsl->diag));
80 97820
        return (-1);
81
}
82
83
struct VSL_data *
84 3772
VSL_New(void)
85
{
86
        struct VSL_data *vsl;
87
88 3772
        ALLOC_OBJ(vsl, VSL_MAGIC);
89 3772
        if (vsl == NULL)
90 0
                return (NULL);
91
92 3772
        vsl->L_opt = 1000;
93 3772
        vsl->T_opt = 120.;
94 3772
        vsl->vbm_select = vbit_new(SLT__MAX);
95 3772
        vsl->vbm_supress = vbit_new(SLT__MAX);
96 3772
        VTAILQ_INIT(&vsl->vslf_select);
97 3772
        VTAILQ_INIT(&vsl->vslf_suppress);
98
99 3772
        return (vsl);
100
}
101
102
static void
103 6824
vsl_IX_free(vslf_list *filters)
104
{
105
        struct vslf *vslf;
106
107 13664
        while (!VTAILQ_EMPTY(filters)) {
108 16
                vslf = VTAILQ_FIRST(filters);
109 16
                CHECK_OBJ_NOTNULL(vslf, VSLF_MAGIC);
110 16
                VTAILQ_REMOVE(filters, vslf, list);
111 16
                if (vslf->tags)
112 0
                        vbit_destroy(vslf->tags);
113 16
                AN(vslf->vre);
114 16
                VRE_free(&vslf->vre);
115 16
                AZ(vslf->vre);
116 16
                FREE_OBJ(vslf);
117
        }
118 6824
}
119
120
void
121 3412
VSL_Delete(struct VSL_data *vsl)
122
{
123
124 3412
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
125
126 3412
        vbit_destroy(vsl->vbm_select);
127 3412
        vbit_destroy(vsl->vbm_supress);
128 3412
        vsl_IX_free(&vsl->vslf_select);
129 3412
        vsl_IX_free(&vsl->vslf_suppress);
130 3412
        VSL_ResetError(vsl);
131 3412
        FREE_OBJ(vsl);
132 3412
}
133
134
const char *
135 97820
VSL_Error(const struct VSL_data *vsl)
136
{
137
138 97820
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
139
140 97820
        if (vsl->diag == NULL)
141 0
                return (NULL);
142
        else
143 97820
                return (VSB_data(vsl->diag));
144
}
145
146
void
147 101156
VSL_ResetError(struct VSL_data *vsl)
148
{
149
150 101156
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
151
152 101156
        if (vsl->diag == NULL)
153 3412
                return;
154 97744
        VSB_destroy(&vsl->diag);
155
}
156
157
static int
158 336
vsl_match_IX(struct VSL_data *vsl, const vslf_list *list,
159
    const struct VSL_cursor *c)
160
{
161
        enum VSL_tag_e tag;
162
        const char *cdata;
163
        int len;
164
        const struct vslf *vslf;
165
166
        (void)vsl;
167 336
        tag = VSL_TAG(c->rec.ptr);
168 336
        cdata = VSL_CDATA(c->rec.ptr);
169 336
        len = VSL_LEN(c->rec.ptr);
170
171 644
        VTAILQ_FOREACH(vslf, list, list) {
172 336
                CHECK_OBJ_NOTNULL(vslf, VSLF_MAGIC);
173 336
                if (vslf->tags != NULL && !vbit_test(vslf->tags, tag))
174 0
                        continue;
175 336
                if (VRE_exec(vslf->vre, cdata, len, 0, 0, NULL, 0, NULL) >= 0)
176 28
                        return (1);
177
        }
178 308
        return (0);
179
}
180
181
int
182 52646
VSL_Match(struct VSL_data *vsl, const struct VSL_cursor *c)
183
{
184
        enum VSL_tag_e tag;
185
186 52646
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
187 52646
        if (c == NULL || c->rec.ptr == NULL)
188 0
                return (0);
189 52646
        tag = VSL_TAG(c->rec.ptr);
190 52646
        if (tag <= SLT__Bogus || tag >= SLT__Reserved)
191 0
                return (0);
192 52646
        if (vsl->c_opt && !VSL_CLIENT(c->rec.ptr))
193 0
                return (0);
194 52646
        if (vsl->b_opt && !VSL_BACKEND(c->rec.ptr))
195 0
                return (0);
196 52914
        if (!VTAILQ_EMPTY(&vsl->vslf_select) &&
197 268
            vsl_match_IX(vsl, &vsl->vslf_select, c))
198 4
                return (1);
199 52642
        else if (vbit_test(vsl->vbm_select, tag))
200 0
                return (1);
201 52715
        else if (!VTAILQ_EMPTY(&vsl->vslf_suppress) &&
202 68
            vsl_match_IX(vsl, &vsl->vslf_suppress, c))
203 24
                return (0);
204 52623
        else if (vbit_test(vsl->vbm_supress, tag))
205 1492
                return (0);
206
207
        /* Default show */
208 51138
        return (1);
209
}
210
211
static const char * const VSL_transactions[VSL_t__MAX] = {
212
        /*                 12345678901234 */
213
        [VSL_t_unknown] = "<< Unknown  >>",
214
        [VSL_t_sess]    = "<< Session  >>",
215
        [VSL_t_req]     = "<< Request  >>",
216
        [VSL_t_bereq]   = "<< BeReq    >>",
217
        [VSL_t_raw]     = "<< Record   >>",
218
};
219
220
#define VSL_PRINT(...)                                  \
221
        do {                                            \
222
                if (0 > fprintf(__VA_ARGS__))           \
223
                        return (-5);                    \
224
        } while (0)
225
226
static int
227 56
vsl_print_unsafe(FILE *fo, unsigned len, const char *data)
228
{
229
230 56
        VSL_PRINT(fo, "\"");
231 2996
        while (len-- > 0) {
232 2884
                if (*data >= ' ' && *data <= '~')
233 2828
                        VSL_PRINT(fo, "%c", *data);
234
                else
235 56
                        VSL_PRINT(fo, "%%%02x", (unsigned char)*data);
236 2884
                data++;
237
        }
238 56
        VSL_PRINT(fo, "\"\n");
239 56
        return (0);
240
}
241
242
243
static int
244 88
vsl_print_binary(FILE *fo, unsigned len, const char *data)
245
{
246
247 88
        VSL_PRINT(fo, "[");
248 2124
        while (len-- > 0) {
249 1948
                VSL_PRINT(fo, "%02x", (unsigned char)*data);
250 1948
                data++;
251
        }
252 88
        VSL_PRINT(fo, "]\n");
253 88
        return (0);
254
}
255
256
static int
257 788
vsl_print(const struct VSL_data *vsl, const struct VSL_cursor *c, void *fo,
258
    int terse)
259
{
260
        enum VSL_tag_e tag;
261
        uint32_t vxid;
262
        unsigned len;
263
        const char *data;
264
        int type;
265
266 788
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
267 788
        if (c == NULL || c->rec.ptr == NULL)
268 0
                return (0);
269 788
        if (fo == NULL)
270 0
                fo = stdout;
271 788
        tag = VSL_TAG(c->rec.ptr);
272 788
        vxid = VSL_ID(c->rec.ptr);
273 788
        len = VSL_LEN(c->rec.ptr);
274 1116
        type = VSL_CLIENT(c->rec.ptr) ? 'c' : VSL_BACKEND(c->rec.ptr) ?
275 328
            'b' : '-';
276 788
        data = VSL_CDATA(c->rec.ptr);
277
278 788
        if (!terse)
279 512
                VSL_PRINT(fo, "%10u ", vxid);
280 788
        VSL_PRINT(fo, "%-14s ", VSL_tags[tag]);
281 788
        if (!terse)
282 512
                VSL_PRINT(fo, "%c ", type);
283
284 788
        if (VSL_tagflags[tag] & SLT_F_UNSAFE)
285 56
                (void)vsl_print_unsafe(fo, len, data);
286 732
        else if (VSL_tagflags[tag] & SLT_F_BINARY)
287 88
                (void)vsl_print_binary(fo, len, data);
288
        else
289 644
                VSL_PRINT(fo, "%.*s\n", (int)len, data);
290
291 788
        return (0);
292
}
293
294
int
295 512
VSL_Print(const struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
296
{
297
298 512
        return (vsl_print(vsl, c, fo, 0));
299
}
300
301
int
302 276
VSL_PrintTerse(const struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
303
{
304
305 276
        return (vsl_print(vsl, c, fo, 1));
306
}
307
308
int
309 0
VSL_PrintAll(struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
310
{
311
        int i;
312
313 0
        if (c == NULL)
314 0
                return (0);
315
        while (1) {
316 0
                i = VSL_Next(c);
317 0
                if (i <= 0)
318 0
                        return (i);
319 0
                if (!VSL_Match(vsl, c))
320 0
                        continue;
321 0
                i = VSL_Print(vsl, c, fo);
322 0
                if (i != 0)
323 0
                        return (i);
324
        }
325
}
326
327
int v_matchproto_(VSLQ_dispatch_f)
328 704
VSL_PrintTransactions(struct VSL_data *vsl, struct VSL_transaction * const pt[],
329
    void *fo)
330
{
331
        struct VSL_transaction *t;
332
        int i;
333 704
        int delim = 0;
334
        int verbose;
335
336 704
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
337 704
        if (fo == NULL)
338 240
                fo = stdout;
339 704
        if (pt[0] == NULL)
340 0
                return (0);
341
342 1408
        for (t = pt[0]; t != NULL; t = *++pt) {
343 704
                if (vsl->c_opt || vsl->b_opt) {
344 12
                        switch (t->type) {
345
                        case VSL_t_req:
346 4
                                if (!vsl->c_opt)
347 4
                                        continue;
348 0
                                break;
349
                        case VSL_t_bereq:
350 4
                                if (!vsl->b_opt)
351 0
                                        continue;
352 4
                                break;
353
                        case VSL_t_raw:
354 0
                                break;
355
                        default:
356 4
                                continue;
357
                        }
358
                }
359
360 696
                verbose = 0;
361 696
                if (t->level == 0 || vsl->v_opt)
362 680
                        verbose = 1;
363
364 696
                if (t->level) {
365
                        /* Print header */
366 20
                        if (t->level > 3)
367 0
                                VSL_PRINT(fo, "*%1.1u* ", t->level);
368
                        else
369 20
                                VSL_PRINT(fo, "%-3.*s ",
370
                                    (int)(t->level), "***");
371 20
                        VSL_PRINT(fo, "%*.s%-14s %*.s%-10u\n",
372
                            verbose ? 10 + 1 : 0, " ",
373
                            VSL_transactions[t->type],
374
                            verbose ? 1 + 1 : 0, " ",
375
                            t->vxid);
376 20
                        delim = 1;
377
                }
378
379
                while (1) {
380
                        /* Print records */
381 3112
                        i = VSL_Next(t->c);
382 1904
                        if (i < 0)
383 0
                                return (i);
384 1904
                        if (i == 0)
385 696
                                break;
386 1208
                        if (!VSL_Match(vsl, t->c))
387 420
                                continue;
388 788
                        if (t->level > 3)
389 0
                                VSL_PRINT(fo, "-%1.1u- ", t->level);
390 788
                        else if (t->level)
391 280
                                VSL_PRINT(fo, "%-3.*s ",
392
                                    (int)(t->level), "---");
393 788
                        if (verbose)
394 512
                                i = VSL_Print(vsl, t->c, fo);
395
                        else
396 276
                                i = VSL_PrintTerse(vsl, t->c, fo);
397 788
                        if (i != 0)
398 0
                                return (i);
399
                }
400
        }
401
402 704
        if (delim)
403 20
                VSL_PRINT(fo, "\n");;
404
405 704
        return (0);
406
}
407
408
FILE*
409 12
VSL_WriteOpen(struct VSL_data *vsl, const char *name, int append, int unbuf)
410
{
411 12
        const char head[] = VSL_FILE_ID;
412
        FILE* f;
413 12
        f = fopen(name, append ? "a" : "w");
414 12
        if (f == NULL) {
415 4
                vsl_diag(vsl, "%s", strerror(errno));
416 4
                return (NULL);
417
        }
418 8
        if (unbuf)
419 0
                setbuf(f, NULL);
420 8
        if (0 == ftell(f)) {
421 8
                if (fwrite(head, 1, sizeof head, f) != sizeof head) {
422 0
                        vsl_diag(vsl, "%s", strerror(errno));
423 0
                        (void)fclose(f);
424 0
                        return (NULL);
425
                }
426
        }
427 8
        return (f);
428
}
429
430
int
431 552
VSL_Write(const struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
432
{
433
        size_t r;
434
435 552
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
436 552
        if (c == NULL || c->rec.ptr == NULL)
437 0
                return (0);
438 552
        if (fo == NULL)
439 0
                fo = stdout;
440 552
        r = fwrite(c->rec.ptr, sizeof *c->rec.ptr,
441 552
            VSL_NEXT(c->rec.ptr) - c->rec.ptr, fo);
442 552
        if (r == 0)
443 0
                return (-5);
444 552
        return (0);
445
}
446
447
int
448 24
VSL_WriteAll(struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
449
{
450
        int i;
451
452 24
        if (c == NULL)
453 0
                return (0);
454
        while (1) {
455 1128
                i = VSL_Next(c);
456 576
                if (i <= 0)
457 24
                        return (i);
458 552
                if (!VSL_Match(vsl, c))
459 0
                        continue;
460 552
                i = VSL_Write(vsl, c, fo);
461 552
                if (i != 0)
462 0
                        return (i);
463
        }
464
}
465
466
int v_matchproto_(VSLQ_dispatch_f)
467 24
VSL_WriteTransactions(struct VSL_data *vsl, struct VSL_transaction * const pt[],
468
    void *fo)
469
{
470
        struct VSL_transaction *t;
471
        int i;
472
473 24
        if (pt == NULL)
474 0
                return (0);
475 48
        for (i = 0, t = pt[0]; i == 0 && t != NULL; t = *++pt)
476 24
                i = VSL_WriteAll(vsl, t->c, fo);
477 24
        return (i);
478
}