varnish-cache/lib/libvarnishapi/vsl_arg.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 <ctype.h>
35
#include <limits.h>
36
#include <math.h>
37
#include <stdio.h>
38
#include <stdlib.h>
39
40
#include "vdef.h"
41
#include "vas.h"
42
#include "miniobj.h"
43
44
#include "vbm.h"
45
#include "vnum.h"
46
#include "vqueue.h"
47
#include "vre.h"
48
#include "vsb.h"
49
50
#include "vapi/vsl.h"
51
52
#include "vsl_api.h"
53
54
/*--------------------------------------------------------------------
55
 * Look up a tag
56
 *   0..255     tag number
57
 *   -1         no tag matches
58
 *   -2         multiple tags match
59
 */
60
61
int
62 74640
VSL_Name2Tag(const char *name, int l)
63
{
64
        int i, n;
65
66 74640
        if (l == -1)
67 7080
                l = strlen(name);
68 74640
        n = -1;
69 3412680
        for (i = 0; i < SLT__MAX; i++) {
70 3412040
                if (VSL_tags[i] != NULL &&
71 3233720
                    !strncasecmp(name, VSL_tags[i], l)) {
72 75360
                        if (strlen(VSL_tags[i]) == l) {
73
                                /* Exact match */
74 74000
                                return (i);
75
                        }
76 1360
                        if (n == -1)
77 160
                                n = i;
78
                        else
79 1200
                                n = -2;
80 1360
                }
81 3338040
        }
82 640
        return (n);
83 74640
}
84
85
int
86 9400
VSL_Glob2Tags(const char *glob, int l, VSL_tagfind_f *func, void *priv)
87
{
88 9400
        const char *p1 = NULL;
89 9400
        const char *p2 = NULL;
90
        const char *e, *p;
91 9400
        int i, l1 = 0, l2 = 0, r = 0;
92
93 9400
        AN(glob);
94 9400
        if (l >= 0)
95 2360
                e = glob + l;
96
        else
97 7040
                e = strchr(glob, '\0');
98 9400
        if (glob == e)
99 80
                return (-1);            // Empty pattern cannot match
100
101 76000
        for (p = glob; p < e; p++)
102 67520
                if (*p == '*')
103 840
                        break;
104
105 9320
        if (p == e) {                   // No wildcard
106 8480
                i = VSL_Name2Tag(glob, l);
107 8480
                if (i < 0)
108 360
                        return (i);
109 8120
                if (func != NULL)
110 8120
                        (func)(i, priv);
111 8120
                return (1);
112
        }
113
114 840
        if (p != glob) {                // Prefix match
115 560
                p1 = glob;
116 560
                l1 = p - p1;
117 560
        }
118
119 840
        if (p != e - 1) {               // Postfix match
120 400
                p2 = p + 1;
121 400
                l2 = e - p2;
122 400
        }
123
124 1600
        for (p++; p < e; p++)
125 1000
                if (*p == '*')
126 240
                        return (-3);    // More than one wildcard
127
128 154200
        for (i = 0; i < SLT__MAX; i++) {
129 153600
                p = VSL_tags[i];
130 153600
                if (p == NULL)
131 97800
                        continue;
132 55800
                e = strchr(p, '\0');
133 55800
                if ((e - p) - l1 < l2)
134 3920
                        continue;
135 51880
                if (p1 != NULL && strncasecmp(p, p1, l1))
136 37640
                        continue;
137 14240
                if (p2 != NULL && strncasecmp(e - l2, p2, l2))
138 6400
                        continue;
139 7840
                if (func != NULL)
140 7840
                        (func)(i, priv);
141 7840
                r++;
142 7840
        }
143 600
        if (r == 0)
144 40
                return (-1);
145 560
        return (r);
146 9400
}
147
148
int
149 1840
VSL_List2Tags(const char *list, int l, VSL_tagfind_f *func, void *priv)
150
{
151
        const char *p, *b, *e;
152 1840
        int r, t = 0;
153
154 1840
        p = list;
155 1840
        if (l >= 0)
156 120
                e = p + l;
157
        else
158 1720
                e = strchr(p, '\0');
159 3840
        while (p < e) {
160 3000
                while (p < e && *p == ',')
161 640
                        p++;
162 2360
                if (p == e)
163 40
                        break;
164 2320
                b = p;
165 15360
                while (p < e && *p != ',')
166 13040
                        p++;
167 2320
                r = VSL_Glob2Tags(b, p - b, func, priv);
168 2320
                if (r < 0)
169 320
                        return (r);
170 2000
                t += r;
171
        }
172 1520
        if (t == 0)
173 40
                return (-1);
174 1480
        return (t);
175 1840
}
176
177
const char *VSLQ_grouping[VSL_g__MAX] = {
178
        [VSL_g_raw]     = "raw",
179
        [VSL_g_vxid]    = "vxid",
180
        [VSL_g_request] = "request",
181
        [VSL_g_session] = "session",
182
};
183
184
int
185 8880
VSLQ_Name2Grouping(const char *name, int l)
186
{
187
        int i, n;
188
189 8880
        AN(name);
190 8880
        if (l == -1)
191 560
                l = strlen(name);
192 8880
        n = -1;
193 15920
        for (i = 0; i < VSL_g__MAX; i++) {
194 15840
                if (!strncasecmp(name, VSLQ_grouping[i], l)) {
195 8880
                        if (strlen(VSLQ_grouping[i]) == l) {
196
                                /* Exact match */
197 8800
                                return (i);
198
                        }
199 80
                        if (n == -1)
200 40
                                n = i;
201
                        else
202 40
                                n = -2;
203 80
                }
204 7040
        }
205 80
        return (n);
206 8880
}
207
208
void v_matchproto_(VSL_tagfind_f)
209 7280
vsl_vbm_bitset(int bit, void *priv)
210
{
211
212 7280
        vbit_set((struct vbitmap *)priv, bit);
213 7280
}
214
215
void v_matchproto_(VSL_tagfind_f)
216 1680
vsl_vbm_bitclr(int bit, void *priv)
217
{
218
219 1680
        vbit_clr((struct vbitmap *)priv, bit);
220 1680
}
221
222
static int
223 1520
vsl_ix_arg(struct VSL_data *vsl, int opt, const char *arg)
224
{
225
        int i;
226
227 1520
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
228 1520
        vsl->flags |= F_SEEN_ixIX;
229
230 3040
        i = VSL_List2Tags(arg, -1, opt == 'x' ? vsl_vbm_bitset : vsl_vbm_bitclr,
231 1520
            vsl->vbm_supress);
232 1520
        if (i == -1)
233 80
                return (vsl_diag(vsl, "-%c: \"%s\" matches zero tags",
234 40
                    (char)opt, arg));
235 1480
        else if (i == -2)
236 80
                return (vsl_diag(vsl, "-%c: \"%s\" is ambiguous",
237 40
                    (char)opt, arg));
238 1440
        else if (i == -3)
239 160
                return (vsl_diag(vsl, "-%c: Syntax error in \"%s\"",
240 80
                    (char)opt, arg));
241
242 1360
        return (1);
243 1520
}
244
245
static int
246 320
vsl_IX_arg(struct VSL_data *vsl, int opt, const char *arg)
247
{
248
        int i, l, off, err;
249
        const char *b, *e;
250
        vre_t *vre;
251
        struct vsb vsb[1];
252
        struct vslf *vslf;
253 320
        struct vbitmap *tags = NULL;
254
        char errbuf[VRE_ERROR_LEN];
255
256
257 320
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
258 320
        AN(arg);
259 320
        vsl->flags |= F_SEEN_ixIX;
260
261 320
        b = arg;
262 320
        e = strchr(b, ':');
263 320
        if (e) {
264 120
                tags = vbit_new(SLT__MAX);
265 120
                AN(tags);
266 120
                l = e - b;
267 120
                i = VSL_List2Tags(b, l, vsl_vbm_bitset, tags);
268 120
                if (i < 0)
269 120
                        vbit_destroy(tags);
270 120
                if (i == -1)
271 80
                        return (vsl_diag(vsl,
272
                            "-%c: \"%*.*s\" matches zero tags",
273 40
                            (char)opt, l, l, b));
274 80
                else if (i == -2)
275 80
                        return (vsl_diag(vsl,
276
                            "-%c: \"%*.*s\" is ambiguous",
277 40
                            (char)opt, l, l, b));
278 40
                else if (i <= -3)
279 80
                        return (vsl_diag(vsl,
280
                            "-%c: Syntax error in \"%*.*s\"",
281 40
                            (char)opt, l, l, b));
282 0
                b = e + 1;
283 0
        }
284
285 200
        vre = VRE_compile(b, vsl->C_opt ? VRE_CASELESS : 0, &err, &off, 1);
286 200
        if (vre == NULL) {
287 40
                if (tags)
288 0
                        vbit_destroy(tags);
289 40
                AN(VSB_init(vsb, errbuf, sizeof errbuf));
290 40
                AZ(VRE_error(vsb, err));
291 40
                AZ(VSB_finish(vsb));
292 40
                VSB_fini(vsb);
293 80
                return (vsl_diag(vsl, "-%c: Regex error at position %d (%s)",
294 40
                    (char)opt, off, errbuf));
295
        }
296
297 160
        ALLOC_OBJ(vslf, VSLF_MAGIC);
298 160
        AN(vslf);
299 160
        vslf->tags = tags;
300 160
        vslf->vre = vre;
301
302 160
        if (opt == 'I')
303 80
                VTAILQ_INSERT_TAIL(&vsl->vslf_select, vslf, list);
304
        else {
305 80
                assert(opt == 'X');
306 80
                VTAILQ_INSERT_TAIL(&vsl->vslf_suppress, vslf, list);
307
        }
308
309 160
        return (1);
310 320
}
311
312
static int
313 440
vsl_R_arg(struct VSL_data *vsl, const char *arg)
314
{
315 440
        char buf[32] = "";
316
        char *p;
317
        long l;
318
319 440
        AN(arg);
320 440
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
321
322 440
        errno = 0;
323 440
        l = strtol(arg, &p, 0);
324 440
        if ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE)
