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 71103
vsl_diag(struct VSL_data *vsl, const char *fmt, ...)
66
{
67
        va_list ap;
68
69 71103
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
70 71103
        AN(fmt);
71
72 71103
        if (vsl->diag == NULL)
73 71103
                vsl->diag = VSB_new_auto();
74 71103
        AN(vsl->diag);
75 71103
        VSB_clear(vsl->diag);
76 71103
        va_start(ap, fmt);
77 71103
        VSB_vprintf(vsl->diag, fmt, ap);
78 71103
        va_end(ap);
79 71103
        AZ(VSB_finish(vsl->diag));
80 71103
        return (-1);
81
}
82
83
struct VSL_data *
84 2781
VSL_New(void)
85
{
86
        struct VSL_data *vsl;
87
88 2781
        ALLOC_OBJ(vsl, VSL_MAGIC);
89 2781
        if (vsl == NULL)
90 0
                return (NULL);
91
92 2781
        vsl->L_opt = 1000;
93 2781
        vsl->T_opt = 120.;
94 2781
        vsl->vbm_select = vbit_new(SLT__MAX);
95 2781
        vsl->vbm_supress = vbit_new(SLT__MAX);
96 2781
        VTAILQ_INIT(&vsl->vslf_select);
97 2781
        VTAILQ_INIT(&vsl->vslf_suppress);
98
99 2781
        return (vsl);
100
}
101
102
static void
103 5076
vsl_IX_free(vslf_list *filters)
104
{
105
        struct vslf *vslf;
106
107 10164
        while (!VTAILQ_EMPTY(filters)) {
108 12
                vslf = VTAILQ_FIRST(filters);
109 12
                CHECK_OBJ_NOTNULL(vslf, VSLF_MAGIC);
110 12
                VTAILQ_REMOVE(filters, vslf, list);
111 12
                if (vslf->tags)
112 0
                        vbit_destroy(vslf->tags);
113 12
                AN(vslf->vre);
114 12
                VRE_free(&vslf->vre);
115 12
                AZ(vslf->vre);
116 12
                FREE_OBJ(vslf);
117
        }
118 5076
}
119
120
void
121 2538
VSL_Delete(struct VSL_data *vsl)
122
{
123
124 2538
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
125
126 2538
        vbit_destroy(vsl->vbm_select);
127 2538
        vbit_destroy(vsl->vbm_supress);
128 2538
        vsl_IX_free(&vsl->vslf_select);
129 2538
        vsl_IX_free(&vsl->vslf_suppress);
130 2538
        VSL_ResetError(vsl);
131 2538
        FREE_OBJ(vsl);
132 2538
}
133
134
const char *
135 71103
VSL_Error(const struct VSL_data *vsl)
136
{
137
138 71103
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
139
140 71103
        if (vsl->diag == NULL)
141 0
                return (NULL);
142
        else
143 71103
                return (VSB_data(vsl->diag));
144
}
145
146
void
147 73584
VSL_ResetError(struct VSL_data *vsl)
148
{
149
150 73584
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
151
152 73584
        if (vsl->diag == NULL)
153 2538
                return;
154 71046
        VSB_destroy(&vsl->diag);
155
}
156
157
static int
158 252
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 252
        tag = VSL_TAG(c->rec.ptr);
168 252
        cdata = VSL_CDATA(c->rec.ptr);
169 252
        len = VSL_LEN(c->rec.ptr);
170
171 483
        VTAILQ_FOREACH(vslf, list, list) {
172 252
                CHECK_OBJ_NOTNULL(vslf, VSLF_MAGIC);
173 252
                if (vslf->tags != NULL && !vbit_test(vslf->tags, tag))
174 0
                        continue;
175 252
                if (VRE_exec(vslf->vre, cdata, len, 0, 0, NULL, 0, NULL) >= 0)
176 21
                        return (1);
177
        }
178 231
        return (0);
