back to topotato report
topotato coverage report
Current view: top level - lib - filter.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 169 403 41.9 %
Date: 2023-02-24 19:38:44 Functions: 24 42 57.1 %

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

Generated by: LCOV version v1.16-topotato