varnish-cache/lib/libvcc/vcc_acl.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2010 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
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 <sys/socket.h>
34
35
#include <netinet/in.h>
36
37
#include <netdb.h>
38
#include <stdlib.h>
39
#include <string.h>
40
41
#include "vcc_compile.h"
42
#include <vtcp.h>
43
#include <vtree.h>
44
#include <vsa.h>
45
46
#define ACL_MAXADDR     (sizeof(struct in6_addr) + 1)
47
48
VRBT_HEAD(acl_tree, acl_e);
49
50
struct acl {
51
        unsigned                magic;
52
#define VCC_ACL_MAGIC           0xb9fb3cd0
53
54
        int                     flag_log;
55
        int                     flag_fold;
56
        int                     flag_fold_report;
57
        int                     flag_pedantic;
58
        int                     flag_table;
59
60
        struct acl_tree         acl_tree;
61
};
62
63
struct acl_e {
64
        unsigned                magic;
65
#define VCC_ACL_E_MAGIC 0xcac81e23
66
        VRBT_ENTRY(acl_e)       branch;
67
        unsigned char           data[ACL_MAXADDR];
68
        unsigned                mask;
69
        unsigned                not;
70
        unsigned                para;
71
        unsigned                overlapped;
72
        char                    *addr;
73
        const char              *fixed;
74
        struct token            *t_addr;
75
        struct token            *t_mask;
76
};
77
78
enum acl_cmp_e {
79
        ACL_EQ = 0,
80
        ACL_LT = -1,            // a < b
81
        ACL_GT = 1,             // b > a
82
        ACL_CONTAINED = -2,     // b contains a
83
        ACL_CONTAINS = 2,       // a contains b
84
        ACL_LEFT = -3,          // a + 1 == b
85
        ACL_RIGHT = 3           // a == b + 1
86
};
87
88
static void vcc_acl_insert_entry(struct vcc *, struct acl_e **);
89
90
/*
91
 * Compare two acl rules for relation
92
 */
93
94
#define CMP(n, a, b)                                                    \
95
        do {                                                            \
96
                if ((a) < (b))                                          \
97
                        return (enum acl_cmp_e)(-n);                    \
98
                else if ((b) < (a))                                     \
99
                        return (n);                                     \
100
        } while (0)
101
102
#define CMPA(a, b)                                                      \
103
        do {                                                            \
104
                if (((a) | 1) == (b))                                   \
105
                        return (ACL_LEFT);                              \
106
                else if (((b) | 1) == (a))                              \
107
                        return (ACL_RIGHT);                             \
108
        } while (0)
109
110
static void
111 240
vcl_acl_free(struct acl_e **aep)
112
{
113
        struct acl_e *a;
114
115 240
        TAKE_OBJ_NOTNULL(a, aep, VCC_ACL_E_MAGIC);
116 240
        free(a->addr);
117 240
        FREE_OBJ(a);
118 240
}
119
120
static enum acl_cmp_e
121 22240
vcl_acl_cmp(const struct acl_e *ae1, const struct acl_e *ae2)
122
{
123
        const unsigned char *p1, *p2;
124
        unsigned m;
125
        unsigned char a1, a2;
126
127 22240
        CHECK_OBJ_NOTNULL(ae1, VCC_ACL_E_MAGIC);
128 22240
        CHECK_OBJ_NOTNULL(ae2, VCC_ACL_E_MAGIC);
129
130 22240
        p1 = ae1->data;
131 22240
        p2 = ae2->data;
132 22240
        m = vmin_t(unsigned, ae1->mask, ae2->mask);
133 114000
        for (; m >= 8; m -= 8) {
134 104280
                if (m == 8 && ae1->mask == ae2->mask)
135 2280
                        CMPA(*p1, *p2);
136 195520
                CMP(ACL_GT, *p1, *p2);
137 91760
                p1++;
138 91760
                p2++;
139 91760
        }
140 9720
        if (m) {
141 9320
                assert (m < 8);
142 9320
                a1 = *p1 >> (8 - m);
143 9320
                a2 = *p2 >> (8 - m);
144 9320
                if (ae1->mask == ae2->mask)
145 2920
                        CMPA(a1, a2);
146 12440
                CMP(ACL_GT, a1, a2);
147 4280
        } else if (ae1->mask == ae2->mask) {
148 400
                CMPA(*p1, *p2);
149 200
        }
150
        /* Long mask is less than short mask */
151 4520
        CMP(ACL_CONTAINS, ae2->mask, ae1->mask);
152
153 240
        return (ACL_EQ);
154 22240
}
155
156
static int
157 4400
vcl_acl_disjoint(const struct acl_e *ae1, const struct acl_e *ae2)
158
{
159
        const unsigned char *p1, *p2;
160
        unsigned m;
161
162 4400
        CHECK_OBJ_NOTNULL(ae1, VCC_ACL_E_MAGIC);
163 4400
        CHECK_OBJ_NOTNULL(ae2, VCC_ACL_E_MAGIC);
164
165 4400
        p1 = ae1->data;
166 4400
        p2 = ae2->data;
167 4400
        m = vmin_t(unsigned, ae1->mask, ae2->mask);
168 31680
        for (; m >= 8; m -= 8) {
169 55880
                CMP(ACL_GT, *p1, *p2);
170 27280
                p1++;
171 27280
                p2++;
172 27280
        }
173 3080
        if (m) {
174 2880
                m = 0xff00 >> m;
175 2880
                m &= 0xff;
176 5360
                CMP(ACL_GT, *p1 & m, *p2 & m);
177 2480
        }
178 2680
        return (0);
179 4400
}
180
181 14720
VRBT_GENERATE_INSERT_COLOR(acl_tree, acl_e, branch, static)
182 7600
VRBT_GENERATE_INSERT_FINISH(acl_tree, acl_e, branch, static)
183 25560
VRBT_GENERATE_INSERT(acl_tree, acl_e, branch, vcl_acl_cmp, static)
184 1760
VRBT_GENERATE_REMOVE_COLOR(acl_tree, acl_e, branch, static)
185 3240
VRBT_GENERATE_REMOVE(acl_tree, acl_e, branch, static)
186 7680
VRBT_GENERATE_MINMAX(acl_tree, acl_e, branch, static)
187 24560
VRBT_GENERATE_NEXT(acl_tree, acl_e, branch, static)
188 18920
VRBT_GENERATE_PREV(acl_tree, acl_e, branch, static)
189
190
static char *
191 7320
vcc_acl_chk(struct vcc *tl, const struct acl_e *ae, const int l,
192
    unsigned char *p, int fam)
