varnish-cache/lib/libvarnishapi/vsl.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 * Author: Martin Blix Grydeland <martin@varnish-software.com>
7
 *
8
 * SPDX-License-Identifier: BSD-2-Clause
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 */
31
32
#include "config.h"
33
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                      vsl_file_id[] = {'V', 'S', 'L', '2'};
54
55
const char * const VSL_tags[SLT__MAX] = {
56
#  define SLTM(foo,flags,sdesc,ldesc)       [SLT_##foo] = #foo,
57
#  include "tbl/vsl_tags.h"
58
};
59
60
const unsigned VSL_tagflags[SLT__MAX] = {
61
#  define SLTM(foo, flags, sdesc, ldesc)        [SLT_##foo] = flags,
62
#  include "tbl/vsl_tags.h"
63
#  undef SLTM
64
};
65
66
int
67 165759
vsl_diag(struct VSL_data *vsl, const char *fmt, ...)
68
{
69
        va_list ap;
70
71 165759
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
72 165759
        AN(fmt);
73
74 165759
        if (vsl->diag == NULL)
75 165759
                vsl->diag = VSB_new_auto();
76 165759
        AN(vsl->diag);
77 165759
        VSB_clear(vsl->diag);
78 165759
        va_start(ap, fmt);
79 165759
        VSB_vprintf(vsl->diag, fmt, ap);
80 165759
        va_end(ap);
81 165759
        AZ(VSB_finish(vsl->diag));
82 165759
        return (-1);
83
}
84
85
struct VSL_data *
86 53920
VSL_New(void)
87
{
88
        struct VSL_data *vsl;
89
90 53920
        ALLOC_OBJ(vsl, VSL_MAGIC);
91 53920
        if (vsl == NULL)
92 0
                return (NULL);
93
94 53920
        vsl->L_opt = 1000;
95 53920
        vsl->T_opt = 120.;
96 53920
        vsl->vbm_select = vbit_new(SLT__MAX);
97 53920
        vsl->vbm_supress = vbit_new(SLT__MAX);
98 53920
        VTAILQ_INIT(&vsl->vslf_select);
99 53920
        VTAILQ_INIT(&vsl->vslf_suppress);
100
101 53920
        return (vsl);
102 53920
}
103
104
static void
105 96480
vsl_IX_free(vslf_list *filters)
106
{
107
        struct vslf *vslf;
108
109 96640
        while (!VTAILQ_EMPTY(filters)) {
110 160
                vslf = VTAILQ_FIRST(filters);
111 160
                CHECK_OBJ_NOTNULL(vslf, VSLF_MAGIC);
112 160
                VTAILQ_REMOVE(filters, vslf, list);
113 160
                if (vslf->tags)
114 0
                        vbit_destroy(vslf->tags);
115 160
                AN(vslf->vre);
116 160
                VRE_free(&vslf->vre);
117 160
                AZ(vslf->vre);
118 160
                FREE_OBJ(vslf);
119
        }
120 96480
}
121
122
void
123 48240
VSL_Delete(struct VSL_data *vsl)
124
{
125
126 48240
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
127
128 48240
        vbit_destroy(vsl->vbm_select);
129 48240
        vbit_destroy(vsl->vbm_supress);
130 48240
        vsl_IX_free(&vsl->vslf_select);
131 48240
        vsl_IX_free(&vsl->vslf_suppress);
132 48240
        VSL_ResetError(vsl);
133 48240
        FREE_OBJ(vsl);
134 48240
}
135
136
const char *
137 165759
VSL_Error(const struct VSL_data *vsl)
138
{
139
140 165759
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
141
142 165759
        if (vsl->diag == NULL)
143 0
                return (NULL);
144
        else
145 165759
                return (VSB_data(vsl->diag));
146 165759
}
147
148
void
149 211879
VSL_ResetError(struct VSL_data *vsl)
150
{
151
152 211879
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
153
154 211879
        if (vsl->diag == NULL)
155 48240
                return;
156 163639
        VSB_destroy(&vsl->diag);
157 211879
}
158
159
static int
160 2080
vsl_match_IX(struct VSL_data *vsl, const vslf_list *list,
161
    const struct VSL_cursor *c)
