]> git.proxmox.com Git - mirror_frr.git/blame - lib/filter.c
Merge pull request #7343 from ton31337/fix/prefix2str_to_pFX
[mirror_frr.git] / lib / filter.c
CommitLineData
718e3744 1/* Route filtering function.
2 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 19 */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "filter.h"
25#include "memory.h"
26#include "command.h"
27#include "sockunion.h"
28#include "buffer.h"
fbf5d033 29#include "log.h"
518f0eb1 30#include "routemap.h"
b85120bc 31#include "libfrr.h"
1d3c4b66 32#include "northbound_cli.h"
718e3744 33
d62a17ae 34DEFINE_MTYPE_STATIC(LIB, ACCESS_LIST, "Access List")
4a1ab8e4 35DEFINE_MTYPE_STATIC(LIB, ACCESS_LIST_STR, "Access List Str")
d62a17ae 36DEFINE_MTYPE_STATIC(LIB, ACCESS_FILTER, "Access Filter")
37
b34fd35d 38/* Static structure for mac access_list's master. */
d37ba549
MK
39static struct access_master access_master_mac = {
40 {NULL, NULL},
41 {NULL, NULL},
42 NULL,
43 NULL,
44};
45
718e3744 46/* Static structure for IPv4 access_list's master. */
d62a17ae 47static struct access_master access_master_ipv4 = {
48 {NULL, NULL},
49 {NULL, NULL},
50 NULL,
51 NULL,
718e3744 52};
53
718e3744 54/* Static structure for IPv6 access_list's master. */
d62a17ae 55static struct access_master access_master_ipv6 = {
56 {NULL, NULL},
57 {NULL, NULL},
58 NULL,
59 NULL,
718e3744 60};
6b0655a2 61
d62a17ae 62static struct access_master *access_master_get(afi_t afi)
718e3744 63{
d62a17ae 64 if (afi == AFI_IP)
65 return &access_master_ipv4;
66 else if (afi == AFI_IP6)
67 return &access_master_ipv6;
d37ba549
MK
68 else if (afi == AFI_L2VPN)
69 return &access_master_mac;
d62a17ae 70 return NULL;
718e3744 71}
72
73/* Allocate new filter structure. */
4cf24501 74struct filter *filter_new(void)
718e3744 75{
9f5dc319 76 return XCALLOC(MTYPE_ACCESS_FILTER, sizeof(struct filter));
718e3744 77}
78
d62a17ae 79static void filter_free(struct filter *filter)
718e3744 80{
d62a17ae 81 XFREE(MTYPE_ACCESS_FILTER, filter);
718e3744 82}
83
84/* Return string of filter_type. */
d62a17ae 85static const char *filter_type_str(struct filter *filter)
86{
87 switch (filter->type) {
88 case FILTER_PERMIT:
89 return "permit";
d62a17ae 90 case FILTER_DENY:
91 return "deny";
d62a17ae 92 case FILTER_DYNAMIC:
93 return "dynamic";
d62a17ae 94 default:
95 return "";
d62a17ae 96 }
718e3744 97}
98
99/* If filter match to the prefix then return 1. */
123214ef 100static int filter_match_cisco(struct filter *mfilter, const struct prefix *p)
718e3744 101{
d62a17ae 102 struct filter_cisco *filter;
103 struct in_addr mask;
d7c0a89a
QY
104 uint32_t check_addr;
105 uint32_t check_mask;
718e3744 106
d62a17ae 107 filter = &mfilter->u.cfilter;
108 check_addr = p->u.prefix4.s_addr & ~filter->addr_mask.s_addr;
718e3744 109
d62a17ae 110 if (filter->extended) {
111 masklen2ip(p->prefixlen, &mask);
112 check_mask = mask.s_addr & ~filter->mask_mask.s_addr;
718e3744 113
d62a17ae 114 if (memcmp(&check_addr, &filter->addr.s_addr, 4) == 0
115 && memcmp(&check_mask, &filter->mask.s_addr, 4) == 0)
116 return 1;
117 } else if (memcmp(&check_addr, &filter->addr.s_addr, 4) == 0)
118 return 1;
718e3744 119
d62a17ae 120 return 0;
718e3744 121}
122
123/* If filter match to the prefix then return 1. */
123214ef 124static int filter_match_zebra(struct filter *mfilter, const struct prefix *p)
718e3744 125{
d37ba549 126 struct filter_zebra *filter = NULL;
718e3744 127
d62a17ae 128 filter = &mfilter->u.zfilter;
718e3744 129
3b0f6068
DL
130 if (filter->prefix.family == p->family) {
131 if (filter->exact) {
132 if (filter->prefix.prefixlen == p->prefixlen)
d62a17ae 133 return prefix_match(&filter->prefix, p);
3b0f6068
DL
134 else
135 return 0;
d62a17ae 136 } else
3b0f6068
DL
137 return prefix_match(&filter->prefix, p);
138 } else
139 return 0;
718e3744 140}
6b0655a2 141
718e3744 142/* Allocate new access list structure. */
d62a17ae 143static struct access_list *access_list_new(void)
718e3744 144{
9f5dc319 145 return XCALLOC(MTYPE_ACCESS_LIST, sizeof(struct access_list));
718e3744 146}
147
148/* Free allocated access_list. */
d62a17ae 149static void access_list_free(struct access_list *access)
718e3744 150{
d62a17ae 151 XFREE(MTYPE_ACCESS_LIST, access);
718e3744 152}
153
154/* Delete access_list from access_master and free it. */
4cf24501 155void access_list_delete(struct access_list *access)
718e3744 156{
d62a17ae 157 struct filter *filter;
158 struct filter *next;
159 struct access_list_list *list;
160 struct access_master *master;
718e3744 161
d62a17ae 162 for (filter = access->head; filter; filter = next) {
163 next = filter->next;
164 filter_free(filter);
165 }
718e3744 166
d62a17ae 167 master = access->master;
718e3744 168
d62a17ae 169 if (access->type == ACCESS_TYPE_NUMBER)
170 list = &master->num;
171 else
172 list = &master->str;
718e3744 173
d62a17ae 174 if (access->next)
175 access->next->prev = access->prev;
176 else
177 list->tail = access->prev;
718e3744 178
d62a17ae 179 if (access->prev)
180 access->prev->next = access->next;
181 else
182 list->head = access->next;
718e3744 183
0a22ddfb 184 XFREE(MTYPE_ACCESS_LIST_STR, access->name);
718e3744 185
0a22ddfb 186 XFREE(MTYPE_TMP, access->remark);
718e3744 187
d62a17ae 188 access_list_free(access);
718e3744 189}
190
191/* Insert new access list to list of access_list. Each acceess_list
192 is sorted by the name. */
d62a17ae 193static struct access_list *access_list_insert(afi_t afi, const char *name)
194{
195 unsigned int i;
196 long number;
197 struct access_list *access;
198 struct access_list *point;
199 struct access_list_list *alist;
200 struct access_master *master;
201
202 master = access_master_get(afi);
203 if (master == NULL)
204 return NULL;
205
206 /* Allocate new access_list and copy given name. */
207 access = access_list_new();
208 access->name = XSTRDUP(MTYPE_ACCESS_LIST_STR, name);
209 access->master = master;
210
211 /* If name is made by all digit character. We treat it as
212 number. */
213 for (number = 0, i = 0; i < strlen(name); i++) {
fefa5e0f 214 if (isdigit((unsigned char)name[i]))
d62a17ae 215 number = (number * 10) + (name[i] - '0');
216 else
217 break;
218 }
219
220 /* In case of name is all digit character */
221 if (i == strlen(name)) {
222 access->type = ACCESS_TYPE_NUMBER;
223
224 /* Set access_list to number list. */
225 alist = &master->num;
226
227 for (point = alist->head; point; point = point->next)
228 if (atol(point->name) >= number)
229 break;
230 } else {
231 access->type = ACCESS_TYPE_STRING;
232
233 /* Set access_list to string list. */
234 alist = &master->str;
235
236 /* Set point to insertion point. */
237 for (point = alist->head; point; point = point->next)
238 if (strcmp(point->name, name) >= 0)
239 break;
240 }
241
242 /* In case of this is the first element of master. */
243 if (alist->head == NULL) {
244 alist->head = alist->tail = access;
245 return access;
246 }
247
248 /* In case of insertion is made at the tail of access_list. */
249 if (point == NULL) {
250 access->prev = alist->tail;
251 alist->tail->next = access;
252 alist->tail = access;
253 return access;
254 }
255
256 /* In case of insertion is made at the head of access_list. */
257 if (point == alist->head) {
258 access->next = alist->head;
259 alist->head->prev = access;
260 alist->head = access;
261 return access;
262 }
263
264 /* Insertion is made at middle of the access_list. */
265 access->next = point;
266 access->prev = point->prev;
267
268 if (point->prev)
269 point->prev->next = access;
270 point->prev = access;
271
272 return access;
718e3744 273}
274
275/* Lookup access_list from list of access_list by name. */
d62a17ae 276struct access_list *access_list_lookup(afi_t afi, const char *name)
718e3744 277{
d62a17ae 278 struct access_list *access;
279 struct access_master *master;
718e3744 280
d62a17ae 281 if (name == NULL)
282 return NULL;
718e3744 283
d62a17ae 284 master = access_master_get(afi);
285 if (master == NULL)
286 return NULL;
718e3744 287
d62a17ae 288 for (access = master->num.head; access; access = access->next)
289 if (strcmp(access->name, name) == 0)
290 return access;
718e3744 291
d62a17ae 292 for (access = master->str.head; access; access = access->next)
293 if (strcmp(access->name, name) == 0)
294 return access;
718e3744 295
d62a17ae 296 return NULL;
718e3744 297}
298
299/* Get access list from list of access_list. If there isn't matched
300 access_list create new one and return it. */
4cf24501 301struct access_list *access_list_get(afi_t afi, const char *name)
718e3744 302{
d62a17ae 303 struct access_list *access;
718e3744 304
d62a17ae 305 access = access_list_lookup(afi, name);
306 if (access == NULL)
307 access = access_list_insert(afi, name);
308 return access;
718e3744 309}
310
311/* Apply access list to object (which should be struct prefix *). */
123214ef
MS
312enum filter_type access_list_apply(struct access_list *access,
313 const void *object)
718e3744 314{
d62a17ae 315 struct filter *filter;
123214ef 316 const struct prefix *p = (const struct prefix *)object;
718e3744 317
d62a17ae 318 if (access == NULL)
319 return FILTER_DENY;
718e3744 320
d62a17ae 321 for (filter = access->head; filter; filter = filter->next) {
322 if (filter->cisco) {
323 if (filter_match_cisco(filter, p))
324 return filter->type;
325 } else {
0f6476cc 326 if (filter_match_zebra(filter, p))
d62a17ae 327 return filter->type;
328 }
718e3744 329 }
718e3744 330
d62a17ae 331 return FILTER_DENY;
718e3744 332}
333
334/* Add hook function. */
d62a17ae 335void access_list_add_hook(void (*func)(struct access_list *access))
718e3744 336{
d62a17ae 337 access_master_ipv4.add_hook = func;
338 access_master_ipv6.add_hook = func;
d37ba549 339 access_master_mac.add_hook = func;
718e3744 340}
341
342/* Delete hook function. */
d62a17ae 343void access_list_delete_hook(void (*func)(struct access_list *access))
718e3744 344{
d62a17ae 345 access_master_ipv4.delete_hook = func;
346 access_master_ipv6.delete_hook = func;
d37ba549 347 access_master_mac.delete_hook = func;
718e3744 348}
349
358189ad 350/* Calculate new sequential number. */
4cf24501 351int64_t filter_new_seq_get(struct access_list *access)
718e3744 352{
358189ad
DA
353 int64_t maxseq;
354 int64_t newseq;
355 struct filter *filter;
718e3744 356
5037cc3e 357 maxseq = 0;
718e3744 358
358189ad
DA
359 for (filter = access->head; filter; filter = filter->next) {
360 if (maxseq < filter->seq)
361 maxseq = filter->seq;
362 }
363
364 newseq = ((maxseq / 5) * 5) + 5;
365
366 return (newseq > UINT_MAX) ? UINT_MAX : newseq;
367}
368
369/* Return access list entry which has same seq number. */
370static struct filter *filter_seq_check(struct access_list *access,
371 int64_t seq)
372{
373 struct filter *filter;
374
375 for (filter = access->head; filter; filter = filter->next)
376 if (filter->seq == seq)
377 return filter;
378 return NULL;
718e3744 379}
380
718e3744 381/* Delete filter from specified access_list. If there is hook
382 function execute it. */
4cf24501
RZ
383void access_list_filter_delete(struct access_list *access,
384 struct filter *filter)
718e3744 385{
d62a17ae 386 struct access_master *master;
718e3744 387
d62a17ae 388 master = access->master;
718e3744 389
d62a17ae 390 if (filter->next)
391 filter->next->prev = filter->prev;
392 else
393 access->tail = filter->prev;
718e3744 394
d62a17ae 395 if (filter->prev)
396 filter->prev->next = filter->next;
397 else
398 access->head = filter->next;
718e3744 399
d62a17ae 400 filter_free(filter);
718e3744 401
d62a17ae 402 route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_DELETED);
403 /* Run hook function. */
404 if (master->delete_hook)
405 (*master->delete_hook)(access);
718e3744 406}
6b0655a2 407
358189ad 408/* Add new filter to the end of specified access_list. */
4cf24501
RZ
409void access_list_filter_add(struct access_list *access,
410 struct filter *filter)
358189ad
DA
411{
412 struct filter *replace;
413 struct filter *point;
414
415 /* Automatic asignment of seq no. */
416 if (filter->seq == -1)
417 filter->seq = filter_new_seq_get(access);
418
419 if (access->tail && filter->seq > access->tail->seq)
420 point = NULL;
421 else {
422 /* Is there any same seq access list filter? */
423 replace = filter_seq_check(access, filter->seq);
424 if (replace)
425 access_list_filter_delete(access, replace);
426
427 /* Check insert point. */
428 for (point = access->head; point; point = point->next)
429 if (point->seq >= filter->seq)
430 break;
431 }
432
433 /* In case of this is the first element of the list. */
434 filter->next = point;
435
436 if (point) {
437 if (point->prev)
438 point->prev->next = filter;
439 else
440 access->head = filter;
441
442 filter->prev = point->prev;
443 point->prev = filter;
444 } else {
445 if (access->tail)
446 access->tail->next = filter;
447 else
448 access->head = filter;
449
450 filter->prev = access->tail;
451 access->tail = filter;
452 }
453
454 /* Run hook function. */
455 if (access->master->add_hook)
456 (*access->master->add_hook)(access);
457 route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_ADDED);
458}
459
718e3744 460/*
461 deny Specify packets to reject
462 permit Specify packets to forward
463 dynamic ?
464*/
465
466/*
467 Hostname or A.B.C.D Address to match
468 any Any source host
469 host A single host address
470*/
471
4cf24501
RZ
472struct filter *filter_lookup_cisco(struct access_list *access,
473 struct filter *mnew)
d62a17ae 474{
475 struct filter *mfilter;
476 struct filter_cisco *filter;
477 struct filter_cisco *new;
478
479 new = &mnew->u.cfilter;
480
481 for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
482 filter = &mfilter->u.cfilter;
483
484 if (filter->extended) {
485 if (mfilter->type == mnew->type
486 && filter->addr.s_addr == new->addr.s_addr
487 && filter->addr_mask.s_addr == new->addr_mask.s_addr
488 && filter->mask.s_addr == new->mask.s_addr
489 && filter->mask_mask.s_addr
490 == new->mask_mask.s_addr)
491 return mfilter;
492 } else {
493 if (mfilter->type == mnew->type
494 && filter->addr.s_addr == new->addr.s_addr
495 && filter->addr_mask.s_addr
496 == new->addr_mask.s_addr)
497 return mfilter;
498 }
499 }
500
501 return NULL;
502}
503
4cf24501
RZ
504struct filter *filter_lookup_zebra(struct access_list *access,
505 struct filter *mnew)
718e3744 506{
d62a17ae 507 struct filter *mfilter;
508 struct filter_zebra *filter;
509 struct filter_zebra *new;
718e3744 510
d62a17ae 511 new = &mnew->u.zfilter;
718e3744 512
d62a17ae 513 for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
514 filter = &mfilter->u.zfilter;
718e3744 515
d62a17ae 516 if (filter->exact == new->exact
d37ba549 517 && mfilter->type == mnew->type) {
0f6476cc
DS
518 if (prefix_same(&filter->prefix, &new->prefix))
519 return mfilter;
d37ba549 520 }
718e3744 521 }
d62a17ae 522 return NULL;
523}
524
eb51bb9b
DL
525static void config_write_access_zebra(struct vty *, struct filter *);
526static void config_write_access_cisco(struct vty *, struct filter *);
718e3744 527
528/* show access-list command. */
d62a17ae 529static int filter_show(struct vty *vty, const char *name, afi_t afi)
530{
531 struct access_list *access;
532 struct access_master *master;
533 struct filter *mfilter;
534 struct filter_cisco *filter;
535 int write = 0;
536
537 master = access_master_get(afi);
538 if (master == NULL)
539 return 0;
540
541 /* Print the name of the protocol */
542 vty_out(vty, "%s:\n", frr_protoname);
543
544 for (access = master->num.head; access; access = access->next) {
545 if (name && strcmp(access->name, name) != 0)
546 continue;
547
548 write = 1;
549
550 for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
551 filter = &mfilter->u.cfilter;
552
553 if (write) {
d37ba549 554 vty_out(vty, "%s %s access list %s\n",
d62a17ae 555 mfilter->cisco ? (filter->extended
556 ? "Extended"
557 : "Standard")
558 : "Zebra",
d37ba549 559 (afi == AFI_IP)
3b0f6068
DL
560 ? ("IP")
561 : ((afi == AFI_IP6) ? ("IPv6 ")
562 : ("MAC ")),
d62a17ae 563 access->name);
564 write = 0;
565 }
566
358189ad
DA
567 vty_out(vty, " seq %" PRId64, mfilter->seq);
568 vty_out(vty, " %s%s", filter_type_str(mfilter),
d62a17ae 569 mfilter->type == FILTER_DENY ? " " : "");
570
571 if (!mfilter->cisco)
572 config_write_access_zebra(vty, mfilter);
573 else if (filter->extended)
574 config_write_access_cisco(vty, mfilter);
575 else {
576 if (filter->addr_mask.s_addr == 0xffffffff)
577 vty_out(vty, " any\n");
578 else {
579 vty_out(vty, " %s",
580 inet_ntoa(filter->addr));
975a328e
DA
581 if (filter->addr_mask.s_addr
582 != INADDR_ANY)
d62a17ae 583 vty_out(vty,
584 ", wildcard bits %s",
585 inet_ntoa(
586 filter->addr_mask));
587 vty_out(vty, "\n");
588 }
589 }
718e3744 590 }
718e3744 591 }
d62a17ae 592
593 for (access = master->str.head; access; access = access->next) {
594 if (name && strcmp(access->name, name) != 0)
595 continue;
596
597 write = 1;
598
599 for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
600 filter = &mfilter->u.cfilter;
601
602 if (write) {
d37ba549 603 vty_out(vty, "%s %s access list %s\n",
d62a17ae 604 mfilter->cisco ? (filter->extended
605 ? "Extended"
606 : "Standard")
607 : "Zebra",
d37ba549 608 (afi == AFI_IP)
3b0f6068
DL
609 ? ("IP")
610 : ((afi == AFI_IP6) ? ("IPv6 ")
611 : ("MAC ")),
d62a17ae 612 access->name);
613 write = 0;
614 }
615
358189ad
DA
616 vty_out(vty, " seq %" PRId64, mfilter->seq);
617 vty_out(vty, " %s%s", filter_type_str(mfilter),
d62a17ae 618 mfilter->type == FILTER_DENY ? " " : "");
619
620 if (!mfilter->cisco)
621 config_write_access_zebra(vty, mfilter);
622 else if (filter->extended)
623 config_write_access_cisco(vty, mfilter);
624 else {
625 if (filter->addr_mask.s_addr == 0xffffffff)
626 vty_out(vty, " any\n");
627 else {
628 vty_out(vty, " %s",
629 inet_ntoa(filter->addr));
975a328e
DA
630 if (filter->addr_mask.s_addr
631 != INADDR_ANY)
d62a17ae 632 vty_out(vty,
633 ", wildcard bits %s",
634 inet_ntoa(
635 filter->addr_mask));
636 vty_out(vty, "\n");
637 }
638 }
718e3744 639 }
718e3744 640 }
d62a17ae 641 return CMD_SUCCESS;
718e3744 642}
643
d37ba549
MK
644/* show MAC access list - this only has MAC filters for now*/
645DEFUN (show_mac_access_list,
646 show_mac_access_list_cmd,
647 "show mac access-list",
648 SHOW_STR
649 "mac access lists\n"
650 "List mac access lists\n")
651{
652 return filter_show(vty, NULL, AFI_L2VPN);
653}
654
655DEFUN (show_mac_access_list_name,
656 show_mac_access_list_name_cmd,
657 "show mac access-list WORD",
658 SHOW_STR
1667fc40 659 "mac access lists\n"
d37ba549 660 "List mac access lists\n"
1667fc40 661 "mac address\n")
d37ba549
MK
662{
663 return filter_show(vty, argv[3]->arg, AFI_L2VPN);
664}
665
718e3744 666DEFUN (show_ip_access_list,
667 show_ip_access_list_cmd,
668 "show ip access-list",
669 SHOW_STR
670 IP_STR
671 "List IP access lists\n")
672{
d62a17ae 673 return filter_show(vty, NULL, AFI_IP);
718e3744 674}
675
676DEFUN (show_ip_access_list_name,
677 show_ip_access_list_name_cmd,
6147e2c6 678 "show ip access-list <(1-99)|(100-199)|(1300-1999)|(2000-2699)|WORD>",
718e3744 679 SHOW_STR
680 IP_STR
681 "List IP access lists\n"
682 "IP standard access list\n"
683 "IP extended access list\n"
684 "IP standard access list (expanded range)\n"
685 "IP extended access list (expanded range)\n"
686 "IP zebra access-list\n")
687{
d62a17ae 688 int idx_acl = 3;
689 return filter_show(vty, argv[idx_acl]->arg, AFI_IP);
718e3744 690}
691
718e3744 692DEFUN (show_ipv6_access_list,
693 show_ipv6_access_list_cmd,
694 "show ipv6 access-list",
695 SHOW_STR
696 IPV6_STR
697 "List IPv6 access lists\n")
698{
d62a17ae 699 return filter_show(vty, NULL, AFI_IP6);
718e3744 700}
701
702DEFUN (show_ipv6_access_list_name,
703 show_ipv6_access_list_name_cmd,
704 "show ipv6 access-list WORD",
705 SHOW_STR
706 IPV6_STR
707 "List IPv6 access lists\n"
708 "IPv6 zebra access-list\n")
709{
d62a17ae 710 int idx_word = 3;
711 return filter_show(vty, argv[idx_word]->arg, AFI_IP6);
712}
713
eb51bb9b 714static void config_write_access_cisco(struct vty *vty, struct filter *mfilter)
d62a17ae 715{
716 struct filter_cisco *filter;
717
718 filter = &mfilter->u.cfilter;
719
720 if (filter->extended) {
721 vty_out(vty, " ip");
722 if (filter->addr_mask.s_addr == 0xffffffff)
723 vty_out(vty, " any");
975a328e 724 else if (filter->addr_mask.s_addr == INADDR_ANY)
d62a17ae 725 vty_out(vty, " host %s", inet_ntoa(filter->addr));
726 else {
727 vty_out(vty, " %s", inet_ntoa(filter->addr));
728 vty_out(vty, " %s", inet_ntoa(filter->addr_mask));
729 }
730
731 if (filter->mask_mask.s_addr == 0xffffffff)
732 vty_out(vty, " any");
975a328e 733 else if (filter->mask_mask.s_addr == INADDR_ANY)
d62a17ae 734 vty_out(vty, " host %s", inet_ntoa(filter->mask));
735 else {
736 vty_out(vty, " %s", inet_ntoa(filter->mask));
737 vty_out(vty, " %s", inet_ntoa(filter->mask_mask));
738 }
739 vty_out(vty, "\n");
740 } else {
741 if (filter->addr_mask.s_addr == 0xffffffff)
742 vty_out(vty, " any\n");
743 else {
744 vty_out(vty, " %s", inet_ntoa(filter->addr));
975a328e 745 if (filter->addr_mask.s_addr != INADDR_ANY)
d62a17ae 746 vty_out(vty, " %s",
747 inet_ntoa(filter->addr_mask));
748 vty_out(vty, "\n");
749 }
718e3744 750 }
718e3744 751}
752
eb51bb9b 753static void config_write_access_zebra(struct vty *vty, struct filter *mfilter)
718e3744 754{
d62a17ae 755 struct filter_zebra *filter;
756 struct prefix *p;
757 char buf[BUFSIZ];
718e3744 758
d62a17ae 759 filter = &mfilter->u.zfilter;
760 p = &filter->prefix;
718e3744 761
d62a17ae 762 if (p->prefixlen == 0 && !filter->exact)
763 vty_out(vty, " any");
d37ba549 764 else if (p->family == AF_INET6 || p->family == AF_INET)
d62a17ae 765 vty_out(vty, " %s/%d%s",
766 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
767 p->prefixlen, filter->exact ? " exact-match" : "");
69b61704 768 else if (p->family == AF_ETHERNET) {
3b0f6068 769 if (p->prefixlen == 0)
69b61704
MK
770 vty_out(vty, " any");
771 else
772 vty_out(vty, " %s", prefix_mac2str(&(p->u.prefix_eth),
773 buf, sizeof(buf)));
774 }
718e3744 775
d62a17ae 776 vty_out(vty, "\n");
718e3744 777}
778
d37ba549 779static struct cmd_node access_mac_node = {
f4b8291f 780 .name = "MAC access list",
62b346ee
DL
781 .node = ACCESS_MAC_NODE,
782 .prompt = "",
62b346ee 783};
d37ba549 784
d37ba549
MK
785static void access_list_reset_mac(void)
786{
787 struct access_list *access;
788 struct access_list *next;
789 struct access_master *master;
790
791 master = access_master_get(AFI_L2VPN);
792 if (master == NULL)
793 return;
794
795 for (access = master->num.head; access; access = next) {
796 next = access->next;
797 access_list_delete(access);
798 }
799 for (access = master->str.head; access; access = next) {
800 next = access->next;
801 access_list_delete(access);
802 }
803
804 assert(master->num.head == NULL);
805 assert(master->num.tail == NULL);
806
807 assert(master->str.head == NULL);
808 assert(master->str.tail == NULL);
809}
810
811/* Install vty related command. */
812static void access_list_init_mac(void)
813{
612c2c15 814 install_node(&access_mac_node);
d37ba549
MK
815
816 install_element(ENABLE_NODE, &show_mac_access_list_cmd);
817 install_element(ENABLE_NODE, &show_mac_access_list_name_cmd);
d37ba549
MK
818}
819
718e3744 820/* Access-list node. */
1d3c4b66 821static int config_write_access(struct vty *vty);
62b346ee 822static struct cmd_node access_node = {
f4b8291f 823 .name = "ipv4 access list",
62b346ee
DL
824 .node = ACCESS_NODE,
825 .prompt = "",
1d3c4b66 826 .config_write = config_write_access,
62b346ee 827};
718e3744 828
1d3c4b66 829static int config_write_access(struct vty *vty)
718e3744 830{
1d3c4b66
RZ
831 struct lyd_node *dnode;
832 int written = 0;
833
834 dnode = yang_dnode_get(running_config->dnode, "/frr-filter:lib");
835 if (dnode) {
836 nb_cli_show_dnode_cmds(vty, dnode, false);
837 written = 1;
838 }
839
840 return written;
718e3744 841}
842
d62a17ae 843static void access_list_reset_ipv4(void)
718e3744 844{
d62a17ae 845 struct access_list *access;
846 struct access_list *next;
847 struct access_master *master;
718e3744 848
d62a17ae 849 master = access_master_get(AFI_IP);
850 if (master == NULL)
851 return;
718e3744 852
d62a17ae 853 for (access = master->num.head; access; access = next) {
854 next = access->next;
855 access_list_delete(access);
856 }
857 for (access = master->str.head; access; access = next) {
858 next = access->next;
859 access_list_delete(access);
860 }
718e3744 861
d62a17ae 862 assert(master->num.head == NULL);
863 assert(master->num.tail == NULL);
718e3744 864
d62a17ae 865 assert(master->str.head == NULL);
866 assert(master->str.tail == NULL);
718e3744 867}
868
869/* Install vty related command. */
d62a17ae 870static void access_list_init_ipv4(void)
871{
612c2c15 872 install_node(&access_node);
d62a17ae 873
874 install_element(ENABLE_NODE, &show_ip_access_list_cmd);
875 install_element(ENABLE_NODE, &show_ip_access_list_name_cmd);
d62a17ae 876}
877
62b346ee 878static struct cmd_node access_ipv6_node = {
f4b8291f 879 .name = "ipv6 access list",
62b346ee
DL
880 .node = ACCESS_IPV6_NODE,
881 .prompt = "",
62b346ee 882};
d62a17ae 883
d62a17ae 884static void access_list_reset_ipv6(void)
885{
886 struct access_list *access;
887 struct access_list *next;
888 struct access_master *master;
889
890 master = access_master_get(AFI_IP6);
891 if (master == NULL)
892 return;
893
894 for (access = master->num.head; access; access = next) {
895 next = access->next;
896 access_list_delete(access);
897 }
898 for (access = master->str.head; access; access = next) {
899 next = access->next;
900 access_list_delete(access);
901 }
718e3744 902
d62a17ae 903 assert(master->num.head == NULL);
904 assert(master->num.tail == NULL);
718e3744 905
d62a17ae 906 assert(master->str.head == NULL);
907 assert(master->str.tail == NULL);
718e3744 908}
909
d62a17ae 910static void access_list_init_ipv6(void)
718e3744 911{
612c2c15 912 install_node(&access_ipv6_node);
718e3744 913
d62a17ae 914 install_element(ENABLE_NODE, &show_ipv6_access_list_cmd);
915 install_element(ENABLE_NODE, &show_ipv6_access_list_name_cmd);
718e3744 916}
718e3744 917
4d762f26 918void access_list_init(void)
718e3744 919{
d62a17ae 920 access_list_init_ipv4();
921 access_list_init_ipv6();
d37ba549 922 access_list_init_mac();
b62578bd
RZ
923
924 filter_cli_init();
718e3744 925}
926
4d762f26 927void access_list_reset(void)
718e3744 928{
d62a17ae 929 access_list_reset_ipv4();
930 access_list_reset_ipv6();
d37ba549 931 access_list_reset_mac();
718e3744 932}