193
{
194
        const unsigned char *u;
195
        char h[VTCP_ADDRBUFSIZE];
196
        char t[VTCP_ADDRBUFSIZE + 10];
197 7320
        char s[vsa_suckaddr_len];
198 7320
        char *r = NULL;
199
        const struct suckaddr *sa;
200
        unsigned m;
201 7320
        int ll, ret = 0;
202
203 7320
        u = p;
204 7320
        ll = l;
205 7320
        m = ae->mask;
206
207 7320
        p += m / 8;
208 7320
        ll -= m / 8;
209 7320
        assert (ll >= 0);
210 7320
        m %= 8;
211
212 7320
        if (m && ((unsigned)*p << m & 0xff) != 0) {
213 160
                ret = 1;
214 160
                m = 0xff00 >> m;
215 160
                *p &= m;
216 160
        }
217 7320
        if (m) {
218 4000
                p++;
219 4000
                ll--;
220 4000
        }
221
222 13600
        for ( ; ll > 0; p++, ll--) {
223 6280
                if (*p == 0)
224 6080
                        continue;
225 200
                ret = 1;
226 200
                *p = 0;
227 200
        }
228 7320
        if (ret == 0)
229 6960
                return (NULL);
230
231 360
        sa = VSA_BuildFAP(s, fam, u, l, NULL, 0);
232 360
        AN(sa);
233 360
        VTCP_name(sa, h, sizeof h, NULL, 0);
234 360
        bprintf(t, "%s/%d", h, ae->mask);
235 360
        if (tl->acl->flag_pedantic != 0) {
236 80
                VSB_cat(tl->sb, "Non-zero bits in masked part, ");
237 80
                VSB_printf(tl->sb, "(maybe use %s ?)\n", t);
238 80
                vcc_ErrWhere(tl, ae->t_addr);
239 80
        }
240 360
        REPLACE(r, t);
241 360
        return (r);
242 7320
}
243
244
static void
245 8040
vcl_acl_fold(struct vcc *tl, struct acl_e **l, struct acl_e **r)
246
{
247
        enum acl_cmp_e cmp;
248
249 8040
        AN(l);
250 8040
        AN(r);
251 8040
        CHECK_OBJ_NOTNULL(*l, VCC_ACL_E_MAGIC);
252 8040
        CHECK_OBJ_NOTNULL(*r, VCC_ACL_E_MAGIC);
253
254 8040
        if ((*l)->not || (*r)->not)
255 4080
                return;
256
257 3960
        cmp = vcl_acl_cmp(*l, *r);
258
259 3960
        assert(cmp < 0);
260 3960
        if (cmp == ACL_LT)
261 2720
                return;
262
263 1240
        do {
264 1280
                switch (cmp) {
265
                case ACL_CONTAINED:
266 760
                        if (tl->acl->flag_fold_report) {
267 760
                                VSB_cat(tl->sb, "ACL entry:\n");
268 760
                                vcc_ErrWhere(tl, (*r)->t_addr);
269 760
                                VSB_cat(tl->sb, "supersedes / removes:\n");
270 760
                                vcc_ErrWhere(tl, (*l)->t_addr);
271 760
                                vcc_Warn(tl);
272 760
                        }
273 760
                        VRBT_REMOVE(acl_tree, &tl->acl->acl_tree, *l);
274 760
                        FREE_OBJ(*l);
275 760
                        *l = VRBT_PREV(acl_tree, &tl->acl->acl_tree, *r);
276 760
                        break;
277
                case ACL_LEFT:
278 520
                        (*l)->mask--;
279 520
                        (*l)->fixed = "folded";
280 520
                        if (tl->acl->flag_fold_report) {
281 440
                                VSB_cat(tl->sb, "ACL entry:\n");
282 440
                                vcc_ErrWhere(tl, (*l)->t_addr);
283 440
                                VSB_cat(tl->sb, "left of:\n");
284 440
                                vcc_ErrWhere(tl, (*r)->t_addr);
285 880
                                VSB_printf(tl->sb, "removing the latter and "
286
                                    "expanding mask of the former by one to "
287 440
                                    "/%u\n", (*l)->mask - 8);
288 440
                                vcc_Warn(tl);
289 440
                        }
290 520
                        VRBT_REMOVE(acl_tree, &tl->acl->acl_tree, *r);
291 520
                        FREE_OBJ(*r);
292 520
                        VRBT_REMOVE(acl_tree, &tl->acl->acl_tree, *l);
293 520
                        vcc_acl_insert_entry(tl, l);
294 520
                        return;
295
                default:
296 0
                        INCOMPL();
297 0
                }
298 760
                if (*l == NULL || *r == NULL || (*l)->not || (*r)->not)
299 440
                        break;
300 320
                cmp = vcl_acl_cmp(*l, *r);
301 320
        } while (cmp != ACL_LT);
302 8040
}
303
304
static void
305 7840
vcc_acl_insert_entry(struct vcc *tl, struct acl_e **aenp)
306
{
307
        struct acl_e *ae2, *l, *r;
308
309 7840
        CHECK_OBJ_NOTNULL(*aenp, VCC_ACL_E_MAGIC);
310 7840
        ae2 = VRBT_INSERT(acl_tree, &tl->acl->acl_tree, *aenp);
311 7840
        if (ae2 != NULL) {
312 240
                if (ae2->not != (*aenp)->not) {
313 40
                        VSB_cat(tl->sb, "Conflicting ACL entries:\n");
314 40
                        vcc_ErrWhere(tl, ae2->t_addr);
315 40
                        VSB_cat(tl->sb, "vs:\n");
316 40
                        vcc_ErrWhere(tl, (*aenp)->t_addr);
317 40
                }
318 240
                return;
319
        }
320
321 7600
        r = *aenp;
322 7600
        *aenp = NULL;
323
324 7600
        if (tl->acl->flag_fold == 0)
325 760
                return;
326
327 6840
        l = VRBT_PREV(acl_tree, &tl->acl->acl_tree, r);
328 6840
        if (l != NULL) {
329 5000
                vcl_acl_fold(tl, &l, &r);
330 5000
        }
331 6840
        if (r == NULL)
332 400
                return;
333 6440
        l = r;
334 6440
        r = VRBT_NEXT(acl_tree, &tl->acl->acl_tree, l);
335 6440
        if (r == NULL)
336 3400
                return;
337 3040
        vcl_acl_fold(tl, &l, &r);
338 7840
}
339
340
static void
341 7400
vcc_acl_add_entry(struct vcc *tl, const struct acl_e *ae, int l,
342
    unsigned char *u, int fam)