325 0
                return (vsl_diag(vsl, "-R: Range error"));
326 440
        if (l <= 0 || l > INT_MAX)
327 120
                return (vsl_diag(vsl, "-R: Range error"));
328 320
        vsl->R_opt_l = l;
329 320
        assert(p != arg);
330 320
        AN(p);
331 320
        if (*p == '\0') {
332 0
                vsl->R_opt_p = 1.0;
333 0
                return (1);
334
        }
335 320
        if (*p != '/' || p[1] == '\0')
336 40
                return (vsl_diag(vsl, "-R: Syntax error"));
337 280
        p++;
338 280
        if (strlen(p) > sizeof(buf) - 2)
339 40
                return (vsl_diag(vsl, "-R: Syntax error"));
340 240
        if (!isdigit(*p))
341 120
                strcat(buf, "1");
342 240
        strcat(buf, p);
343 240
        vsl->R_opt_p = VNUM_duration(buf);
344 240
        if (isnan(vsl->R_opt_p) || vsl->R_opt_p <= 0.0)
345 160
                return (vsl_diag(vsl, "-R: Syntax error: Invalid duration"));
346 80
        return (1);
347 440
}
348
349
int
350 6320
VSL_Arg(struct VSL_data *vsl, int opt, const char *arg)
351
{
352
        int i;
353
        char *p;
354
        double d;
355
        long l;
356
357 6320
        CHECK_OBJ_NOTNULL(vsl, VSL_MAGIC);
358
        /* If first option is 'i', set all bits for supression */
359 6320
        if ((opt == 'i' || opt == 'I') && !(vsl->flags & F_SEEN_ixIX))
360 277560
                for (i = 0; i < SLT__MAX; i++)
361 277560
                        vbit_set(vsl->vbm_supress, i);
362
363 6320
        switch (opt) {
364 600
        case 'b': vsl->b_opt = 1; return (1);
365 2800
        case 'c': vsl->c_opt = 1; return (1);
366
        case 'C':
367
                /* Caseless regular expressions */
368 80
                vsl->C_opt = 1;
369 80
                return (1);
370
        case 'E':
371 360
                vsl->E_opt = 1;
372 360
                vsl->c_opt = 1;
373 360
                return (1);
374 1520
        case 'i': case 'x': return (vsl_ix_arg(vsl, opt, arg));
375 320
        case 'I': case 'X': return (vsl_IX_arg(vsl, opt, arg));
376
        case 'L':
377 40
                AN(arg);
378 40
                l = strtol(arg, &p, 0);
379 40
                while (isspace(*p))
380 0
                        p++;
381 40
                if (*p != '\0')
382 0
                        return (vsl_diag(vsl, "-L: Syntax error"));
383 40
                if (l <= 0 || l > INT_MAX)
384 40
                        return (vsl_diag(vsl, "-L: Range error"));
385 0
                vsl->L_opt = (int)l;
386 0
                return (1);
387
        case 'R':
388 440
                return (vsl_R_arg(vsl, arg));
389
        case 'T':
390 40
                AN(arg);
391 40
                d = VNUM(arg);
392 40
                if (isnan(d))
393 0
                        return (vsl_diag(vsl, "-T: Syntax error"));
394 40
                if (d < 0.)
395 0
                        return (vsl_diag(vsl, "-T: Range error"));
396 40
                vsl->T_opt = d;
397 40
                return (1);
398 40
        case 'v': vsl->v_opt = 1; return (1);
399
        default:
400 80
                return (0);
401
        }
402 6320
}