162
{
163
        enum VSL_tag_e tag;
164
        const char *cdata;
165
        int len;
166
        const struct vslf *vslf;
167
168 2080
        (void)vsl;
169 2080
        tag = VSL_TAG(c->rec.ptr);
170 2080
        cdata = VSL_CDATA(c->rec.ptr);
171 2080
        len = VSL_LEN(c->rec.ptr);
172
173 3600
        VTAILQ_FOREACH(vslf, list, list) {
174 2080
                CHECK_OBJ_NOTNULL(vslf, VSLF_MAGIC);
175 2080
                if (vslf->tags != NULL && !vbit_test(vslf->tags, tag))
176 0
                        continue;
177 2080
                if (VRE_match(vslf->vre, cdata, len, 0, NULL) >= 0)
178 560
                        return (1);
179 1520
        }
180 1520
        return (0);
181 2080
}
182
183
int
184 1169777
VSL_Match(struct VSL_data *vsl, const struct VSL_cursor *c)
185
{
186
        enum VSL_tag_e tag;
187
188 1169777
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
189 1169777
        if (c == NULL || c->rec.ptr == NULL)
190 46
                return (0);
191 1169777
        tag = VSL_TAG(c->rec.ptr);
192 1169777
        if (tag <= SLT__Bogus || tag >= SLT__Reserved)
193 22
                return (0);
194 1169761
        if (!vsl->c_opt || !vsl->b_opt) {
195 1168406
                if (vsl->c_opt && !VSL_CLIENT(c->rec.ptr))
196 3840
                        return (0);
197 1164566
                if (vsl->b_opt && !VSL_BACKEND(c->rec.ptr))
198 0
                        return (0);
199 1164566
        }
200 1165921
        if (!VTAILQ_EMPTY(&vsl->vslf_select) &&
201 240
            vsl_match_IX(vsl, &vsl->vslf_select, c))
202 80
                return (1);
203 1165841
        else if (vbit_test(vsl->vbm_select, tag))
204 0
                return (1);
205 1165841
        else if (!VTAILQ_EMPTY(&vsl->vslf_suppress) &&
206 1840
            vsl_match_IX(vsl, &vsl->vslf_suppress, c))
207 480
                return (0);
208 1165361
        else if (vbit_test(vsl->vbm_supress, tag))
209 65160
                return (0);
210
211
        /* Default show */
212 1100201
        return (1);
213 1169761
}
214
215
static const char * const VSL_transactions[VSL_t__MAX] = {
216
        /*                 12345678901234 */
217
        [VSL_t_unknown] = "<< Unknown  >>",
218
        [VSL_t_sess]    = "<< Session  >>",
219
        [VSL_t_req]     = "<< Request  >>",
220
        [VSL_t_bereq]   = "<< BeReq    >>",
221
        [VSL_t_raw]     = "<< Record   >>",
222
};
223
224
#define VSL_PRINT(...)                                  \
225
        do {                                            \
226
                if (0 > fprintf(__VA_ARGS__))           \
227
                        return (-5);                    \
228
        } while (0)
229
230
static int
231 3058
vsl_print_unsafe(FILE *fo, unsigned len, const char *data)
232
{
233
234 3058
        VSL_PRINT(fo, "\"");
235 189440
        while (len-- > 0) {
236 186382
                if (*data >= ' ' && *data <= '~')
237 183324
                        VSL_PRINT(fo, "%c", *data);
238
                else
239 3058
                        VSL_PRINT(fo, "%%%02x", (unsigned char)*data);
240 186382
                data++;
241
        }
242 3058
        VSL_PRINT(fo, "\"\n");
243 3058
        return (0);
244 3058
}
245
246
247
static int
248 916
vsl_print_binary(FILE *fo, unsigned len, const char *data)
249
{
250
251 916
        VSL_PRINT(fo, "[");
252 20902
        while (len-- > 0) {
253 19986
                VSL_PRINT(fo, "%02x", (unsigned char)*data);
254 19986
                data++;
255
        }
256 916
        VSL_PRINT(fo, "]\n");
257 916
        return (0);
258 916
}
259
260
static int
261 22580
vsl_print(const struct VSL_data *vsl, const struct VSL_cursor *c, void *fo,
262
    int terse)
