]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/filter.c
zebra, lib: fix the ZEBRA_INTERFACE_VRF_UPDATE zapi message
[mirror_frr.git] / lib / filter.c
index 0262234c782596d6ab513ae9f3f3da6cbcc9a4e2..1aae58b61ca59c1b53ab7cf3c2f83548cba0fe1e 100644 (file)
@@ -90,6 +90,14 @@ struct access_master {
        void (*delete_hook)(struct access_list *);
 };
 
+/* Static structure for mac access_list's master. */
+static struct access_master access_master_mac = {
+       {NULL, NULL},
+       {NULL, NULL},
+       NULL,
+       NULL,
+};
+
 /* Static structure for IPv4 access_list's master. */
 static struct access_master access_master_ipv4 = {
        {NULL, NULL},
@@ -112,6 +120,8 @@ static struct access_master *access_master_get(afi_t afi)
                return &access_master_ipv4;
        else if (afi == AFI_IP6)
                return &access_master_ipv6;
+       else if (afi == AFI_L2VPN)
+               return &access_master_mac;
        return NULL;
 }
 
@@ -147,12 +157,12 @@ static const char *filter_type_str(struct filter *filter)
 }
 
 /* If filter match to the prefix then return 1. */
-static int filter_match_cisco(struct filter *mfilter, struct prefix *p)
+static int filter_match_cisco(struct filter *mfilter, const struct prefix *p)
 {
        struct filter_cisco *filter;
        struct in_addr mask;
-       u_int32_t check_addr;
-       u_int32_t check_mask;
+       uint32_t check_addr;
+       uint32_t check_mask;
 
        filter = &mfilter->u.cfilter;
        check_addr = p->u.prefix4.s_addr & ~filter->addr_mask.s_addr;
@@ -171,9 +181,9 @@ static int filter_match_cisco(struct filter *mfilter, struct prefix *p)
 }
 
 /* If filter match to the prefix then return 1. */
-static int filter_match_zebra(struct filter *mfilter, struct prefix *p)
+static int filter_match_zebra(struct filter *mfilter, const struct prefix *p)
 {
-       struct filter_zebra *filter;
+       struct filter_zebra *filter = NULL;
 
        filter = &mfilter->u.zfilter;
 
@@ -362,12 +372,11 @@ static struct access_list *access_list_get(afi_t afi, const char *name)
 }
 
 /* Apply access list to object (which should be struct prefix *). */
-enum filter_type access_list_apply(struct access_list *access, void *object)
+enum filter_type access_list_apply(struct access_list *access,
+                                  const void *object)
 {
        struct filter *filter;
-       struct prefix *p;
-
-       p = (struct prefix *)object;
+       const struct prefix *p = (const struct prefix *)object;
 
        if (access == NULL)
                return FILTER_DENY;
@@ -390,6 +399,7 @@ void access_list_add_hook(void (*func)(struct access_list *access))
 {
        access_master_ipv4.add_hook = func;
        access_master_ipv6.add_hook = func;
+       access_master_mac.add_hook = func;
 }
 
 /* Delete hook function. */
@@ -397,6 +407,7 @@ void access_list_delete_hook(void (*func)(struct access_list *access))
 {
        access_master_ipv4.delete_hook = func;
        access_master_ipv6.delete_hook = func;
+       access_master_mac.delete_hook = func;
 }
 
 /* Add new filter to the end of specified access_list. */
@@ -515,10 +526,10 @@ static struct filter *filter_lookup_zebra(struct access_list *access,
                filter = &mfilter->u.zfilter;
 
                if (filter->exact == new->exact
-                   && mfilter->type
-                              == mnew->type &&prefix_same(&filter->prefix,
-                                                          &new->prefix))
-                       return mfilter;
+                   && mfilter->type == mnew->type) {
+                       if (prefix_same(&filter->prefix, &new->prefix))
+                               return mfilter;
+               }
        }
        return NULL;
 }
@@ -539,8 +550,7 @@ static int vty_access_list_remark_unset(struct vty *vty, afi_t afi,
                access->remark = NULL;
        }
 
