varnish-cache/lib/libvarnishapi/vsl_arg.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 <ctype.h>
34
#include <limits.h>
35
#include <math.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
39
#include "vdef.h"
40
#include "vas.h"
41
#include "miniobj.h"
42
43
#include "vbm.h"
44
#include "vnum.h"
45
#include "vqueue.h"
46
#include "vre.h"
47
48
#include "vapi/vsl.h"
49
50
#include "vsl_api.h"
51
52
/*--------------------------------------------------------------------
53
 * Look up a tag
54
 *   0..255     tag number
55
 *   -1         no tag matches
56
 *   -2         multiple tags match
57
 */
58
59
int
60 1976
VSL_Name2Tag(const char *name, int l)
61
{
62
        int i, n;
63
64 1976
        if (l == -1)
65 140
                l = strlen(name);
66 1976
        n = -1;
67 101670
        for (i = 0; i < SLT__MAX; i++) {
68 197756
                if (VSL_tags[i] != NULL &&
69 96108
                    !strncasecmp(name, VSL_tags[i], l)) {
70 2006
                        if (strlen(VSL_tags[i]) == l) {
71
                                /* Exact match */
72 1954
                                return (i);
73
                        }
74 52
                        if (n == -1)
75 6
                                n = i;
76
                        else
77 46
                                n = -2;
78
                }
79
        }
80 22
        return (n);
81
}
82
83
int
84 186
VSL_Glob2Tags(const char *glob, int l, VSL_tagfind_f *func, void *priv)
85
{
86 186
        const char *p1 = NULL;
87 186
        const char *p2 = NULL;
88
        const char *e, *p;
89 186
        int i, l1 = 0, l2 = 0, r = 0;
90
91 186
        AN(glob);
92 186
        if (l >= 0)
93 36
                e = glob + l;
94
        else
95 150
                e = strchr(glob, '\0');
96 186
        if (glob == e)
97 4
                return (-1);            // Empty pattern cannot match
98
99 1472
        for (p = glob; p < e; p++)
100 1320
                if (*p == '*')
101 30
                        break;
102
103 182
        if (p == e) {                   // No wildcard
104 152
                i = VSL_Name2Tag(glob, l);
105 152
                if (i < 0)
106 12
                        return (i);
107 140
                if (func != NULL)
108 140
                        (func)(i, priv);
109 140
                return (1);
110
        }
111
112 30
        if (p != glob) {                // Prefix match
113 20
                p1 = glob;
114 20
                l1 = p - p1;
115
        }
116
117 30
        if (p != e - 1) {               // Postfix match
118 16
                p2 = p + 1;
119 16
                l2 = e - p2;
120
        }
121
122 56
        for (p++; p < e; p++)
123 36
                if (*p == '*')
124 10
                        return (-3);    // More than one wildcard
125
126 5140
        for (i = 0; i < SLT__MAX; i++) {
127 5120
                p = VSL_tags[i];
128 5120
                if (p == NULL)
129 3260
                        continue;
130 1860
                e = strchr(p, '\0');
131 1860
                if (e - p < l1 + l2)
132 128
                        continue;
133 1732
                if (p1 != NULL && strncasecmp(p, p1, l1))
134 1262
                        continue;
135 470
                if (p2 != NULL && strncasecmp(e - l2, p2, l2))
136 160
                        continue;
137 310
                if (func != NULL)
138 310
                        (func)(i, priv);
139 310
                r++;
140
        }
141 20
        if (r == 0)
142 2
                return (-1);
143 18
        return (r);
144
}
145
146
int
147 34
VSL_List2Tags(const char *list, int l, VSL_tagfind_f *func, void *priv)
148
{
149
        const char *p, *b, *e;
150 34
        int r, t = 0;
151
152 34
        p = list;
153 34
        if (l >= 0)
154 6
                e = p + l;
155
        else
156 28
                e = strchr(p, '\0');
157 86
        while (p < e) {
158 80
                while (p < e && *p == ',')
159 8
                        p++;
160 36
                if (p == e)
161 2
                        break;
162 34
                b = p;
163 250
                while (p < e && *p != ',')
164 182
                        p++;
165 34
                r = VSL_Glob2Tags(b, p - b, func, priv);
166 34
                if (r < 0)
167 16
                        return (r);
168 18
                t += r;
169
        }
170 18
        if (t == 0)
171 2
                return (-1);
172 16
        return (t);
173
}
174
175
const char *VSLQ_grouping[VSL_g__MAX] = {
176
        [VSL_g_raw]     = "raw",
177
        [VSL_g_vxid]    = "vxid",
178
        [VSL_g_request] = "request",
179
        [VSL_g_session] = "session",
180
};
181
182
int
183 314
VSLQ_Name2Grouping(const char *name, int l)
184
{
185
        int i, n;
186
187 314
        AN(name);
188 314
        if (l == -1)
189 18
                l = strlen(name);
190 314
        n = -1;
191 584
        for (i = 0; i < VSL_g__MAX; i++) {
192 580
                if (!strncasecmp(name, VSLQ_grouping[i], l)) {
193 314
                        if (strlen(VSLQ_grouping[i]) == l) {
194
                                /* Exact match */
195 310
                                return (i);
196
                        }
197 4
                        if (n == -1)
198 2
                                n = i;
199
                        else
200 2
                                n = -2;
201
                }
202
        }
203 4
        return (n);
204
}
205
206
void v_matchproto_(VSL_tagfind_f)
207 160
vsl_vbm_bitset(int bit, void *priv)
208
{
209
210 160
        vbit_set((struct vbitmap *)priv, bit);
211 160
}
212
213
void v_matchproto_(VSL_tagfind_f)
214 12
vsl_vbm_bitclr(int bit, void *priv)
215
{
216
217 12
        vbit_clr((struct vbitmap *)priv, bit);
218 12
}
219
220
static int
221 22
vsl_ix_arg(struct VSL_data *vsl, int opt, const char *arg)
222
{
223
        int i;
224
225 22
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
226 22
        vsl->flags |= F_SEEN_ixIX;
227
228 22
        i = VSL_List2Tags(arg, -1, opt == 'x' ? vsl_vbm_bitset : vsl_vbm_bitclr,
229 22
            vsl->vbm_supress);
230 22
        if (i == -1)
231 2
                return (vsl_diag(vsl, "-%c: \"%s\" matches zero tags",
232 2
                    (char)opt, arg));
233 20
        else if (i == -2)
234 2
                return (vsl_diag(vsl, "-%c: \"%s\" is ambiguous",
235 2
                    (char)opt, arg));
236 18
        else if (i == -3)
237 4
                return (vsl_diag(vsl, "-%c: Syntax error in \"%s\"",
238 4
                    (char)opt, arg));
239
240 14
        return (1);
241
}
242
243
static int
244 16
vsl_IX_arg(struct VSL_data *vsl, int opt, const char *arg)
245
{
246
        int i, l, off;
247
        const char *b, *e, *err;
248
        vre_t *vre;
249
        struct vslf *vslf;
250 16
        struct vbitmap *tags = NULL;
251
252 16
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
253 16
        AN(arg);
254 16
        vsl->flags |= F_SEEN_ixIX;
255
256 16
        b = arg;
257 16
        e = strchr(b, ':');
258 16
        if (e) {
259 6
                tags = vbit_new(SLT__MAX);
260 6
                AN(tags);
261 6
                l = e - b;
262 6
                i = VSL_List2Tags(b, l, vsl_vbm_bitset, tags);
263 6
                if (i < 0)
264 6
                        vbit_destroy(tags);
265 6
                if (i == -1)
266 2
                        return (vsl_diag(vsl,
267
                            "-%c: \"%*.*s\" matches zero tags",
268 2
                            (char)opt, l, l, b));
269 4
                else if (i == -2)
270 2
                        return (vsl_diag(vsl,
271
                            "-%c: \"%*.*s\" is ambiguous",
272 2
                            (char)opt, l, l, b));
273 2
                else if (i <= -3)
274 2
                        return (vsl_diag(vsl,
275
                            "-%c: Syntax error in \"%*.*s\"",
276 2
                            (char)opt, l, l, b));
277 0
                b = e + 1;
278
        }
279
280 10
        vre = VRE_compile(b, vsl->C_opt ? VRE_CASELESS : 0, &err, &off);
281 10
        if (vre == NULL) {
282 2
                if (tags)
283 0
                        vbit_destroy(tags);
284 4
                return (vsl_diag(vsl, "-%c: Regex error at position %d (%s)",
285 2
                    (char)opt, off, err));
286
        }
287
288 8
        ALLOC_OBJ(vslf, VSLF_MAGIC);
289 8
        AN(vslf);
290 8
        vslf->tags = tags;
291 8
        vslf->vre = vre;
292
293 8
        if (opt == 'I')
294 6
                VTAILQ_INSERT_TAIL(&vsl->vslf_select, vslf, list);
295
        else {
296 2
                assert(opt == 'X');
297 2
                VTAILQ_INSERT_TAIL(&vsl->vslf_suppress, vslf, list);
298
        }
299
300 8
        return (1);
301
}
302
303
int
304 62
VSL_Arg(struct VSL_data *vsl, int opt, const char *arg)
305
{
306
        int i;
307
        char *p;
308
        double d;
309
        long l;
310
311 62
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
312
        /* If first option is 'i', set all bits for supression */
313 62
        if ((opt == 'i' || opt == 'I') && !(vsl->flags & F_SEEN_ixIX))
314 7710
                for (i = 0; i < SLT__MAX; i++)
315 7680
                        vbit_set(vsl->vbm_supress, i);
316
317 62
        switch (opt) {
318 8
        case 'b': vsl->b_opt = 1; return (1);
319 4
        case 'c': vsl->c_opt = 1; return (1);
320
        case 'C':
321
                /* Caseless regular expressions */
322 2
                vsl->C_opt = 1;
323 2
                return (1);
324 22
        case 'i': case 'x': return (vsl_ix_arg(vsl, opt, arg));
325 16
        case 'I': case 'X': return (vsl_IX_arg(vsl, opt, arg));
326
        case 'L':
327 2
                AN(arg);
328 2
                l = strtol(arg, &p, 0);
329 4
                while (isspace(*p))
330 0
                        p++;
331 2
                if (*p != '\0')
332 0
                        return (vsl_diag(vsl, "-L: Syntax error"));
333 2
                if (l <= 0 || l > INT_MAX)
334 2
                        return (vsl_diag(vsl, "-L: Range error"));
335 0
                vsl->L_opt = (int)l;
336 0
                return (1);
337
        case 'T':
338 2
                AN(arg);
339 2
                d = VNUM(arg);
340 2
                if (isnan(d))
341 0
                        return (vsl_diag(vsl, "-T: Syntax error"));
342 2
                if (d < 0.)
343 0
                        return (vsl_diag(vsl, "-T: Range error"));
344 2
                vsl->T_opt = d;
345 2
                return (1);
346 2
        case 'v': vsl->v_opt = 1; return (1);
347
        default:
348 4
                return (0);
349
        }
350
}