263
{
264
        enum VSL_tag_e tag;
265
        uint64_t vxid;
266
        unsigned len;
267
        const char *data;
268
        int type;
269
270 22580
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
271 22580
        if (c == NULL || c->rec.ptr == NULL)
272 0
                return (0);
273 22580
        if (fo == NULL)
274 0
                fo = stdout;
275 22580
        tag = VSL_TAG(c->rec.ptr);
276 22580
        vxid = VSL_ID(c->rec.ptr);
277 22580
        len = VSL_LEN(c->rec.ptr);
278 22580
        type = VSL_CLIENT(c->rec.ptr) ? 'c' : VSL_BACKEND(c->rec.ptr) ?
279
            'b' : '-';
280 22580
        data = VSL_CDATA(c->rec.ptr);
281
282 22580
        if (!terse)
283 18060
                VSL_PRINT(fo, "%10ju ", (uintmax_t)vxid);
284 22580
        VSL_PRINT(fo, "%-14s ", VSL_tags[tag]);
285 22580
        if (!terse)
286 18060
                VSL_PRINT(fo, "%c ", type);
287
288 22580
        if (VSL_tagflags[tag] & SLT_F_UNSAFE)
289 3058
                (void)vsl_print_unsafe(fo, len, data);
290 19522
        else if (VSL_tagflags[tag] & SLT_F_BINARY)
291 916
                (void)vsl_print_binary(fo, len, data);
292
        else
293 18606
                VSL_PRINT(fo, "%.*s\n", (int)len, data);
294
295 22580
        return (0);
296 22580
}
297
298
int
299 18060
VSL_Print(const struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
300
{
301
302 18060
        return (vsl_print(vsl, c, fo, 0));
303
}
304
305
int
306 4520
VSL_PrintTerse(const struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
307
{
308
309 4520
        return (vsl_print(vsl, c, fo, 1));
310
}
311
312
int
313 0
VSL_PrintAll(struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
314
{
315
        int i;
316
317 0
        if (c == NULL)
318 0
                return (0);
319 0
        while (1) {
320 0
                i = VSL_Next(c);
321 0
                if (i <= 0)
322 0
                        return (i);
323 0
                if (!VSL_Match(vsl, c))
324 0
                        continue;
325 0
                i = VSL_Print(vsl, c, fo);
326 0
                if (i != 0)
327 0
                        return (i);
328
        }
329 0
}
330
331
int v_matchproto_(VSLQ_dispatch_f)
332 32940
VSL_PrintTransactions(struct VSL_data *vsl, struct VSL_transaction * const pt[],
333
    void *fo)
334
{
335
        struct VSL_transaction *t;
336
        int i;
337 32940
        int delim = 0;
338
        int verbose;
339
340 32940
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
341 32940
        if (fo == NULL)
342 27102
                fo = stdout;
343 32940
        if (pt[0] == NULL)
344 0
                return (0);
345
346 66120
        for (t = pt[0]; t != NULL; t = *++pt) {
347 33180
                if (vsl->c_opt || vsl->b_opt) {
348 14680
                        switch (t->type) {
349
                        case VSL_t_req:
350 800
                                if (!vsl->c_opt)
351 0
                                        continue;
352 800
                                if (t->reason == VSL_r_esi && !vsl->E_opt)
353 160
                                        continue;
354 640
                                break;
355
                        case VSL_t_bereq:
356 160
                                if (!vsl->b_opt)
357 80
                                        continue;
358 80
                                break;
359
                        case VSL_t_raw:
360 13600
                                break;
361
                        default:
362 120
                                continue;
363
                        }
364 14320
                }
365
366 32820
                verbose = 0;
367 32820
                if (t->level == 0 || vsl->v_opt)
368 31860
                        verbose = 1;
369
370 32820
                if (t->level) {
371
                        /* Print header */
372 1000
                        if (t->level > 3)
373 0
                                VSL_PRINT(fo, "*%1.1d* ", t->level);
374
                        else
375 1000
                                VSL_PRINT(fo, "%-3.*s ",
376
                                    (int)(t->level), "***");
377 1000
                        VSL_PRINT(fo, "%*.s%-14s %*.s%-10ju\n",
378
                            verbose ? 10 + 1 : 0, " ",
379
                            VSL_transactions[t->type],
380
                            verbose ? 1 + 1 : 0, " ",
381
                            (uintmax_t)t->vxid);
382 1000
                        delim = 1;
383 1000
                }
384
385 55400
                while (1) {
386
                        /* Print records */
387 94280
                        i = VSL_Next(t->c);
388 94280
                        if (i < 0)
389 0
                                return (i);
390 94280
                        if (i == 0)
391 32820
                                break;
392 61460
                        if (!VSL_Match(vsl, t->c))
393 38880
                                continue;
394 22580
                        if (t->level > 3)
395 0
                                VSL_PRINT(fo, "-%1.1d- ", t->level);
396 22580
                        else if (t->level)
397 4560
                                VSL_PRINT(fo, "%-3.*s ",
398
                                    (int)(t->level), "---");
399 22580
                        if (verbose)
400 18060
                                i = VSL_Print(vsl, t->c, fo);
401
                        else
402 4520
                                i = VSL_PrintTerse(vsl, t->c, fo);
403 22580
                        if (i != 0)
404 0
                                return (i);
405
                }
406 32820
        }
407
408 32940
        if (delim)
409 1000
                VSL_PRINT(fo, "\n");;
410
411 32940
        return (0);
412 32940
}
413
414
FILE*
415 160
VSL_WriteOpen(struct VSL_data *vsl, const char *name, int append, int unbuf)
416
{
417
        FILE* f;
418
419 160
        if (!strcmp(name, "-"))
420 40
                f = stdout;
421
        else
422 120
                f = fopen(name, append ? "a" : "w");
423 160
        if (f == NULL) {
424 40
                vsl_diag(vsl, "%s", strerror(errno));
425 40
                return (NULL);
426
        }
427 120
        if (unbuf)
428 0
                setbuf(f, NULL);
429 120
        if (ftell(f) == 0 || f == stdout) {
430 120
                if (fwrite(VSL_FILE_ID, 1, sizeof VSL_FILE_ID, f) !=
431
                    sizeof VSL_FILE_ID) {
432 0
                        vsl_diag(vsl, "%s", strerror(errno));
433 0
                        (void)fclose(f);
434 0
                        return (NULL);
435
                }
436 120
        }
437 120
        return (f);
438 160
}
439
440
int
441 4280
VSL_Write(const struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
442
{
443
        size_t r;
444
445 4280
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
446 4280
        if (c == NULL || c->rec.ptr == NULL)
447 0
                return (0);
448 4280
        if (fo == NULL)
449 0
                fo = stdout;
450 8560
        r = fwrite(c->rec.ptr, sizeof *c->rec.ptr,
451 4280
            VSL_NEXT(c->rec.ptr) - c->rec.ptr, fo);
452 4280
        if (r == 0)
453 0
                return (-5);
454 4280
        return (0);
455 4280
}
456
457
int
458 360
VSL_WriteAll(struct VSL_data *vsl, const struct VSL_cursor *c, void *fo)
459
{
460
        int i;
461
462 360
        if (c == NULL)
463 0
                return (0);
464 4640
        while (1) {
465 10880
                i = VSL_Next(c);
466 10880
                if (i <= 0)
467 360
                        return (i);
468 10520
                if (!VSL_Match(vsl, c))
469 6240
                        continue;
470 4280
                i = VSL_Write(vsl, c, fo);
471 4280
                if (i != 0)
472 0
                        return (i);
473
        }
474 360
}
475
476
int v_matchproto_(VSLQ_dispatch_f)
477 360
VSL_WriteTransactions(struct VSL_data *vsl, struct VSL_transaction * const pt[],
478
    void *fo)
479
{
480
        struct VSL_transaction *t;
481
        int i;
482
483 360
        if (pt == NULL)
484 0
                return (0);
485 720
        for (i = 0, t = pt[0]; i == 0 && t != NULL; t = *++pt)
486 360
                i = VSL_WriteAll(vsl, t->c, fo);
487 360
        return (i);
488 360
}