-       if (access->head == NULL && access->tail == NULL
-           && access->remark == NULL)
+       if (access->head == NULL && access->tail == NULL)
                access_list_delete(access);
 
        return CMD_SUCCESS;
@@ -1252,6 +1262,12 @@ static int filter_set_zebra(struct vty *vty, const char *name_str,
                                "IPv6 address prefix/prefixlen is malformed\n");
                        return CMD_WARNING_CONFIG_FAILED;
                }
+       } else if (afi == AFI_L2VPN) {
+               ret = str2prefix_eth(prefix_str, (struct prefix_eth *)&p);
+               if (ret <= 0) {
+                       vty_out(vty, "MAC address is malformed\n");
+                       return CMD_WARNING;
+               }
        } else
                return CMD_WARNING_CONFIG_FAILED;
 
@@ -1274,7 +1290,6 @@ static int filter_set_zebra(struct vty *vty, const char *name_str,
                        access_list_filter_add(access, mfilter);
        } else {
                struct filter *delete_filter;
-
                delete_filter = filter_lookup_zebra(access, mfilter);
                if (delete_filter)
                        access_list_filter_delete(access, delete_filter);
@@ -1285,6 +1300,64 @@ static int filter_set_zebra(struct vty *vty, const char *name_str,
        return CMD_SUCCESS;
 }
 
+DEFUN (mac_access_list,
+       mac_access_list_cmd,
+       "mac access-list WORD <deny|permit> X:X:X:X:X:X",
+       "Add a mac access-list\n"
+       "Add an access list entry\n"
+       "MAC zebra access-list name\n"
+       "Specify packets to reject\n"
+       "Specify packets to forward\n"
+       "MAC address to match. e.g. 00:01:00:01:00:01\n")
+{
+       return filter_set_zebra(vty, argv[2]->arg, argv[3]->arg, AFI_L2VPN,
+                               argv[4]->arg, 0, 1);
+}
+
+DEFUN (no_mac_access_list,
+       no_mac_access_list_cmd,
+       "no mac access-list WORD <deny|permit> X:X:X:X:X:X",
+       NO_STR
+       "Remove a mac access-list\n"
+       "Remove an access list entry\n"
+       "MAC zebra access-list name\n"
+       "Specify packets to reject\n"
+       "Specify packets to forward\n"
+       "MAC address to match. e.g. 00:01:00:01:00:01\n")
+{
+       return filter_set_zebra(vty, argv[3]->arg, argv[4]->arg, AFI_L2VPN,
+                               argv[5]->arg, 0, 0);
+}
+
+DEFUN (mac_access_list_any,
+       mac_access_list_any_cmd,
+       "mac access-list WORD <deny|permit> any",
+       "Add a mac access-list\n"
+       "Add an access list entry\n"
+       "MAC zebra access-list name\n"
+       "Specify packets to reject\n"
+       "Specify packets to forward\n"
+       "MAC address to match. e.g. 00:01:00:01:00:01\n")
+{
+       return filter_set_zebra(vty, argv[2]->arg, argv[3]->arg, AFI_L2VPN,
+                               "00:00:00:00:00:00", 0, 1);
+}
+
+DEFUN (no_mac_access_list_any,
+       no_mac_access_list_any_cmd,
+       "no mac access-list WORD <deny|permit> any",
+       NO_STR
+       "Remove a mac access-list\n"
+       "Remove an access list entry\n"
+       "MAC zebra access-list name\n"
+       "Specify packets to reject\n"
+       "Specify packets to forward\n"
+       "MAC address to match. e.g. 00:01:00:01:00:01\n")
+{
+       return filter_set_zebra(vty, argv[3]->arg, argv[4]->arg, AFI_L2VPN,
+                               "00:00:00:00:00:00", 0, 0);
+}
+
 DEFUN (access_list_exact,
        access_list_exact_cmd,
        "access-list WORD <deny|permit> A.B.C.D/M [exact-match]",
@@ -1295,7 +1368,7 @@ DEFUN (access_list_exact,
        "Prefix to match. e.g. 10.0.0.0/8\n"
        "Exact match of the prefixes\n")
 {
-       int idx;
+       int idx = 0;
        int exact = 0;
        int idx_word = 1;
        int idx_permit_deny = 2;
@@ -1337,7 +1410,7 @@ DEFUN (no_access_list_exact,
        "Prefix to match. e.g. 10.0.0.0/8\n"
        "Exact match of the prefixes\n")
 {
-       int idx;
+       int idx = 0;
        int exact = 0;
        int idx_word = 2;
        int idx_permit_deny = 3;
@@ -1476,7 +1549,7 @@ DEFUN (ipv6_access_list_exact,
        "IPv6 prefix\n"
        "Exact match of the prefixes\n")
 {
-       int idx;
+       int idx = 0;
        int exact = 0;
        int idx_word = 2;
        int idx_allow = 3;
@@ -1519,7 +1592,7 @@ DEFUN (no_ipv6_access_list_exact,
        "Prefix to match. e.g. 3ffe:506::/32\n"
        "Exact match of the prefixes\n")
 {
-       int idx;
+       int idx = 0;
        int exact = 0;
        int idx_word = 3;
        int idx_permit_deny = 4;
@@ -1666,12 +1739,15 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi)
                        filter = &mfilter->u.cfilter;
 
                        if (write) {
-                               vty_out(vty, "%s IP%s access list %s\n",
+                               vty_out(vty, "%s %s access list %s\n",
                                        mfilter->cisco ? (filter->extended
                                                                  ? "Extended"
                                                                  : "Standard")
                                                       : "Zebra",
-                                       afi == AFI_IP6 ? "v6" : "",
+                                       (afi == AFI_IP)
+                                               ? ("IP")
+                                               : ((afi == AFI_IP6) ? ("IPv6 ")
+                                                                   : ("MAC ")),
                                        access->name);
                                write = 0;
                        }
@@ -1710,12 +1786,15 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi)
                        filter = &mfilter->u.cfilter;
 
                        if (write) {
-                               vty_out(vty, "%s IP%s access list %s\n",
+                               vty_out(vty, "%s %s access list %s\n",
                                        mfilter->cisco ? (filter->extended
                                                                  ? "Extended"
                                                                  : "Standard")
                                                       : "Zebra",
-                                       afi == AFI_IP6 ? "v6" : "",
+                                       (afi == AFI_IP)
+                                               ? ("IP")
+                                               : ((afi == AFI_IP6) ? ("IPv6 ")
+                                                                   : ("MAC ")),
                                        access->name);
                                write = 0;
                        }
@@ -1746,6 +1825,28 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi)
        return CMD_SUCCESS;
 }
 
+/* show MAC access list - this only has MAC filters for now*/
+DEFUN (show_mac_access_list,
+       show_mac_access_list_cmd,
+       "show mac access-list",
+       SHOW_STR
+       "mac access lists\n"
+       "List mac access lists\n")
+{
+       return filter_show(vty, NULL, AFI_L2VPN);
+}
+
+DEFUN (show_mac_access_list_name,
+       show_mac_access_list_name_cmd,
+       "show mac access-list WORD",
+       SHOW_STR
+       "mac access lists\n"
+       "List mac access lists\n"
+       "mac address\n")
+{
+       return filter_show(vty, argv[3]->arg, AFI_L2VPN);
+}
+
 DEFUN (show_ip_access_list,
        show_ip_access_list_cmd,
        "show ip access-list",
@@ -1844,10 +1945,17 @@ void config_write_access_zebra(struct vty *vty, struct filter *mfilter)
 
        if (p->prefixlen == 0 && !filter->exact)
                vty_out(vty, " any");
-       else
+       else if (p->family == AF_INET6 || p->family == AF_INET)
                vty_out(vty, " %s/%d%s",
                        inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
                        p->prefixlen, filter->exact ? " exact-match" : "");
+       else if (p->family == AF_ETHERNET) {
+               if (p->prefixlen == 0)
+                       vty_out(vty, " any");
+               else
+                       vty_out(vty, " %s", prefix_mac2str(&(p->u.prefix_eth),
+                                                          buf, sizeof(buf)));
+       }
 
        vty_out(vty, "\n");
 }
@@ -1866,15 +1974,19 @@ static int config_write_access(struct vty *vty, afi_t afi)
        for (access = master->num.head; access; access = access->next) {
                if (access->remark) {
                        vty_out(vty, "%saccess-list %s remark %s\n",
-                               afi == AFI_IP ? "" : "ipv6 ", access->name,
-                               access->remark);
+                               (afi == AFI_IP) ? ("")
+                                               : ((afi == AFI_IP6) ? ("ipv6 ")
+                                                                   : ("mac ")),
+                               access->name, access->remark);
                        write++;
                }
 
                for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
                        vty_out(vty, "%saccess-list %s %s",
-                               afi == AFI_IP ? "" : "ipv6 ", access->name,
-                               filter_type_str(mfilter));
+                               (afi == AFI_IP) ? ("")
+                                               : ((afi == AFI_IP6) ? ("ipv6 ")
+                                                                   : ("mac ")),
+                               access->name, filter_type_str(mfilter));
 
                        if (mfilter->cisco)
                                config_write_access_cisco(vty, mfilter);
@@ -1888,15 +2000,19 @@ static int config_write_access(struct vty *vty, afi_t afi)
        for (access = master->str.head; access; access = access->next) {
                if (access->remark) {
                        vty_out(vty, "%saccess-list %s remark %s\n",
-                               afi == AFI_IP ? "" : "ipv6 ", access->name,
-                               access->remark);
+                               (afi == AFI_IP) ? ("")
+                                               : ((afi == AFI_IP6) ? ("ipv6 ")
+                                                                   : ("mac ")),
+                               access->name, access->remark);
                        write++;
                }
 
                for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
                        vty_out(vty, "%saccess-list %s %s",
-                               afi == AFI_IP ? "" : "ipv6 ", access->name,
-                               filter_type_str(mfilter));
+                               (afi == AFI_IP) ? ("")
+                                               : ((afi == AFI_IP6) ? ("ipv6 ")
+                                                                   : ("mac ")),
+                               access->name, filter_type_str(mfilter));
 
                        if (mfilter->cisco)
                                config_write_access_cisco(vty, mfilter);
@@ -1909,6 +2025,56 @@ static int config_write_access(struct vty *vty, afi_t afi)
        return write;
 }
 
+static struct cmd_node access_mac_node = {
+       ACCESS_MAC_NODE, "", /* Access list has no interface. */
+       1};
+
+static int config_write_access_mac(struct vty *vty)
+{
+       return config_write_access(vty, AFI_L2VPN);
+}
+
+static void access_list_reset_mac(void)
+{
+       struct access_list *access;
+       struct access_list *next;
+       struct access_master *master;
+
+       master = access_master_get(AFI_L2VPN);
+       if (master == NULL)
+               return;
+
+       for (access = master->num.head; access; access = next) {
+               next = access->next;
+               access_list_delete(access);
+       }
+       for (access = master->str.head; access; access = next) {
+               next = access->next;
+               access_list_delete(access);
+       }
+
+       assert(master->num.head == NULL);
+       assert(master->num.tail == NULL);
+
+       assert(master->str.head == NULL);
+       assert(master->str.tail == NULL);
+}
+
+/* Install vty related command. */
+static void access_list_init_mac(void)
+{
+       install_node(&access_mac_node, config_write_access_mac);
+
+       install_element(ENABLE_NODE, &show_mac_access_list_cmd);
+       install_element(ENABLE_NODE, &show_mac_access_list_name_cmd);
+
+       /* Zebra access-list */
+       install_element(CONFIG_NODE, &mac_access_list_cmd);
+       install_element(CONFIG_NODE, &no_mac_access_list_cmd);
+       install_element(CONFIG_NODE, &mac_access_list_any_cmd);
+       install_element(CONFIG_NODE, &no_mac_access_list_any_cmd);
+}
+
 /* Access-list node. */
 static struct cmd_node access_node = {ACCESS_NODE,
                                      "", /* Access list has no interface. */
@@ -2050,10 +2216,12 @@ void access_list_init()
 {
        access_list_init_ipv4();
        access_list_init_ipv6();
+       access_list_init_mac();
 }
 
 void access_list_reset()
 {
        access_list_reset_ipv4();
        access_list_reset_ipv6();
+       access_list_reset_mac();
 }