343
{
344
        struct acl_e *aen;
345
346 7400
        if (fam == PF_INET && ae->mask > 32) {
347 80
                VSB_printf(tl->sb,
348 40
                    "Too wide mask (/%u) for IPv4 address\n", ae->mask);
349 40
                if (ae->t_mask != NULL)
350 40
                        vcc_ErrWhere(tl, ae->t_mask);
351
                else
352 0
                        vcc_ErrWhere(tl, ae->t_addr);
353 40
                return;
354
        }
355 7360
        if (fam == PF_INET6 && ae->mask > 128) {
356 80
                VSB_printf(tl->sb,
357 40
                    "Too wide mask (/%u) for IPv6 address\n", ae->mask);
358 40
                vcc_ErrWhere(tl, ae->t_mask);
359 40
                return;
360
        }
361
362
        /* Make a copy from the template */
363 7320
        ALLOC_OBJ(aen, VCC_ACL_E_MAGIC);
364 7320
        AN(aen);
365 7320
        *aen = *ae;
366 7320
        aen->addr = strdup(ae->addr);
367 7320
        AN(aen->addr);
368
369 7320
        aen->fixed = vcc_acl_chk(tl, ae, l, u, fam);
370
371
        /* We treat family as part of address, it saves code */
372 7320
        assert(fam <= 0xff);
373 7320
        aen->data[0] = fam & 0xff;
374 7320
        aen->mask += 8;
375
376 7320
        assert(l + 1UL <= sizeof aen->data);
377 7320
        memcpy(aen->data + 1L, u, l);
378
379 7320
        vcc_acl_insert_entry(tl, &aen);
380 7320
        if (aen != NULL)
381 240
                vcl_acl_free(&aen);
382 7400
}
383
384
static void
385 2360
vcc_acl_try_getaddrinfo(struct vcc *tl, struct acl_e *ae)
386
{
387
        struct addrinfo *res0, *res, hint;
388
        struct sockaddr_in *sin4;
389
        struct sockaddr_in6 *sin6;
390
        unsigned char *u, i4, i6;
391
        int error;
392
393 2360
        CHECK_OBJ_NOTNULL(ae, VCC_ACL_E_MAGIC);
394 2360
        memset(&hint, 0, sizeof hint);
395 2360
        hint.ai_family = PF_UNSPEC;
396 2360
        hint.ai_socktype = SOCK_STREAM;
397 2360
        error = getaddrinfo(ae->addr, "0", &hint, &res0);
398 2360
        if (error) {
399 160
                if (ae->para) {
400 160
                        VSB_printf(tl->sb,
401
                            "Warning: %s ignored\n  -- %s\n",
402 80
                            ae->addr, gai_strerror(error));
403 160
                        Fh(tl, 1, "/* Ignored ACL entry: %s%s",
404 80
                            ae->para ? "\"(\" " : "", ae->not ? "\"!\" " : "");
405 80
                        EncToken(tl->fh, ae->t_addr);
406 80
                        if (ae->t_mask)
407 40
                                Fh(tl, 0, "/%u", ae->mask);
408 80
                        Fh(tl, 0, "%s\n", ae->para ? " \")\"" : "");
409 160
                        Fh(tl, 1, " * getaddrinfo:  %s */\n",
410 80
                             gai_strerror(error));
411 80
                } else {
412 160
                        VSB_printf(tl->sb,
413
                            "DNS lookup(%s): %s\n",
414 80
                            ae->addr, gai_strerror(error));
415 80
                        vcc_ErrWhere(tl, ae->t_addr);
416
                }
417 160
                return;
418
        }
419
420 2200
        i4 = i6 = 0;
421 4560
        for (res = res0; res != NULL; res = res->ai_next) {
422 2360
                switch (res->ai_family) {
423
                case PF_INET:
424 160
                        i4++;
425 160
                        break;
426
                case PF_INET6:
427 2200
                        i6++;
428 2200
                        break;
429
                default:
430 0
                        VSB_printf(tl->sb,
431
                            "Ignoring unknown protocol family (%d) for %.*s\n",
432 0
                                res->ai_family, PF(ae->t_addr));
433 0
                        continue;
434
                }
435 2360
        }
436
437 2200
        if (ae->t_mask != NULL && i4 > 0 && i6 > 0) {
438 0
                VSB_printf(tl->sb,
439
                    "Mask (/%u) specified, but string resolves to"
440 0
                    " both IPv4 and IPv6 addresses.\n", ae->mask);
441 0
                vcc_ErrWhere(tl, ae->t_mask);
442 0
                freeaddrinfo(res0);
443 0
                return;
444
        }
445
446 4480
        for (res = res0; res != NULL; res = res->ai_next) {
447 2360
                switch (res->ai_family) {
448
                case PF_INET:
449 160
                        assert(PF_INET < 256);
450 160
                        sin4 = (void*)res->ai_addr;
451 160
                        assert(sizeof(sin4->sin_addr) == 4);
452 160
                        u = (void*)&sin4->sin_addr;
453 160
                        if (ae->t_mask == NULL)
454 160
                                ae->mask = 32;
455 160
                        vcc_acl_add_entry(tl, ae, 4, u, res->ai_family);
456 160
                        break;
457
                case PF_INET6:
458 2200
                        assert(PF_INET6 < 256);
459 2200
                        sin6 = (void*)res->ai_addr;
460 2200
                        assert(sizeof(sin6->sin6_addr) == 16);
461 2200
                        u = (void*)&sin6->sin6_addr;
462 2200
                        if (ae->t_mask == NULL)
463 400
                                ae->mask = 128;
464 2200
                        vcc_acl_add_entry(tl, ae, 16, u, res->ai_family);
465 2200
                        break;
466
                default:
467 0
                        continue;
468
                }
469 2360
                if (tl->err)
470 80
                        freeaddrinfo(res0);
471 2360
                ERRCHK(tl);
472 2280
        }
473 2120
        freeaddrinfo(res0);
474
475 2360
}
476
477
/*--------------------------------------------------------------------
478
 * Ancient stupidity on the part of X/Open and other standards orgs
479
 * dictate that "192.168" be translated to 192.0.0.168.  Ever since
480
 * CIDR happened, "192.168/16" notation has been used, but apparently
481
 * no API supports parsing this, so roll our own.
482
 */
