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},
return &access_master_ipv4;
else if (afi == AFI_IP6)
return &access_master_ipv6;
+ else if (afi == AFI_L2VPN)
+ return &access_master_mac;
return NULL;
}
}
/* 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;
}
/* 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;
}
/* 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;
{
access_master_ipv4.add_hook = func;
access_master_ipv6.add_hook = func;
+ access_master_mac.add_hook = func;
}
/* Delete hook function. */
{
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. */
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;
}
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;
"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;
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);
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]",
"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;
"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;
"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;
"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;
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;
}
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;
}
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",
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");
}
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);
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);
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. */
{
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();
}