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