483
484
static int
485 7400
vcc_acl_try_netnotation(struct vcc *tl, struct acl_e *ae)
486
{
487
        unsigned char b[4];
488
        int i, j, k;
489
        unsigned u;
490
        const char *p;
491
492 7400
        CHECK_OBJ_NOTNULL(ae, VCC_ACL_E_MAGIC);
493 7400
        memset(b, 0, sizeof b);
494 7400
        p = ae->addr;
495 21760
        for (i = 0; i < 4; i++) {
496 21760
                j = sscanf(p, "%u%n", &u, &k);
497 21760
                if (j != 1)
498 2160
                        return (0);
499 19600
                if (u & ~0xff)
500 80
                        return (0);
501 19520
                b[i] = (unsigned char)u;
502 19520
                if (p[k] == '\0')
503 5040
                        break;
504 14480
                if (p[k] != '.')
505 120
                        return (0);
506 14360
                p += k + 1;
507 14360
        }
508 5040
        if (ae->t_mask == NULL)
509 1120
                ae->mask = 8 + 8 * i;
510 5040
        vcc_acl_add_entry(tl, ae, 4, b, AF_INET);
511 5040
        return (1);
512 7400
}
513
514
static void
515 7560
vcc_acl_entry(struct vcc *tl)
516
{
517
        struct acl_e ae[1];
518
        char *sl, *e;
519
520 7560
        INIT_OBJ(ae, VCC_ACL_E_MAGIC);
521
522 7560
        if (tl->t->tok == '!') {
523 1680
                ae->not = 1;
524 1680
                vcc_NextToken(tl);
525 1680
        }
526
527 7560
        if (tl->t->tok == '(') {
528 120
                ae->para = 1;
529 120
                vcc_NextToken(tl);
530 120
        }
531
532 7560
        if (!ae->not && tl->t->tok == '!') {
533 40
                ae->not = 1;
534 40
                vcc_NextToken(tl);
535 40
        }
536
537 7560
        ExpectErr(tl, CSTR);
538 7560
        ae->t_addr = tl->t;
539 7560
        ae->addr = ae->t_addr->dec;
540 7560
        vcc_NextToken(tl);
541
542 7560
        if (strchr(ae->t_addr->dec, '/') != NULL) {
543 120
                sl = strchr(ae->addr, '/');
544 120
                AN(sl);
545 120
                *sl++ = '\0';
546 120
                e = NULL;
547 120
                ae->mask = strtoul(sl, &e, 10);
548 120
                if (*e != '\0') {
549 80
                        VSB_cat(tl->sb, ".../mask is not numeric.\n");
550 80
                        vcc_ErrWhere(tl, ae->t_addr);
551 80
                        return;
552
                }
553 40
                ae->t_mask = ae->t_addr;
554 40
                if (tl->t->tok == '/') {
555 40
                        VSB_cat(tl->sb, "/mask only allowed once.\n");
556 40
                        vcc_ErrWhere(tl, tl->t);
557 40
                        return;
558
                }
559 7440
        } else if (tl->t->tok == '/') {
560 5760
                vcc_NextToken(tl);
561 5760
                ae->t_mask = tl->t;
562 5760
                ExpectErr(tl, CNUM);
563 5760
                ae->mask = vcc_UintVal(tl);
564 5760
        }
565
566 7440
        if (ae->para)
567 120
                SkipToken(tl, ')');
568
569 7400
        if (!vcc_acl_try_netnotation(tl, ae)) {
570 2360
                ERRCHK(tl);
571 2360
                vcc_acl_try_getaddrinfo(tl, ae);
572 2360
        }
573 7400
        ERRCHK(tl);
574 7560
}
575
576
/*********************************************************************
577
 * Emit the tokens making up an entry as C-strings
578
 */
