| | 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 |
181302 |
vsl_diag(struct VSL_data *vsl, const char *fmt, ...) |
68 |
|
{ |
69 |
|
va_list ap; |
70 |
|
|
71 |
181302 |
CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC); |
72 |
181302 |
AN(fmt); |
73 |
|
|
74 |
181302 |
if (vsl->diag == NULL) |
75 |
181302 |
vsl->diag = VSB_new_auto(); |
76 |
181302 |
AN(vsl->diag); |
77 |
181302 |
VSB_clear(vsl->diag); |
78 |
181302 |
va_start(ap, fmt); |
79 |
181302 |
VSB_vprintf(vsl->diag, fmt, ap); |
80 |
181302 |
va_end(ap); |
81 |
181302 |
AZ(VSB_finish(vsl->diag)); |
82 |
181302 |
return (-1); |
83 |
|
} |
84 |
|
|
85 |
|
struct VSL_data * |
86 |
54440 |
VSL_New(void) |
87 |
|
{ |
88 |
|
struct VSL_data *vsl; |
89 |
|
|
90 |
54440 |
ALLOC_OBJ(vsl, VSL_MAGIC); |
91 |
54440 |
if (vsl == NULL) |
92 |
0 |
return (NULL); |
93 |
|
|
94 |
54440 |
vsl->L_opt = 1000; |
95 |
54440 |
vsl->T_opt = 120.; |
96 |
54440 |
vsl->vbm_select = vbit_new(SLT__MAX); |
97 |
54440 |
vsl->vbm_suppress = vbit_new(SLT__MAX); |
98 |
54440 |
VTAILQ_INIT(&vsl->vslf_select); |
99 |
54440 |
VTAILQ_INIT(&vsl->vslf_suppress); |
100 |
|
|
101 |
54440 |
return (vsl); |
102 |
54440 |
} |
103 |
|
|
104 |
|
static void |
105 |
97520 |
vsl_IX_free(vslf_list *filters) |
106 |
|
{ |
107 |
|
struct vslf *vslf; |
108 |
|
|
109 |
97680 |
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 |
97520 |
} |
121 |
|
|
122 |
|
void |
123 |
48760 |
VSL_Delete(struct VSL_data *vsl) |
124 |
|
{ |
125 |
|
|
126 |
48760 |
CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC); |
127 |
|
|
128 |
48760 |
vbit_destroy(vsl->vbm_select); |
129 |
48760 |
vbit_destroy(vsl->vbm_suppress); |
130 |
48760 |
vsl_IX_free(&vsl->vslf_select); |
131 |
48760 |
vsl_IX_free(&vsl->vslf_suppress); |
132 |
48760 |
VSL_ResetError(vsl); |
133 |
48760 |
FREE_OBJ(vsl); |
134 |
48760 |
} |
135 |
|
|
136 |
|
const char * |
137 |
181302 |
VSL_Error(const struct VSL_data *vsl) |
138 |
|
{ |
139 |
|
|
140 |
181302 |
CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC); |
141 |
|
|
142 |
181302 |
if (vsl->diag == NULL) |
143 |
0 |
return (NULL); |
144 |
|
else |
145 |
181302 |
return (VSB_data(vsl->diag)); |
146 |
181302 |
} |
147 |
|
|
148 |
|
void |
149 |
227942 |
VSL_ResetError(struct VSL_data *vsl) |
150 |
|
{ |
151 |
|
|
152 |
227942 |
CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC); |
153 |
|
|
154 |
227942 |
if (vsl->diag == NULL) |
155 |
48760 |
return; |
156 |
179182 |
VSB_destroy(&vsl->diag); |
157 |
227942 |
} |
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 |
1173712 |
VSL_Match(struct VSL_data *vsl, const struct VSL_cursor *c) |
185 |
|
{ |
186 |
|
enum VSL_tag_e tag; |
187 |
|
|
188 |
1173712 |
CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC); |
189 |
1173712 |
if (c == NULL || c->rec.ptr == NULL) |
190 |
12 |
return (0); |
191 |
1173712 |
tag = VSL_TAG(c->rec.ptr); |
192 |
1173712 |
if (tag <= SLT__Bogus || tag >= SLT__Reserved) |
193 |
12 |
return (0); |
194 |
1173704 |
if (!vsl->c_opt || !vsl->b_opt) { |
195 |
1172347 |
if (vsl->c_opt && !VSL_CLIENT(c->rec.ptr)) |
196 |
3840 |
return (0); |
197 |
1168507 |
if (vsl->b_opt && !VSL_BACKEND(c->rec.ptr)) |
198 |
0 |
return (0); |
199 |
1168507 |
} |
200 |
1169864 |
if (!VTAILQ_EMPTY(&vsl->vslf_select) && |
201 |
240 |
vsl_match_IX(vsl, &vsl->vslf_select, c)) |
202 |
80 |
return (1); |
203 |
1169784 |
else if (vbit_test(vsl->vbm_select, tag)) |
204 |
0 |
return (1); |
205 |
1169784 |
else if (!VTAILQ_EMPTY(&vsl->vslf_suppress) && |
206 |
1840 |
vsl_match_IX(vsl, &vsl->vslf_suppress, c)) |
207 |
480 |
return (0); |
208 |
1169304 |
else if (vbit_test(vsl->vbm_suppress, tag)) |
209 |
65160 |
return (0); |
210 |
|
|
211 |
|
/* Default show */ |
212 |
1104144 |
return (1); |
213 |
1173704 |
} |
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 |
3056 |
vsl_print_unsafe(FILE *fo, unsigned len, const char *data) |
232 |
|
{ |
233 |
|
|
234 |
3056 |
VSL_PRINT(fo, "\""); |
235 |
189344 |
while (len-- > 0) { |
236 |
186288 |
if (*data >= ' ' && *data <= '~') |
237 |
183232 |
VSL_PRINT(fo, "%c", *data); |
238 |
|
else |
239 |
3056 |
VSL_PRINT(fo, "%%%02x", (unsigned char)*data); |
240 |
186288 |
data++; |
241 |
|
} |
242 |
3056 |
VSL_PRINT(fo, "\"\n"); |
243 |
3056 |
return (0); |
244 |
3056 |
} |
245 |
|
|
246 |
|
|
247 |
|
static int |
248 |
912 |
vsl_print_binary(FILE *fo, unsigned len, const char *data) |
249 |
|
{ |
250 |
|
|
251 |
912 |
VSL_PRINT(fo, "["); |
252 |
20872 |
while (len-- > 0) { |
253 |
19960 |
VSL_PRINT(fo, "%02x", (unsigned char)*data); |
254 |
19960 |
data++; |
255 |
|
} |
256 |
912 |
VSL_PRINT(fo, "]\n"); |
257 |
912 |
return (0); |
258 |
912 |
} |
259 |
|
|
260 |
|
static int |
261 |
22582 |
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 |
22582 |
CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC); |
271 |
22582 |
if (c == NULL || c->rec.ptr == NULL) |
272 |
0 |
return (0); |
273 |
22582 |
if (fo == NULL) |
274 |
0 |
fo = stdout; |
275 |
22582 |
tag = VSL_TAG(c->rec.ptr); |
276 |
22582 |
vxid = VSL_ID(c->rec.ptr); |
277 |
22582 |
len = VSL_LEN(c->rec.ptr); |
278 |
22582 |
type = VSL_CLIENT(c->rec.ptr) ? 'c' : VSL_BACKEND(c->rec.ptr) ? |
279 |
|
'b' : '-'; |
280 |
22582 |
data = VSL_CDATA(c->rec.ptr); |
281 |
|
|
282 |
22582 |
if (!terse) |
283 |
18062 |
VSL_PRINT(fo, "%10ju ", (uintmax_t)vxid); |
284 |
22582 |
VSL_PRINT(fo, "%-14s ", VSL_tags[tag]); |
285 |
22582 |
if (!terse) |
286 |
18062 |
VSL_PRINT(fo, "%c ", type); |
287 |
|
|
288 |
22582 |
if (VSL_tagflags[tag] & SLT_F_UNSAFE) |
289 |
3056 |
(void)vsl_print_unsafe(fo, len, data); |
290 |
19526 |
else if (VSL_tagflags[tag] & SLT_F_BINARY) |
291 |
912 |
(void)vsl_print_binary(fo, len, data); |
292 |
|
else |
293 |
18614 |
VSL_PRINT(fo, "%.*s\n", (int)len, data); |
294 |
|
|
295 |
22582 |
return (0); |
296 |
22582 |
} |
297 |
|
|
298 |
|
int |
299 |
18062 |
VSL_Print(const struct VSL_data *vsl, const struct VSL_cursor *c, void *fo) |
300 |
|
{ |
301 |
|
|
302 |
18062 |
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 |
32942 |
VSL_PrintTransactions(struct VSL_data *vsl, struct VSL_transaction * const pt[], |
333 |
|
void *fo) |
334 |
|
{ |
335 |
|
struct VSL_transaction *t; |
336 |
|
int i; |
337 |
32942 |
int delim = 0; |
338 |
|
int verbose; |
339 |
|
|
340 |
32942 |
CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC); |
341 |
32942 |
if (fo == NULL) |
342 |
27102 |
fo = stdout; |
343 |
32942 |
if (pt[0] == NULL) |
344 |
0 |
return (0); |
345 |
|
|
346 |
66124 |
for (t = pt[0]; t != NULL; t = *++pt) { |
347 |
33182 |
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 |
32822 |
verbose = 0; |
367 |
32822 |
if (t->level == 0 || vsl->v_opt) |
368 |
31862 |
verbose = 1; |
369 |
|
|
370 |
32822 |
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 |
55404 |
while (1) { |
386 |
|
/* Print records */ |
387 |
94284 |
i = VSL_Next(t->c); |
388 |
94284 |
if (i < 0) |
389 |
0 |
return (i); |
390 |
94284 |
if (i == 0) |
391 |
32822 |
break; |
392 |
61462 |
if (!VSL_Match(vsl, t->c)) |
393 |
38880 |
continue; |
394 |
22582 |
if (t->level > 3) |
395 |
0 |
VSL_PRINT(fo, "-%1.1d- ", t->level); |
396 |
22582 |
else if (t->level) |
397 |
4560 |
VSL_PRINT(fo, "%-3.*s ", |
398 |
|
(int)(t->level), "---"); |
399 |
22582 |
if (verbose) |
400 |
18062 |
i = VSL_Print(vsl, t->c, fo); |
401 |
|
else |
402 |
4520 |
i = VSL_PrintTerse(vsl, t->c, fo); |
403 |
22582 |
if (i != 0) |
404 |
0 |
return (i); |
405 |
|
} |
406 |
32822 |
} |
407 |
|
|
408 |
32942 |
if (delim) |
409 |
1000 |
VSL_PRINT(fo, "\n");; |
410 |
|
|
411 |
32942 |
return (0); |
412 |
32942 |
} |
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 |
} |