179
}
180
181
int
182 38876
VSL_Match(struct VSL_data *vsl, const struct VSL_cursor *c)
183
{
184
        enum VSL_tag_e tag;
185
186 38876
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
187 38876
        if (c == NULL || c->rec.ptr == NULL)
188 0
                return (0);
189 38876
        tag = VSL_TAG(c->rec.ptr);
190 38876
        if (tag <= SLT__Bogus || tag >= SLT__Reserved)
191 0
                return (0);
192 38876
        if (vsl->c_opt && !VSL_CLIENT(c->rec.ptr))
193 0
                return (0);
194 38876
        if (vsl->b_opt && !VSL_BACKEND(c->rec.ptr))
195 0
                return (0);
196 39077
        if (!VTAILQ_EMPTY(&vsl->vslf_select) &&
197 201
            vsl_match_IX(vsl, &vsl->vslf_select, c))
198 3
                return (1);
199 38873
        else if (vbit_test(vsl->vbm_select, tag))
200 0
                return (1);
201 38927
        else if (!VTAILQ_EMPTY(&vsl->vslf_suppress) &&
202 51
            vsl_match_IX(vsl, &vsl->vslf_suppress, c))
203 18
                return (0);
204 38858
        else if (vbit_test(vsl->vbm_supress, tag))
205 1119
                return (0);
206
207
        /* Default show */
208 37751
        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 63
vsl_print_unsafe(FILE *fo, unsigned len, const char *data)
228
{
229
230 63
        VSL_PRINT(fo, "\"");
231 2736
        while (len-- > 0) {
232 2610
                if (*data >= ' ' && *data <= '~')
233 2547
                        VSL_PRINT(fo, "%c", *data);
234
                else
235 63
                        VSL_PRINT(fo, "%%%02x", (unsigned char)*data);
236 2610
                data++;
237
        }
238 63
        VSL_PRINT(fo, "\"\n");
239 63
        return (0);
240
}
241
242
243
static int
244 72
vsl_print_binary(FILE *fo, unsigned len, const char *data)
245
{
246
247 72
        VSL_PRINT(fo, "[");
248 1644
        while (len-- > 0) {
249 1500
                VSL_PRINT(fo, "%02x", (unsigned char)*data);
250 1500
                data++;
251
        }
252 72
        VSL_PRINT(fo, "]\n");
253 72
        return (0);
254
}
255
256
static int
257 628
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 628
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
267 628
        if (c == NULL || c->rec.ptr == NULL)
268 0
                return (0);
269 628
        if (fo == NULL)
270 0
                fo = stdout;
271 628
        tag = VSL_TAG(c->rec.ptr);
272 628
        vxid = VSL_ID(c->rec.ptr);
273 628
        len = VSL_LEN(c->rec.ptr);
274 874
        type = VSL_CLIENT(c->rec.ptr) ? 'c' : VSL_BACKEND(c->rec.ptr) ?
275 246
            'b' : '-';
276 628
        data = VSL_CDATA(c->rec.ptr);
277
278 628
        if (!terse)
279 421
                VSL_PRINT(fo, "%10u ", vxid);
280 628
        VSL_PRINT(fo, "%-14s ", VSL_tags[tag]);
281 628
        if (!terse)
282 421
                VSL_PRINT(fo, "%c ", type);
283
284 628
        if (VSL_tagflags[tag] & SLT_F_UNSAFE)
285 63
                (void)vsl_print_unsafe(fo, len, data);
286 565
        else if (VSL_tagflags[tag] & SLT_F_BINARY)
287 72
                (void)vsl_print_binary(fo, len, data);
288
        else
289 493
                VSL_PRINT(fo, "%.*s\n", (int)len, data);
290
291 628
        return (0);
292
}
293
294
int
295 421
VSL_Print(const struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
296
{
297
298 421
        return (vsl_print(vsl, c, fo, 0));
299
}
300
301
int
302 207
VSL_PrintTerse(const struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
303
{
304
305 207
        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 565
VSL_PrintTransactions(struct VSL_data *vsl, struct VSL_transaction * const pt[],
329
    void *fo)
330
{
331
        struct VSL_transaction *t;
332
        int i;
333 565
        int delim = 0;
334
        int verbose;
335
336 565
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
337 565
        if (fo == NULL)
338 180
                fo = stdout;
339 565
        if (pt[0] == NULL)
340 0
                return (0);
341
342 1130
        for (t = pt[0]; t != NULL; t = *++pt) {
343 565
                if (vsl->c_opt || vsl->b_opt) {
344 9
                        switch (t->type) {
345
                        case VSL_t_req:
346 3
                                if (!vsl->c_opt)
347 3
                                        continue;
348 0
                                break;
349
                        case VSL_t_bereq:
350 3
                                if (!vsl->b_opt)
351 0
                                        continue;
352 3
                                break;
353
                        case VSL_t_raw:
354 0
                                break;
355
                        default:
356 3
                                continue;
357
                        }
358
                }
359
360 559
                verbose = 0;
361 559
                if (t->level == 0 || vsl->v_opt)
362 547
                        verbose = 1;
363
364 559
                if (t->level) {
365
                        /* Print header */
366 15
                        if (t->level > 3)
367 0
                                VSL_PRINT(fo, "*%1.1u* ", t->level);
368
                        else
369 15
                                VSL_PRINT(fo, "%-3.*s ",
370
                                    (int)(t->level), "***");
371 15
                        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 15
                        delim = 1;
377
                }
378
379
                while (1) {
380
                        /* Print records */
381 2445
                        i = VSL_Next(t->c);
382 1502
                        if (i < 0)
383 0
                                return (i);
384 1502
                        if (i == 0)
385 559
                                break;
386 943
                        if (!VSL_Match(vsl, t->c))
387 315
                                continue;
388 628
                        if (t->level > 3)
389 0
                                VSL_PRINT(fo, "-%1.1u- ", t->level);
390 628
                        else if (t->level)
391 210
                                VSL_PRINT(fo, "%-3.*s ",
392
                                    (int)(t->level), "---");
393 628
                        if (verbose)
394 421
                                i = VSL_Print(vsl, t->c, fo);
395
                        else
396 207
                                i = VSL_PrintTerse(vsl, t->c, fo);
397 628
                        if (i != 0)
398 0
                                return (i);
399
                }
400
        }
401
402 565
        if (delim)
403 15
                VSL_PRINT(fo, "\n");;
404
405 565
        return (0);
406
}
407
408
FILE*
409 9
VSL_WriteOpen(struct VSL_data *vsl, const char *name, int append, int unbuf)
410
{
411 9
        const char head[] = VSL_FILE_ID;
412
        FILE* f;
413 9
        f = fopen(name, append ? "a" : "w");
414 9
        if (f == NULL) {
415 3
                vsl_diag(vsl, "%s", strerror(errno));
416 3
                return (NULL);
417
        }
418 6
        if (unbuf)
419 0
                setbuf(f, NULL);
420 6
        if (0 == ftell(f)) {
421 6
                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 6
        return (f);
428
}
429
430
int
431 414
VSL_Write(const struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
432
{
433
        size_t r;
434
435 414
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
436 414
        if (c == NULL || c->rec.ptr == NULL)
437 0
                return (0);
438 414
        if (fo == NULL)
439 0
                fo = stdout;
440 414
        r = fwrite(c->rec.ptr, sizeof *c->rec.ptr,
441 414
            VSL_NEXT(c->rec.ptr) - c->rec.ptr, fo);
442 414
        if (r == 0)
443 0
                return (-5);
444 414
        return (0);
445
}
446
447
int
448 18
VSL_WriteAll(struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
449
{
450
        int i;
451
452 18
        if (c == NULL)
453 0
                return (0);
454
        while (1) {
455 846
                i = VSL_Next(c);
456 432
                if (i <= 0)
457 18
                        return (i);
458 414
                if (!VSL_Match(vsl, c))
459 0
                        continue;
460 414
                i = VSL_Write(vsl, c, fo);
461 414
                if (i != 0)
462 0
                        return (i);
463
        }
464
}
465
466
int v_matchproto_(VSLQ_dispatch_f)
467 18
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 18
        if (pt == NULL)
474 0
                return (0);
475 36
        for (i = 0, t = pt[0]; i == 0 && t != NULL; t = *++pt)
476 18
                i = VSL_WriteAll(vsl, t->c, fo);
477 18
        return (i);
478
}