579
580
static void
581 2160
vcc_acl_emit_tokens(const struct vcc *tl, const struct acl_e *ae)
582
{
583
        struct token *t;
584 2160
        const char *sep = "";
585
586 2160
        CHECK_OBJ_NOTNULL(ae, VCC_ACL_E_MAGIC);
587 2160
        t = ae->t_addr;
588 2160
        do {
589 6320
                if (t->tok == CSTR) {
590 2160
                        Fh(tl, 0, "%s\"\\\"\" ", sep);
591 2160
                        EncToken(tl->fh, t);
592 2160
                        Fh(tl, 0, " \"\\\"\"");
593 6320
                } else if (t == ae->t_mask) {
594 2080
                        Fh(tl, 0, " \"%u\"", ae->mask - 8);
595 2080
                } else {
596 2080
                        Fh(tl, 0, "%s\"%.*s\"", sep, PF(t));
597
                }
598 6320
                if (t == ae->t_mask)
599 2080
                        break;
600 4240
                t = vcc_PeekTokenFrom(tl, t);
601 4240
                AN(t);
602 4240
                sep = " ";
603 4240
        } while (ae->t_mask != NULL);
604 2160
        if (ae->fixed)
605 440
                Fh(tl, 0, "\" fixed: %s\"", ae->fixed);
606 2160
}
607
608
/*********************************************************************
609
 * Emit ACL on table format
610
 */
611
612
static unsigned
613 80
vcc_acl_emit_tables(const struct vcc *tl, unsigned n, const char *name)
614
{
615
        struct acl_e *ae;
616 80
        unsigned rv = sizeof(ae->data) + 3;
617 80
        unsigned nn = 0;
618
        size_t sz;
619
620 160
        Fh(tl, 0, "\nstatic unsigned char acl_tbl_%s[%u*%u] = {\n",
621 80
            name, n, rv);
622 1840
        VRBT_FOREACH(ae, acl_tree, &tl->acl->acl_tree) {
623 1760
                if (ae->overlapped)
624 1440
                        continue;
625 320
                Fh(tl, 0, "\t0x%02x,", ae->not ? 0 : 1);
626 320
                Fh(tl, 0, "0x%02x,", (ae->mask >> 3) - 1);
627 320
                Fh(tl, 0, "0x%02x,", (0xff00 >> (ae->mask & 7)) & 0xff);
628 5760
                for (sz = 0; sz < sizeof(ae->data); sz++)
629 5440
                        Fh(tl, 0, "0x%02x,", ae->data[sz]);
630 320
                for (; sz < rv - 3; sz++)
631 0
                        Fh(tl, 0, "0,");
632 320
                Fh(tl, 0, "\n");
633 320
                nn++;
634 320
        }
635 80
        assert(n == nn);
636 80
        Fh(tl, 0, "};\n");
637 80
        if (tl->acl->flag_log) {
638 80
                Fh(tl, 0, "\nstatic const char *acl_str_%s[%d] = {\n",
639 40
                    name, n);
640 920
                VRBT_FOREACH(ae, acl_tree, &tl->acl->acl_tree) {
641 880
                        if (ae->overlapped)
642 720
                                continue;
643 160
                        Fh(tl, 0, "\t");
644 320
                        Fh(tl, 0, "\"%sMATCH %s \" ",
645 160
                            ae->not ? "NEG_" : "", name);
646 160
                        vcc_acl_emit_tokens(tl, ae);
647 160
                        Fh(tl, 0, ",\n");
648 160
                }
649 40
                Fh(tl, 0, "};\n");
650 40
        }
651 80
        return (rv);
652
}
653
654
/*********************************************************************
655
 * Emit a function to match the ACL we have collected
656
 */
657
658
static void
659 1280
vcc_acl_emit(struct vcc *tl, const struct symbol *sym)
660
{
661
        struct acl_e *ae, *ae2;
662
        int depth, l, m, i;
663
        unsigned at[ACL_MAXADDR];
664 1280
        struct inifin *ifp = NULL;
665
        struct vsb *func;
666 1280
        unsigned n, no, nw = 0;
667
668 1280
        func = VSB_new_auto();
669 1280
        AN(func);
670 1280
        VSB_cat(func, "match_acl_");
671 1280
        VCC_PrintCName(func, sym->name, NULL);
672 1280
        AZ(VSB_finish(func));
673
674 1280
        depth = -1;
675 1280
        at[0] = 256;
676 1280
        ae2 = NULL;
677 1280
        n = no = 0;
678 6920
        VRBT_FOREACH_REVERSE(ae, acl_tree, &tl->acl->acl_tree) {
679 5640
                n++;
680 5640
                if (ae2 == NULL) {
681 1240
                        ae2 = ae;
682 5640
                } else if (vcl_acl_disjoint(ae, ae2)) {
683 1720
                        ae2 = ae;
684 1720
                } else {
685 2680
                        no++;
686 2680
                        ae->overlapped = 1;
687
                }
688 5640
        }
689
690 1280
        Fh(tl, 0, "/* acl_n_%s n %u no %u */\n", sym->name, n, no);
691 1280
        if (n - no < (1<<1))
692 640
                no = n;
693 640
        else if (!tl->acl->flag_table)
694 560
                no = n;
695
696 1280
        if (no < n)
697 80
                nw = vcc_acl_emit_tables(tl, n - no, sym->name);
698
699
700 1280
        Fh(tl, 0, "\nstatic int v_matchproto_(acl_match_f)\n");
701 1280
        Fh(tl, 0, "%s(VRT_CTX, const VCL_IP p)\n", VSB_data(func));
702 1280
        Fh(tl, 0, "{\n");
703 1280
        Fh(tl, 0, "\tconst unsigned char *a;\n");
704 1280
        Fh(tl, 0, "\tint fam;\n");
705 1280
        Fh(tl, 0, "\n");
706 1280
        Fh(tl, 0, "\tfam = VRT_VSA_GetPtr(ctx, p, &a);\n");
707 1280
        Fh(tl, 0, "\tif (fam < 0) {\n");
708 1280
        Fh(tl, 0, "\t\tVRT_fail(ctx,");
709 1280
        Fh(tl, 0, " \"ACL %s: no protocol family\");\n", sym->name);
710 1280
        Fh(tl, 0, "\t\treturn(0);\n");
711 1280
        Fh(tl, 0, "\t}\n\n");
712 1280
        if (!tl->err_unref) {
713 80
                ifp = New_IniFin(tl);
714 160
                VSB_printf(ifp->ini,
715 80
                        "\t(void)%s;\n", VSB_data(func));
716 80
        }
717
718 6920
        VRBT_FOREACH(ae, acl_tree, &tl->acl->acl_tree) {
719
720 5640
                if (no < n && !ae->overlapped)
721 320
                        continue;
722
723
                /* Find how much common prefix we have */
724 29600
                for (l = 0; l <= depth && l * 8 < (int)ae->mask - 7; l++) {
725 26320
                        assert(l >= 0);
726 26320
                        if (ae->data[l] != at[l])
727 2040
                                break;
728 24280
                }
729
730
                /* Back down, if necessary */
731 12520
                while (l <= depth) {
732 7200
                        Fh(tl, 0, "\t%*s}\n", -depth, "");
733 7200
                        depth--;
734
                }
735
736 5320
                m = (int)ae->mask;
737 5320
                assert(m >= l*8);
738 5320
                m -= l * 8;
739
740
                /* Do whole byte compares */
741 20960
                for (i = l; m >= 8; m -= 8, i++) {
742 15640
                        if (i == 0)
743 3600
                                Fh(tl, 0, "\t%*s%sif (fam == %d) {\n",
744 1800
                                    -i, "", "", ae->data[i]);
745
                        else
746 27680
                                Fh(tl, 0, "\t%*s%sif (a[%d] == %d) {\n",
747 13840
                                    -i, "", "", i - 1, ae->data[i]);
748 15640
                        at[i] = ae->data[i];
749 15640
                        depth = i;
750 15640
                }
751
752 5320
                if (m > 0) {
753
                        // XXX can remove masking due to fixup
754
                        /* Do fractional byte compares */
755 6000
                        Fh(tl, 0, "\t%*s%sif ((a[%d] & 0x%x) == %d) {\n",
756 3000
                            -i, "", "", i - 1, (0xff00 >> m) & 0xff,
757 3000
                            ae->data[i] & ((0xff00 >> m) & 0xff));
758 3000
                        at[i] = 256;
759 3000
                        depth = i;
760 3000
                }
761
762 5320
                i = ((int)ae->mask + 7) / 8;
763
764 5320
                if (tl->acl->flag_log) {
765 4000
                        Fh(tl, 0, "\t%*sVPI_acl_log(ctx, \"%sMATCH %s \" ",
766 2000
                            -i, "", ae->not ? "NEG_" : "", sym->name);
767 2000
                        vcc_acl_emit_tokens(tl, ae);
768 2000
                        Fh(tl, 0, ");\n");
769 2000
                }
770
771 5320
                Fh(tl, 0, "\t%*sreturn (%d);\n", -i, "", ae->not ? 0 : 1);
772 5320
        }
773
774
        /* Unwind */
775 12720
        for (; 0 <= depth; depth--)
776 11440
                Fh(tl, 0, "\t%*.*s}\n", depth, depth, "");
777
778 1280
        if (no < n) {
779 80
                Fh(tl, 0, "\treturn(\n\t    VPI_acl_table(ctx,\n");
780 80
                Fh(tl, 0, "\t\tp,\n");
781 80
                Fh(tl, 0, "\t\t%u, %u,\n", n - no, nw);
782 80
                Fh(tl, 0, "\t\tacl_tbl_%s,\n", sym->name);
783 80
                if (tl->acl->flag_log)
784 40
                        Fh(tl, 0, "\t\tacl_str_%s,\n", sym->name);
785
                else
786 40
                        Fh(tl, 0, "\t\tNULL,\n");
787 80
                Fh(tl, 0, "\t\t\"NO MATCH %s\"\n\t    )\n\t);\n", sym->name);
788 80
        } else {
789
                /* Deny by default */
790 1200
                if (tl->acl->flag_log)
791 400
                        Fh(tl, 0, "\tVPI_acl_log(ctx, \"NO_MATCH %s\");\n",
792 200
                            sym->name);
793 1200
                Fh(tl, 0, "\treturn(0);\n");
794
        }
795 1280
        Fh(tl, 0, "}\n");
796
797
        /* Emit the struct that will be referenced */
798 1280
        Fh(tl, 0, "\nstatic const struct vrt_acl %s[] = {{\n", sym->rname);
799 1280
        Fh(tl, 0, "\t.magic = VRT_ACL_MAGIC,\n");
800 1280
        Fh(tl, 0, "\t.match = &%s,\n", VSB_data(func));
801 1280
        Fh(tl, 0, "\t.name = \"%s\",\n", sym->name);
802 1280
        Fh(tl, 0, "}};\n\n");
803 1280
        if (!tl->err_unref) {
804 80
                AN(ifp);
805 80
                VSB_printf(ifp->ini, "\t(void)%s;", sym->rname);
806 80
        }
807 1280
        VSB_destroy(&func);
808 1280
}
809
810
static void
811 240
vcc_parseAclFold(struct vcc *tl, int sign)
812
{
813
        struct acl *acl;
814
815 240
        CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
816 240
        assert(vcc_IdIs(tl->t, "fold"));
817 240
        acl = tl->acl;
818 240
        CHECK_OBJ_NOTNULL(acl, VCC_ACL_MAGIC);
819
820 240
        acl->flag_fold = sign;
821 240
        acl->flag_fold_report = 1;
822 240
        vcc_NextToken(tl);
823 240
        if (tl->t->tok != '(')
824 120
                return;
825
826 120
        if (! acl->flag_fold) {
827 40
                VSB_cat(tl->sb, "-fold(...) is invalid, use -fold:\n");
828 40
                vcc_ErrWhere(tl, tl->t);
829 40
                return;
830
        }
831
832 80
        SkipToken(tl, '(');
833
834
#define FOLD_SUBFLAGS_MSG "The only ACL fold sub-flag is `report`:\n"
835
836 80
        sign = vcc_IsFlag(tl);
837 80
        if (tl->err) {
838 0
                VSB_cat(tl->sb, FOLD_SUBFLAGS_MSG);
839 0
                return;
840
        }
841 80
        if (sign < 0)
842 0
                return;
843
844 80
        if (! vcc_IdIs(tl->t, "report")) {
845 40
                VSB_cat(tl->sb, FOLD_SUBFLAGS_MSG);
846 40
                vcc_ErrWhere(tl, tl->t);
847 40
                return;
848
        }
849
850 40
        acl->flag_fold_report = sign;
851
852 40
        vcc_NextToken(tl);
853 40
        SkipToken(tl, ')');
854 240
}
855
856
void
857 1960
vcc_ParseAcl(struct vcc *tl)
858
{
859
        struct symbol *sym;
860
        int sign;
861
        struct acl acl[1];
862
863 1960
        INIT_OBJ(acl, VCC_ACL_MAGIC);
864 1960
        tl->acl = acl;
865 1960
        acl->flag_pedantic = 1;
866 1960
        acl->flag_fold = 1;
867 1960
        acl->flag_fold_report = 1;
868 1960
        vcc_NextToken(tl);
869 1960
        VRBT_INIT(&acl->acl_tree);
870
871 1960
        vcc_ExpectVid(tl, "ACL");
872 1960
        ERRCHK(tl);
873 1920
        sym = VCC_HandleSymbol(tl, ACL);
874 1920
        ERRCHK(tl);
875 1920
        AN(sym);
876
877
#define FLAGS_MSG "Valid ACL flags are `log`, `fold`, `pedantic` and `table`:\n"
878
879 2920
        while (1) {
880 2920
                sign = vcc_IsFlag(tl);
881 2920
                if (tl->err) {
882 40
                        VSB_cat(tl->sb, FLAGS_MSG);
883 40
                        return;
884
                }
885 2880
                if (sign < 0)
886 1760
                        break;
887 1120
                if (vcc_IdIs(tl->t, "log")) {
888 320
                        acl->flag_log = sign;
889 320
                        vcc_NextToken(tl);
890 1120
                } else if (vcc_IdIs(tl->t, "fold")) {
891 240
                        vcc_parseAclFold(tl, sign);
892 240
                        if (tl->err)
893 80
                                return;
894 720
                } else if (vcc_IdIs(tl->t, "pedantic")) {
895 440
                        acl->flag_pedantic = sign;
896 440
                        vcc_NextToken(tl);
897 560
                } else if (vcc_IdIs(tl->t, "table")) {
898 80
                        acl->flag_table = sign;
899 80
                        vcc_NextToken(tl);
900 80
                } else {
901 40
                        VSB_cat(tl->sb, "Unknown ACL flag. " FLAGS_MSG);
902 40
                        vcc_ErrWhere(tl, tl->t);
903 40
                        return;
904
                }
905
        }
906
907
#undef FLAGS_MSG
908
909 1760
        SkipToken(tl, '{');
910
911 8840
        while (tl->t->tok != '}') {
912 7560
                vcc_acl_entry(tl);
913 7560
                ERRCHK(tl);
914 7120
                SkipToken(tl, ';');
915
        }
916 1280
        SkipToken(tl, '}');
917
918 1280
        vcc_acl_emit(tl, sym);
919 1960
}