diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/atomlist.h | 10 | ||||
| -rw-r--r-- | lib/compiler.h | 7 | ||||
| -rw-r--r-- | lib/ferr.c | 12 | ||||
| -rw-r--r-- | lib/ferr.h | 1 | ||||
| -rw-r--r-- | lib/filter.c | 1373 | ||||
| -rw-r--r-- | lib/libfrr.c | 1 | ||||
| -rw-r--r-- | lib/prefix.c | 50 | ||||
| -rw-r--r-- | lib/prefix.h | 14 | ||||
| -rw-r--r-- | lib/routemap.c | 203 | ||||
| -rw-r--r-- | lib/routemap.h | 38 | ||||
| -rw-r--r-- | lib/typerb.c | 5 | ||||
| -rw-r--r-- | lib/typerb.h | 23 | ||||
| -rw-r--r-- | lib/typesafe.c | 13 | ||||
| -rw-r--r-- | lib/typesafe.h | 51 |
14 files changed, 1379 insertions, 422 deletions
diff --git a/lib/atomlist.h b/lib/atomlist.h index e4098ccb54..621db6824f 100644 --- a/lib/atomlist.h +++ b/lib/atomlist.h @@ -135,8 +135,10 @@ macro_inline void prefix ## _add_tail(struct prefix##_head *h, type *item) \ macro_inline void prefix ## _del_hint(struct prefix##_head *h, type *item, \ _Atomic atomptr_t *hint) \ { atomlist_del_hint(&h->ah, &item->field.ai, hint); } \ -macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ -{ atomlist_del_hint(&h->ah, &item->field.ai, NULL); } \ +macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ +{ atomlist_del_hint(&h->ah, &item->field.ai, NULL); \ + /* TODO: Return NULL if not found */ \ + return item; } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ { char *p = (char *)atomlist_pop(&h->ah); \ return p ? (type *)(p - offsetof(type, field)) : NULL; } \ @@ -273,9 +275,11 @@ macro_inline void prefix ## _del_hint(struct prefix##_head *h, type *item, \ { \ atomsort_del_hint(&h->ah, &item->field.ai, hint); \ } \ -macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ +macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ { \ atomsort_del_hint(&h->ah, &item->field.ai, NULL); \ + /* TODO: Return NULL if not found */ \ + return item; \ } \ macro_inline size_t prefix ## _count(struct prefix##_head *h) \ { \ diff --git a/lib/compiler.h b/lib/compiler.h index 7c7f4ce294..6700ca9e8b 100644 --- a/lib/compiler.h +++ b/lib/compiler.h @@ -165,6 +165,13 @@ extern "C" { _min_a < _min_b ? _min_a : _min_b; \ }) +#define numcmp(a, b) \ + ({ \ + typeof(a) _cmp_a = (a); \ + typeof(b) _cmp_b = (b); \ + (_cmp_a < _cmp_b) ? -1 : ((_cmp_a > _cmp_b) ? 1 : 0); \ + }) + #ifndef offsetof #ifdef __compiler_offsetof #define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE,MEMBER) diff --git a/lib/ferr.c b/lib/ferr.c index 65c0cf886d..8afc926c41 100644 --- a/lib/ferr.c +++ b/lib/ferr.c @@ -126,10 +126,8 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json) if (code) { ref = log_ref_get(code); - if (!ref) { - vty_out(vty, "Code %"PRIu32" - Unknown\n", code); + if (!ref) return; - } listnode_add(errlist, ref); } @@ -197,8 +195,6 @@ void log_ref_init(void) "Error Reference Texts"); } pthread_mutex_unlock(&refs_mtx); - - install_element(VIEW_NODE, &show_error_code_cmd); } void log_ref_fini(void) @@ -212,6 +208,12 @@ void log_ref_fini(void) pthread_mutex_unlock(&refs_mtx); } +void log_ref_vty_init(void) +{ + install_element(VIEW_NODE, &show_error_code_cmd); +} + + const struct ferr *ferr_get_last(ferr_r errval) { struct ferr *last_error = pthread_getspecific(errkey); diff --git a/lib/ferr.h b/lib/ferr.h index 93d0ced538..a89b595e87 100644 --- a/lib/ferr.h +++ b/lib/ferr.h @@ -158,6 +158,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json); */ void log_ref_init(void); void log_ref_fini(void); +void log_ref_vty_init(void); /* get error details. * diff --git a/lib/filter.c b/lib/filter.c index 276df4b4d7..14b89217b8 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -60,6 +60,9 @@ struct filter { /* Filter type information. */ enum filter_type type; + /* Sequence number */ + int64_t seq; + /* Cisco access-list */ int cisco; @@ -406,23 +409,35 @@ void access_list_delete_hook(void (*func)(struct access_list *access)) access_master_mac.delete_hook = func; } -/* Add new filter to the end of specified access_list. */ -static void access_list_filter_add(struct access_list *access, - struct filter *filter) +/* Calculate new sequential number. */ +static int64_t filter_new_seq_get(struct access_list *access) { - filter->next = NULL; - filter->prev = access->tail; + int64_t maxseq; + int64_t newseq; + struct filter *filter; - if (access->tail) - access->tail->next = filter; - else - access->head = filter; - access->tail = filter; + maxseq = newseq = 0; - /* Run hook function. */ - if (access->master->add_hook) - (*access->master->add_hook)(access); - route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_ADDED); + for (filter = access->head; filter; filter = filter->next) { + if (maxseq < filter->seq) + maxseq = filter->seq; + } + + newseq = ((maxseq / 5) * 5) + 5; + + return (newseq > UINT_MAX) ? UINT_MAX : newseq; +} + +/* Return access list entry which has same seq number. */ +static struct filter *filter_seq_check(struct access_list *access, + int64_t seq) +{ + struct filter *filter; + + for (filter = access->head; filter; filter = filter->next) + if (filter->seq == seq) + return filter; + return NULL; } /* If access_list has no filter then return 1. */ @@ -465,6 +480,58 @@ static void access_list_filter_delete(struct access_list *access, access_list_delete(access); } +/* Add new filter to the end of specified access_list. */ +static void access_list_filter_add(struct access_list *access, + struct filter *filter) +{ + struct filter *replace; + struct filter *point; + + /* Automatic asignment of seq no. */ + if (filter->seq == -1) + filter->seq = filter_new_seq_get(access); + + if (access->tail && filter->seq > access->tail->seq) + point = NULL; + else { + /* Is there any same seq access list filter? */ + replace = filter_seq_check(access, filter->seq); + if (replace) + access_list_filter_delete(access, replace); + + /* Check insert point. */ + for (point = access->head; point; point = point->next) + if (point->seq >= filter->seq) + break; + } + + /* In case of this is the first element of the list. */ + filter->next = point; + + if (point) { + if (point->prev) + point->prev->next = filter; + else + access->head = filter; + + filter->prev = point->prev; + point->prev = filter; + } else { + if (access->tail) + access->tail->next = filter; + else + access->head = filter; + + filter->prev = access->tail; + access->tail = filter; + } + + /* Run hook function. */ + if (access->master->add_hook) + (*access->master->add_hook)(access); + route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_ADDED); +} + /* deny Specify packets to reject permit Specify packets to forward @@ -553,12 +620,13 @@ static int vty_access_list_remark_unset(struct vty *vty, afi_t afi, } static int filter_set_cisco(struct vty *vty, const char *name_str, - const char *type_str, const char *addr_str, - const char *addr_mask_str, const char *mask_str, - const char *mask_mask_str, int extended, int set) + const char *seq, const char *type_str, + const char *addr_str, const char *addr_mask_str, + const char *mask_str, const char *mask_mask_str, + int extended, int set) { int ret; - enum filter_type type; + enum filter_type type = FILTER_DENY; struct filter *mfilter; struct filter_cisco *filter; struct access_list *access; @@ -566,15 +634,21 @@ static int filter_set_cisco(struct vty *vty, const char *name_str, struct in_addr addr_mask; struct in_addr mask; struct in_addr mask_mask; + int64_t seqnum = -1; + + if (seq) + seqnum = (int64_t)atol(seq); /* Check of filter type. */ - if (strncmp(type_str, "p", 1) == 0) - type = FILTER_PERMIT; - else if (strncmp(type_str, "d", 1) == 0) - type = FILTER_DENY; - else { - vty_out(vty, "%% filter type must be permit or deny\n"); - return CMD_WARNING_CONFIG_FAILED; + if (type_str) { + if (strncmp(type_str, "p", 1) == 0) + type = FILTER_PERMIT; + else if (strncmp(type_str, "d", 1) == 0) + type = FILTER_DENY; + else { + vty_out(vty, "%% filter type must be permit or deny\n"); + return CMD_WARNING_CONFIG_FAILED; + } } ret = inet_aton(addr_str, &addr); @@ -606,6 +680,7 @@ static int filter_set_cisco(struct vty *vty, const char *name_str, mfilter = filter_new(); mfilter->type = type; mfilter->cisco = 1; + mfilter->seq = seqnum; filter = &mfilter->u.cfilter; filter->extended = extended; filter->addr.s_addr = addr.s_addr & ~addr_mask.s_addr; @@ -640,163 +715,311 @@ static int filter_set_cisco(struct vty *vty, const char *name_str, /* Standard access-list */ DEFUN (access_list_standard, access_list_standard_cmd, - "access-list <(1-99)|(1300-1999)> <deny|permit> A.B.C.D A.B.C.D", + "access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> A.B.C.D A.B.C.D", "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Address to match\n" "Wildcard bits\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 3; - int idx_ipv4_2 = 4; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, NULL, NULL, 0, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *address = NULL; + char *wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + address = argv[idx]->arg; + wildcard = argv[idx + 1]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + address, wildcard, NULL, NULL, 0, 1); } DEFUN (access_list_standard_nomask, access_list_standard_nomask_cmd, - "access-list <(1-99)|(1300-1999)> <deny|permit> A.B.C.D", + "access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> A.B.C.D", "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Address to match\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 3; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", NULL, NULL, 0, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *address = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + address = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + address, "0.0.0.0", NULL, NULL, 0, 1); } DEFUN (access_list_standard_host, access_list_standard_host_cmd, - "access-list <(1-99)|(1300-1999)> <deny|permit> host A.B.C.D", + "access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> host A.B.C.D", "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "A single host address\n" "Address to match\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 4; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", NULL, NULL, 0, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *address = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + address = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + address, "0.0.0.0", NULL, NULL, 0, 1); } DEFUN (access_list_standard_any, access_list_standard_any_cmd, - "access-list <(1-99)|(1300-1999)> <deny|permit> any", + "access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> any", "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any source host\n") { int idx_acl = 1; - int idx_permit_deny = 2; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", NULL, NULL, 0, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", NULL, NULL, 0, 1); } DEFUN (no_access_list_standard, no_access_list_standard_cmd, - "no access-list <(1-99)|(1300-1999)> <deny|permit> A.B.C.D A.B.C.D", + "no access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> A.B.C.D A.B.C.D", NO_STR "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Address to match\n" "Wildcard bits\n") { - int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, NULL, NULL, 0, 0); + int idx_acl = 1; + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *address = NULL; + char *wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + address = argv[idx]->arg; + wildcard = argv[idx + 1]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + address, wildcard, NULL, NULL, 0, 0); } DEFUN (no_access_list_standard_nomask, no_access_list_standard_nomask_cmd, - "no access-list <(1-99)|(1300-1999)> <deny|permit> A.B.C.D", + "no access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> A.B.C.D", NO_STR "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Address to match\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 4; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", NULL, NULL, 0, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *address = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + address = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + address, "0.0.0.0", NULL, NULL, 0, 0); } DEFUN (no_access_list_standard_host, no_access_list_standard_host_cmd, - "no access-list <(1-99)|(1300-1999)> <deny|permit> host A.B.C.D", + "no access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> host A.B.C.D", NO_STR "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "A single host address\n" "Address to match\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 5; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", NULL, NULL, 0, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *address = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + address = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + address, "0.0.0.0", NULL, NULL, 0, 0); } DEFUN (no_access_list_standard_any, no_access_list_standard_any_cmd, - "no access-list <(1-99)|(1300-1999)> <deny|permit> any", + "no access-list <(1-99)|(1300-1999)> [seq (1-4294967295)] <deny|permit> any", NO_STR "Add an access list entry\n" "IP standard access list\n" "IP standard access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any source host\n") { int idx_acl = 2; - int idx_permit_deny = 3; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", NULL, NULL, 0, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", NULL, NULL, 0, 0); } /* Extended access-list */ DEFUN (access_list_extended, access_list_extended_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip A.B.C.D A.B.C.D A.B.C.D A.B.C.D", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip A.B.C.D A.B.C.D A.B.C.D A.B.C.D", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -806,23 +1029,45 @@ DEFUN (access_list_extended, "Destination Wildcard bits\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - int idx_ipv4_3 = 6; - int idx_ipv4_4 = 7; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, - argv[idx_ipv4_4]->arg, 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + char *src_wildcard = NULL; + char *dst_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + src_wildcard = argv[idx + 1]->arg; + dst = argv[idx + 2]->arg; + dst_wildcard = argv[idx + 3]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + src_wildcard, dst, dst_wildcard, 1, 1); } DEFUN (access_list_extended_mask_any, access_list_extended_mask_any_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip A.B.C.D A.B.C.D any", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip A.B.C.D A.B.C.D any", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -831,21 +1076,42 @@ DEFUN (access_list_extended_mask_any, "Any destination host\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, "0.0.0.0", - "255.255.255.255", 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *src_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + src_wildcard = argv[idx + 1]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + src_wildcard, "0.0.0.0", "255.255.255.255", 1, + 1); } DEFUN (access_list_extended_any_mask, access_list_extended_any_mask_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip any A.B.C.D A.B.C.D", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip any A.B.C.D A.B.C.D", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -854,21 +1120,42 @@ DEFUN (access_list_extended_any_mask, "Destination Wildcard bits\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *dst = NULL; + char *dst_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + dst = argv[idx]->arg; + dst_wildcard = argv[idx + 1]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", dst, dst_wildcard, + 1, 1); } DEFUN (access_list_extended_any_any, access_list_extended_any_any_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip any any", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip any any", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -876,18 +1163,33 @@ DEFUN (access_list_extended_any_any, "Any destination host\n") { int idx_acl = 1; - int idx_permit_deny = 2; - return filter_set_cisco( - vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", "0.0.0.0", "255.255.255.255", 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", "0.0.0.0", + "255.255.255.255", 1, 1); } DEFUN (access_list_extended_mask_host, access_list_extended_mask_host_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip A.B.C.D A.B.C.D host A.B.C.D", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip A.B.C.D A.B.C.D host A.B.C.D", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -897,22 +1199,43 @@ DEFUN (access_list_extended_mask_host, "Destination address\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 4; - int idx_ipv4_2 = 5; - int idx_ipv4_3 = 7; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, - "0.0.0.0", 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + char *src_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + src_wildcard = argv[idx + 1]->arg; + dst = argv[idx + 3]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + src_wildcard, dst, "0.0.0.0", 1, 1); } DEFUN (access_list_extended_host_mask, access_list_extended_host_mask_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip host A.B.C.D A.B.C.D A.B.C.D", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip host A.B.C.D A.B.C.D A.B.C.D", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -922,22 +1245,43 @@ DEFUN (access_list_extended_host_mask, "Destination Wildcard bits\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - int idx_ipv4_3 = 7; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", argv[idx_ipv4_2]->arg, - argv[idx_ipv4_3]->arg, 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + char *dst_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + dst = argv[idx + 1]->arg; + dst_wildcard = argv[idx + 2]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + "0.0.0.0", dst, dst_wildcard, 1, 1); } DEFUN (access_list_extended_host_host, access_list_extended_host_host_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip host A.B.C.D host A.B.C.D", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip host A.B.C.D host A.B.C.D", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -947,21 +1291,41 @@ DEFUN (access_list_extended_host_host, "Destination address\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 5; - int idx_ipv4_2 = 7; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", argv[idx_ipv4_2]->arg, "0.0.0.0", 1, - 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + dst = argv[idx + 2]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + "0.0.0.0", dst, "0.0.0.0", 1, 1); } DEFUN (access_list_extended_any_host, access_list_extended_any_host_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip any host A.B.C.D", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip any host A.B.C.D", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -970,19 +1334,39 @@ DEFUN (access_list_extended_any_host, "Destination address\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 6; - return filter_set_cisco( - vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", argv[idx_ipv4]->arg, "0.0.0.0", 1, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *dst = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + dst = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", dst, "0.0.0.0", 1, + 1); } DEFUN (access_list_extended_host_any, access_list_extended_host_any_cmd, - "access-list <(100-199)|(2000-2699)> <deny|permit> ip host A.B.C.D any", + "access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip host A.B.C.D any", "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -991,20 +1375,39 @@ DEFUN (access_list_extended_host_any, "Any destination host\n") { int idx_acl = 1; - int idx_permit_deny = 2; - int idx_ipv4 = 5; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + src = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, "0.0.0.0", "0.0.0.0", "255.255.255.255", 1, 1); } DEFUN (no_access_list_extended, no_access_list_extended_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip A.B.C.D A.B.C.D A.B.C.D A.B.C.D", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip A.B.C.D A.B.C.D A.B.C.D A.B.C.D", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1014,24 +1417,46 @@ DEFUN (no_access_list_extended, "Destination Wildcard bits\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - int idx_ipv4_3 = 7; - int idx_ipv4_4 = 8; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, - argv[idx_ipv4_4]->arg, 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + char *src_wildcard = NULL; + char *dst_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + src_wildcard = argv[idx + 1]->arg; + dst = argv[idx + 2]->arg; + dst_wildcard = argv[idx + 3]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + src_wildcard, dst, dst_wildcard, 1, 0); } DEFUN (no_access_list_extended_mask_any, no_access_list_extended_mask_any_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip A.B.C.D A.B.C.D any", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip A.B.C.D A.B.C.D any", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1040,22 +1465,43 @@ DEFUN (no_access_list_extended_mask_any, "Any destination host\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, "0.0.0.0", - "255.255.255.255", 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *src_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + src_wildcard = argv[idx + 1]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + src_wildcard, "0.0.0.0", "255.255.255.255", 1, + 0); } DEFUN (no_access_list_extended_any_mask, no_access_list_extended_any_mask_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip any A.B.C.D A.B.C.D", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip any A.B.C.D A.B.C.D", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1064,22 +1510,43 @@ DEFUN (no_access_list_extended_any_mask, "Destination Wildcard bits\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 6; - int idx_ipv4_2 = 7; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *dst = NULL; + char *dst_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + dst = argv[idx]->arg; + dst_wildcard = argv[idx + 1]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", dst, dst_wildcard, + 1, 0); } DEFUN (no_access_list_extended_any_any, no_access_list_extended_any_any_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip any any", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip any any", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1087,19 +1554,34 @@ DEFUN (no_access_list_extended_any_any, "Any destination host\n") { int idx_acl = 2; - int idx_permit_deny = 3; - return filter_set_cisco( - vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", "0.0.0.0", "255.255.255.255", 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", "0.0.0.0", + "255.255.255.255", 1, 0); } DEFUN (no_access_list_extended_mask_host, no_access_list_extended_mask_host_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip A.B.C.D A.B.C.D host A.B.C.D", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip A.B.C.D A.B.C.D host A.B.C.D", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1109,23 +1591,44 @@ DEFUN (no_access_list_extended_mask_host, "Destination address\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 5; - int idx_ipv4_2 = 6; - int idx_ipv4_3 = 8; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - argv[idx_ipv4_2]->arg, argv[idx_ipv4_3]->arg, - "0.0.0.0", 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + char *src_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + src_wildcard = argv[idx + 1]->arg; + dst = argv[idx + 3]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + src_wildcard, dst, "0.0.0.0", 1, 0); } DEFUN (no_access_list_extended_host_mask, no_access_list_extended_host_mask_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip host A.B.C.D A.B.C.D A.B.C.D", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip host A.B.C.D A.B.C.D A.B.C.D", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1135,23 +1638,44 @@ DEFUN (no_access_list_extended_host_mask, "Destination Wildcard bits\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 6; - int idx_ipv4_2 = 7; - int idx_ipv4_3 = 8; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", argv[idx_ipv4_2]->arg, - argv[idx_ipv4_3]->arg, 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + char *dst_wildcard = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + dst = argv[idx + 1]->arg; + dst_wildcard = argv[idx + 2]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + "0.0.0.0", dst, dst_wildcard, 1, 0); } DEFUN (no_access_list_extended_host_host, no_access_list_extended_host_host_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip host A.B.C.D host A.B.C.D", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip host A.B.C.D host A.B.C.D", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1161,22 +1685,42 @@ DEFUN (no_access_list_extended_host_host, "Destination address\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 6; - int idx_ipv4_2 = 8; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, - "0.0.0.0", argv[idx_ipv4_2]->arg, "0.0.0.0", 1, - 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + char *dst = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) { + src = argv[idx]->arg; + dst = argv[idx + 2]->arg; + } + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, + "0.0.0.0", dst, "0.0.0.0", 1, 0); } DEFUN (no_access_list_extended_any_host, no_access_list_extended_any_host_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip any host A.B.C.D", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip any host A.B.C.D", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1185,20 +1729,40 @@ DEFUN (no_access_list_extended_any_host, "Destination address\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 7; - return filter_set_cisco( - vty, argv[idx_acl]->arg, argv[idx_permit_deny]->arg, "0.0.0.0", - "255.255.255.255", argv[idx_ipv4]->arg, "0.0.0.0", 1, 0); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *dst = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + dst = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, + "0.0.0.0", "255.255.255.255", dst, "0.0.0.0", 1, + 0); } DEFUN (no_access_list_extended_host_any, no_access_list_extended_host_any_cmd, - "no access-list <(100-199)|(2000-2699)> <deny|permit> ip host A.B.C.D any", + "no access-list <(100-199)|(2000-2699)> [seq (1-4294967295)] <deny|permit> ip host A.B.C.D any", NO_STR "Add an access list entry\n" "IP extended access list\n" "IP extended access list (expanded range)\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any Internet Protocol\n" @@ -1207,23 +1771,41 @@ DEFUN (no_access_list_extended_host_any, "Any destination host\n") { int idx_acl = 2; - int idx_permit_deny = 3; - int idx_ipv4 = 6; - return filter_set_cisco(vty, argv[idx_acl]->arg, - argv[idx_permit_deny]->arg, argv[idx_ipv4]->arg, + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *src = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D", &idx); + if (idx) + src = argv[idx]->arg; + + return filter_set_cisco(vty, argv[idx_acl]->arg, seq, permit_deny, src, "0.0.0.0", "0.0.0.0", "255.255.255.255", 1, 0); } static int filter_set_zebra(struct vty *vty, const char *name_str, - const char *type_str, afi_t afi, + const char *seq, const char *type_str, afi_t afi, const char *prefix_str, int exact, int set) { int ret; - enum filter_type type; + enum filter_type type = FILTER_DENY; struct filter *mfilter; struct filter_zebra *filter; struct access_list *access; struct prefix p; + int64_t seqnum = -1; if (strlen(name_str) > ACL_NAMSIZ) { vty_out(vty, @@ -1233,14 +1815,19 @@ static int filter_set_zebra(struct vty *vty, const char *name_str, return CMD_WARNING_CONFIG_FAILED; } + if (seq) + seqnum = (int64_t)atol(seq); + /* Check of filter type. */ - if (strncmp(type_str, "p", 1) == 0) - type = FILTER_PERMIT; - else if (strncmp(type_str, "d", 1) == 0) - type = FILTER_DENY; - else { - vty_out(vty, "filter type must be [permit|deny]\n"); - return CMD_WARNING_CONFIG_FAILED; + if (type_str) { + if (strncmp(type_str, "p", 1) == 0) + type = FILTER_PERMIT; + else if (strncmp(type_str, "d", 1) == 0) + type = FILTER_DENY; + else { + vty_out(vty, "filter type must be [permit|deny]\n"); + return CMD_WARNING_CONFIG_FAILED; + } } /* Check string format of prefix and prefixlen. */ @@ -1269,6 +1856,7 @@ static int filter_set_zebra(struct vty *vty, const char *name_str, mfilter = filter_new(); mfilter->type = type; + mfilter->seq = seqnum; filter = &mfilter->u.zfilter; prefix_copy(&filter->prefix, &p); @@ -1298,67 +1886,145 @@ static int filter_set_zebra(struct vty *vty, const char *name_str, DEFUN (mac_access_list, mac_access_list_cmd, - "mac access-list WORD <deny|permit> X:X:X:X:X:X", + "mac access-list WORD [seq (1-4294967295)] <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" + "Sequence number of an entry\n" + "Sequence number\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); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *mac = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "X:X:X:X:X:X", &idx); + if (idx) + mac = argv[idx]->arg; + + return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, AFI_L2VPN, + mac, 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 mac access-list WORD [seq (1-4294967295)] <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" + "Sequence number of an entry\n" + "Sequence number\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); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + char *mac = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "X:X:X:X:X:X", &idx); + if (idx) + mac = argv[idx]->arg; + + return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, AFI_L2VPN, + mac, 0, 0); } DEFUN (mac_access_list_any, mac_access_list_any_cmd, - "mac access-list WORD <deny|permit> any", + "mac access-list WORD [seq (1-4294967295)] <deny|permit> any", "Add a mac access-list\n" "Add an access list entry\n" "MAC zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\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, + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, 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 mac access-list WORD [seq (1-4294967295)] <deny|permit> any", NO_STR "Remove a mac access-list\n" "Remove an access list entry\n" "MAC zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\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, + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, 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]", + "access-list WORD [seq (1-4294967295)] <deny|permit> A.B.C.D/M [exact-match]", "Add an access list entry\n" "IP zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Prefix to match. e.g. 10.0.0.0/8\n" @@ -1366,41 +2032,71 @@ DEFUN (access_list_exact, { int idx = 0; int exact = 0; - int idx_word = 1; - int idx_permit_deny = 2; - int idx_ipv4_prefixlen = 3; - idx = idx_ipv4_prefixlen; - + char *seq = NULL; + char *permit_deny = NULL; + char *prefix = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D/M", &idx); + if (idx) + prefix = argv[idx]->arg; + + idx = 0; if (argv_find(argv, argc, "exact-match", &idx)) exact = 1; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP, - argv[idx_ipv4_prefixlen]->arg, exact, 1); + return filter_set_zebra(vty, argv[1]->arg, seq, permit_deny, + AFI_IP, prefix, exact, 1); } DEFUN (access_list_any, access_list_any_cmd, - "access-list WORD <deny|permit> any", + "access-list WORD [seq (1-4294967295)] <deny|permit> any", "Add an access list entry\n" "IP zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Prefix to match. e.g. 10.0.0.0/8\n") { int idx_word = 1; - int idx_permit_deny = 2; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP, "0.0.0.0/0", - 0, 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, + AFI_IP, "0.0.0.0/0", 0, 1); } DEFUN (no_access_list_exact, no_access_list_exact_cmd, - "no access-list WORD <deny|permit> A.B.C.D/M [exact-match]", + "no access-list WORD [seq (1-4294967295)] <deny|permit> A.B.C.D/M [exact-match]", NO_STR "Add an access list entry\n" "IP zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Prefix to match. e.g. 10.0.0.0/8\n" @@ -1408,34 +2104,62 @@ DEFUN (no_access_list_exact, { int idx = 0; int exact = 0; - int idx_word = 2; - int idx_permit_deny = 3; - int idx_ipv4_prefixlen = 4; - idx = idx_ipv4_prefixlen; - + char *seq = NULL; + char *permit_deny = NULL; + char *prefix = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "A.B.C.D/M", &idx); + if (idx) + prefix = argv[idx]->arg; + + idx = 0; if (argv_find(argv, argc, "exact-match", &idx)) exact = 1; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP, - argv[idx_ipv4_prefixlen]->arg, exact, 0); + return filter_set_zebra(vty, argv[2]->arg, seq, permit_deny, + AFI_IP, prefix, exact, 0); } DEFUN (no_access_list_any, no_access_list_any_cmd, - "no access-list WORD <deny|permit> any", + "no access-list WORD [seq (1-4294967295)] <deny|permit> any", NO_STR "Add an access list entry\n" "IP zebra access-list name\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Prefix to match. e.g. 10.0.0.0/8\n") { - int idx_word = 2; - int idx_permit_deny = 3; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP, "0.0.0.0/0", - 0, 0); + int idx_word = 1; + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, + AFI_IP, "0.0.0.0/0", 0, 0); } DEFUN (no_access_list_all, @@ -1536,10 +2260,12 @@ DEFUN (no_access_list_remark_comment, DEFUN (ipv6_access_list_exact, ipv6_access_list_exact_cmd, - "ipv6 access-list WORD <deny|permit> X:X::X:X/M [exact-match]", + "ipv6 access-list WORD [seq (1-4294967295)] <deny|permit> X:X::X:X/M [exact-match]", IPV6_STR "Add an access list entry\n" "IPv6 zebra access-list\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "IPv6 prefix\n" @@ -1548,41 +2274,73 @@ DEFUN (ipv6_access_list_exact, int idx = 0; int exact = 0; int idx_word = 2; - int idx_allow = 3; - int idx_addr = 4; - idx = idx_addr; - + char *seq = NULL; + char *permit_deny = NULL; + char *prefix = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "X:X::X:X/M", &idx); + if (idx) + prefix = argv[idx]->arg; + + idx = 0; if (argv_find(argv, argc, "exact-match", &idx)) exact = 1; - return filter_set_zebra(vty, argv[idx_word]->arg, argv[idx_allow]->text, - AFI_IP6, argv[idx_addr]->arg, exact, 1); + return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, + AFI_IP6, prefix, exact, 1); } DEFUN (ipv6_access_list_any, ipv6_access_list_any_cmd, - "ipv6 access-list WORD <deny|permit> any", + "ipv6 access-list WORD [seq (1-4294967295)] <deny|permit> any", IPV6_STR "Add an access list entry\n" "IPv6 zebra access-list\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any prefixi to match\n") { int idx_word = 2; - int idx_permit_deny = 3; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP6, "::/0", 0, - 1); + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, + AFI_IP6, "::/0", 0, 1); } DEFUN (no_ipv6_access_list_exact, no_ipv6_access_list_exact_cmd, - "no ipv6 access-list WORD <deny|permit> X:X::X:X/M [exact-match]", + "no ipv6 access-list WORD [seq (1-4294967295)] <deny|permit> X:X::X:X/M [exact-match]", NO_STR IPV6_STR "Add an access list entry\n" "IPv6 zebra access-list\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Prefix to match. e.g. 3ffe:506::/32\n" @@ -1590,35 +2348,64 @@ DEFUN (no_ipv6_access_list_exact, { int idx = 0; int exact = 0; - int idx_word = 3; - int idx_permit_deny = 4; - int idx_ipv6_prefixlen = 5; - idx = idx_ipv6_prefixlen; - + int idx_word = 2; + char *seq = NULL; + char *permit_deny = NULL; + char *prefix = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "X:X::X:X/M", &idx); + if (idx) + prefix = argv[idx]->arg; + + idx = 0; if (argv_find(argv, argc, "exact-match", &idx)) exact = 1; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP6, - argv[idx_ipv6_prefixlen]->arg, exact, 0); + return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, + AFI_IP6, prefix, exact, 0); } DEFUN (no_ipv6_access_list_any, no_ipv6_access_list_any_cmd, - "no ipv6 access-list WORD <deny|permit> any", + "no ipv6 access-list WORD [seq (1-4294967295)] <deny|permit> any", NO_STR IPV6_STR "Add an access list entry\n" "IPv6 zebra access-list\n" + "Sequence number of an entry\n" + "Sequence number\n" "Specify packets to reject\n" "Specify packets to forward\n" "Any prefixi to match\n") { - int idx_word = 3; - int idx_permit_deny = 4; - return filter_set_zebra(vty, argv[idx_word]->arg, - argv[idx_permit_deny]->arg, AFI_IP6, "::/0", 0, - 0); + int idx_word = 2; + int idx = 0; + char *seq = NULL; + char *permit_deny = NULL; + + argv_find(argv, argc, "(1-4294967295)", &idx); + if (idx) + seq = argv[idx]->arg; + + idx = 0; + argv_find(argv, argc, "permit", &idx); + argv_find(argv, argc, "deny", &idx); + if (idx) + permit_deny = argv[idx]->arg; + + return filter_set_zebra(vty, argv[idx_word]->arg, seq, permit_deny, + AFI_IP6, "::/0", 0, 0); } @@ -1748,7 +2535,8 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi) write = 0; } - vty_out(vty, " %s%s", filter_type_str(mfilter), + vty_out(vty, " seq %" PRId64, mfilter->seq); + vty_out(vty, " %s%s", filter_type_str(mfilter), mfilter->type == FILTER_DENY ? " " : ""); if (!mfilter->cisco) @@ -1795,7 +2583,8 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi) write = 0; } - vty_out(vty, " %s%s", filter_type_str(mfilter), + vty_out(vty, " seq %" PRId64, mfilter->seq); + vty_out(vty, " %s%s", filter_type_str(mfilter), mfilter->type == FILTER_DENY ? " " : ""); if (!mfilter->cisco) @@ -1978,11 +2767,12 @@ static int config_write_access(struct vty *vty, afi_t afi) } for (mfilter = access->head; mfilter; mfilter = mfilter->next) { - vty_out(vty, "%saccess-list %s %s", + vty_out(vty, "%saccess-list %s seq %" PRId64 " %s", (afi == AFI_IP) ? ("") : ((afi == AFI_IP6) ? ("ipv6 ") : ("mac ")), - access->name, filter_type_str(mfilter)); + access->name, mfilter->seq, + filter_type_str(mfilter)); if (mfilter->cisco) config_write_access_cisco(vty, mfilter); @@ -2004,11 +2794,12 @@ static int config_write_access(struct vty *vty, afi_t afi) } for (mfilter = access->head; mfilter; mfilter = mfilter->next) { - vty_out(vty, "%saccess-list %s %s", + vty_out(vty, "%saccess-list %s seq %" PRId64 " %s", (afi == AFI_IP) ? ("") : ((afi == AFI_IP6) ? ("ipv6 ") : ("mac ")), - access->name, filter_type_str(mfilter)); + access->name, mfilter->seq, + filter_type_str(mfilter)); if (mfilter->cisco) config_write_access_cisco(vty, mfilter); diff --git a/lib/libfrr.c b/lib/libfrr.c index 3294a61295..0fc321d6e0 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -681,6 +681,7 @@ struct thread_master *frr_init(void) log_filter_cmd_init(); log_ref_init(); + log_ref_vty_init(); lib_error_init(); yang_init(); diff --git a/lib/prefix.c b/lib/prefix.c index 7abeebcd09..1a4a914e05 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -628,8 +628,15 @@ int prefix_match_network_statement(const struct prefix *n, return 1; } -void prefix_copy(struct prefix *dest, const struct prefix *src) +#ifdef __clang_analyzer__ +#undef prefix_copy /* cf. prefix.h */ +#endif + +void prefix_copy(union prefixptr udest, union prefixconstptr usrc) { + struct prefix *dest = udest.p; + const struct prefix *src = usrc.p; + dest->family = src->family; dest->prefixlen = src->prefixlen; @@ -674,8 +681,11 @@ void prefix_copy(struct prefix *dest, const struct prefix *src) * the same. Note that this routine has the same return value sense * as '==' (which is different from prefix_cmp). */ -int prefix_same(const struct prefix *p1, const struct prefix *p2) +int prefix_same(union prefixconstptr up1, union prefixconstptr up2) { + const struct prefix *p1 = up1.p; + const struct prefix *p2 = up2.p; + if ((p1 && !p2) || (!p1 && p2)) return 0; @@ -712,57 +722,59 @@ int prefix_same(const struct prefix *p1, const struct prefix *p2) } /* - * Return 0 if the network prefixes represented by the struct prefix - * arguments are the same prefix, and 1 otherwise. Network prefixes - * are considered the same if the prefix lengths are equal and the - * network parts are the same. Host bits (which are considered masked + * Return -1/0/1 comparing the prefixes in a way that gives a full/linear + * order. + * + * Network prefixes are considered the same if the prefix lengths are equal + * and the network parts are the same. Host bits (which are considered masked * by the prefix length) are not significant. Thus, 10.0.0.1/8 and * 10.0.0.2/8 are considered equivalent by this routine. Note that * this routine has the same return sense as strcmp (which is different * from prefix_same). */ -int prefix_cmp(const struct prefix *p1, const struct prefix *p2) +int prefix_cmp(union prefixconstptr up1, union prefixconstptr up2) { + const struct prefix *p1 = up1.p; + const struct prefix *p2 = up2.p; int offset; int shift; + int i; /* Set both prefix's head pointer. */ const uint8_t *pp1; const uint8_t *pp2; if (p1->family != p2->family) - return 1; + return numcmp(p1->family, p2->family); if (p1->family == AF_FLOWSPEC) { pp1 = (const uint8_t *)p1->u.prefix_flowspec.ptr; pp2 = (const uint8_t *)p2->u.prefix_flowspec.ptr; if (p1->u.prefix_flowspec.prefixlen != p2->u.prefix_flowspec.prefixlen) - return 1; + return numcmp(p1->u.prefix_flowspec.prefixlen, + p2->u.prefix_flowspec.prefixlen); offset = p1->u.prefix_flowspec.prefixlen; while (offset--) if (pp1[offset] != pp2[offset]) - return 1; + return numcmp(pp1[offset], pp2[offset]); return 0; } pp1 = p1->u.val; pp2 = p2->u.val; if (p1->prefixlen != p2->prefixlen) - return 1; + return numcmp(p1->prefixlen, p2->prefixlen); offset = p1->prefixlen / PNBBY; shift = p1->prefixlen % PNBBY; - if (shift) - if (maskbit[shift] & (pp1[offset] ^ pp2[offset])) - return 1; - - while (offset--) - if (pp1[offset] != pp2[offset]) - return 1; + i = memcmp(pp1, pp2, offset); + if (i) + return i; - return 0; + return numcmp(pp1[offset] & maskbit[shift], + pp2[offset] & maskbit[shift]); } /* diff --git a/lib/prefix.h b/lib/prefix.h index d57b43dac6..e338140f1a 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -410,12 +410,20 @@ extern const char *prefix2str(union prefixconstptr, char *, int); extern int prefix_match(const struct prefix *, const struct prefix *); extern int prefix_match_network_statement(const struct prefix *, const struct prefix *); -extern int prefix_same(const struct prefix *, const struct prefix *); -extern int prefix_cmp(const struct prefix *, const struct prefix *); +extern int prefix_same(union prefixconstptr, union prefixconstptr); +extern int prefix_cmp(union prefixconstptr, union prefixconstptr); extern int prefix_common_bits(const struct prefix *, const struct prefix *); -extern void prefix_copy(struct prefix *dest, const struct prefix *src); +extern void prefix_copy(union prefixptr, union prefixconstptr); extern void apply_mask(struct prefix *); +#ifdef __clang_analyzer__ +/* clang-SA doesn't understand transparent unions, making it think that the + * target of prefix_copy is uninitialized. So just memset the target. + * cf. https://bugs.llvm.org/show_bug.cgi?id=42811 + */ +#define prefix_copy(a, b) ({ memset(a, 0, sizeof(*a)); prefix_copy(a, b); }) +#endif + extern struct prefix *sockunion2prefix(const union sockunion *dest, const union sockunion *mask); extern struct prefix *sockunion2hostprefix(const union sockunion *, diff --git a/lib/routemap.c b/lib/routemap.c index 2fee3a479e..eca02e8366 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -927,15 +927,15 @@ static const char *route_map_type_str(enum route_map_type type) return ""; } -static const char *route_map_result_str(route_map_result_t res) +static const char *route_map_cmd_result_str(enum route_map_cmd_result_t res) { switch (res) { case RMAP_MATCH: return "match"; - case RMAP_DENYMATCH: - return "deny"; case RMAP_NOMATCH: return "no match"; + case RMAP_NOOP: + return "noop"; case RMAP_ERROR: return "error"; case RMAP_OKAY: @@ -945,6 +945,18 @@ static const char *route_map_result_str(route_map_result_t res) return "invalid"; } +static const char *route_map_result_str(route_map_result_t res) +{ + switch (res) { + case RMAP_DENYMATCH: + return "deny"; + case RMAP_PERMITMATCH: + return "permit"; + } + + return "invalid"; +} + static int route_map_empty(struct route_map *map) { if (map->head == NULL && map->tail == NULL) @@ -1558,20 +1570,98 @@ int route_map_delete_set(struct route_map_index *index, const char *set_name, return 1; } +static enum route_map_cmd_result_t +route_map_apply_match(struct route_map_rule_list *match_list, + const struct prefix *prefix, route_map_object_t type, + void *object) +{ + enum route_map_cmd_result_t ret = RMAP_NOMATCH; + struct route_map_rule *match; + bool is_matched = false; + + + /* Check all match rule and if there is no match rule, go to the + set statement. */ + if (!match_list->head) + ret = RMAP_MATCH; + else { + for (match = match_list->head; match; match = match->next) { + /* + * Try each match statement. If any match does not + * return RMAP_MATCH or RMAP_NOOP, return. + * Otherwise continue on to next match statement. + * All match statements must MATCH for + * end-result to be a match. + * (Exception:If match stmts result in a mix of + * MATCH/NOOP, then also end-result is a match) + * If all result in NOOP, end-result is NOOP. + */ + ret = (*match->cmd->func_apply)(match->value, prefix, + type, object); + + /* + * If the consolidated result of func_apply is: + * ----------------------------------------------- + * | MATCH | NOMATCH | NOOP | Final Result | + * ------------------------------------------------ + * | yes | yes | yes | NOMATCH | + * | no | no | yes | NOOP | + * | yes | no | yes | MATCH | + * | no | yes | yes | NOMATCH | + * |----------------------------------------------- + * + * Traditionally, all rules within route-map + * should match for it to MATCH. + * If there are noops within the route-map rules, + * it follows the above matrix. + * + * Eg: route-map rm1 permit 10 + * match rule1 + * match rule2 + * match rule3 + * .... + * route-map rm1 permit 20 + * match ruleX + * match ruleY + * ... + */ + + switch (ret) { + case RMAP_MATCH: + is_matched = true; + break; + + case RMAP_NOMATCH: + return ret; + + case RMAP_NOOP: + if (is_matched) + ret = RMAP_MATCH; + break; + + default: + break; + } + + } + } + return ret; +} + /* Apply route map's each index to the object. The matrix for a route-map looks like this: (note, this includes the description for the "NEXT" and "GOTO" frobs now - Match | No Match - | - permit action | cont - | - ------------------+--------------- - | - deny deny | cont - | + | Match | No Match | No op + |-----------|--------------|------- + permit | action | cont | cont. + | | default:deny | default:permit + -------------------+----------------------- + | deny | cont | cont. + deny | | default:deny | default:permit + |-----------|--------------|-------- action) -Apply Set statements, accept route @@ -1604,45 +1694,13 @@ int route_map_delete_set(struct route_map_index *index, const char *set_name, We need to make sure our route-map processing matches the above */ - -static route_map_result_t -route_map_apply_match(struct route_map_rule_list *match_list, - const struct prefix *prefix, route_map_object_t type, - void *object) -{ - route_map_result_t ret = RMAP_NOMATCH; - struct route_map_rule *match; - - - /* Check all match rule and if there is no match rule, go to the - set statement. */ - if (!match_list->head) - ret = RMAP_MATCH; - else { - for (match = match_list->head; match; match = match->next) { - /* Try each match statement in turn, If any do not - return - RMAP_MATCH, return, otherwise continue on to next - match - statement. All match statements must match for - end-result - to be a match. */ - ret = (*match->cmd->func_apply)(match->value, prefix, - type, object); - if (ret != RMAP_MATCH) - return ret; - } - } - return ret; -} - -/* Apply route map to the object. */ route_map_result_t route_map_apply(struct route_map *map, const struct prefix *prefix, route_map_object_t type, void *object) { static int recursion = 0; - int ret = 0; + enum route_map_cmd_result_t match_ret = RMAP_NOMATCH; + route_map_result_t ret = RMAP_PERMITMATCH; struct route_map_index *index; struct route_map_rule *set; char buf[PREFIX_STRLEN]; @@ -1656,7 +1714,7 @@ route_map_result_t route_map_apply(struct route_map *map, return RMAP_DENYMATCH; } - if (map == NULL) { + if (map == NULL || map->head == NULL) { ret = RMAP_DENYMATCH; goto route_map_apply_end; } @@ -1665,29 +1723,64 @@ route_map_result_t route_map_apply(struct route_map *map, for (index = map->head; index; index = index->next) { /* Apply this index. */ index->applied++; - ret = route_map_apply_match(&index->match_list, prefix, type, - object); + match_ret = route_map_apply_match(&index->match_list, prefix, + type, object); if (rmap_debug) { zlog_debug("Route-map: %s, sequence: %d, prefix: %s, result: %s", map->name, index->pref, prefix2str(prefix, buf, sizeof(buf)), - route_map_result_str(ret)); + route_map_cmd_result_str(match_ret)); } /* Now we apply the matrix from above */ - if (ret == RMAP_NOMATCH) - /* 'cont' from matrix - continue to next route-map - * sequence */ + if (match_ret == RMAP_NOOP) + /* + * Do not change the return value. Retain the previous + * return value. Previous values can be: + * 1)permitmatch (if a nomatch was never + * seen before in this route-map.) + * 2)denymatch (if a nomatch was seen earlier in one + * of the previous sequences) + */ + + /* + * 'cont' from matrix - continue to next route-map + * sequence + */ continue; - else if (ret == RMAP_MATCH) { + else if (match_ret == RMAP_NOMATCH) { + + /* + * The return value is now changed to denymatch. + * So from here on out, even if we see more noops, + * we retain this return value and return this + * eventually if there are no matches. + */ + ret = RMAP_DENYMATCH; + + /* + * 'cont' from matrix - continue to next route-map + * sequence + */ + continue; + } else if (match_ret == RMAP_MATCH) { if (index->type == RMAP_PERMIT) /* 'action' */ { + /* Match succeeded, rmap is of type permit */ + ret = RMAP_PERMITMATCH; + /* permit+match must execute sets */ for (set = index->set_list.head; set; set = set->next) - ret = (*set->cmd->func_apply)( + /* + * set cmds return RMAP_OKAY or + * RMAP_ERROR. We do not care if + * set succeeded or not. So, ignore + * return code. + */ + (void) (*set->cmd->func_apply)( set->value, prefix, type, object); @@ -1741,8 +1834,6 @@ route_map_result_t route_map_apply(struct route_map *map, } } } - /* Finally route-map does not match at all. */ - ret = RMAP_DENYMATCH; route_map_apply_end: if (rmap_debug) { diff --git a/lib/routemap.h b/lib/routemap.h index 90df1048ed..f9ad0f64a9 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -38,13 +38,35 @@ DECLARE_MTYPE(ROUTE_MAP_COMPILED) enum route_map_type { RMAP_PERMIT, RMAP_DENY, RMAP_ANY }; typedef enum { - RMAP_MATCH, RMAP_DENYMATCH, - RMAP_NOMATCH, - RMAP_ERROR, - RMAP_OKAY + RMAP_PERMITMATCH } route_map_result_t; +/* + * Route-map match or set result "Eg: match evpn vni xx" + * route-map match cmd always returns match/nomatch/noop + * match--> found a match + * nomatch--> didnt find a match + * noop--> not applicable + * route-map set retuns okay/error + * okay --> set was successful + * error --> set was not successful + */ +enum route_map_cmd_result_t { + /* + * route-map match cmd results + */ + RMAP_MATCH, + RMAP_NOMATCH, + RMAP_NOOP, + /* + * route-map set cmd results + */ + RMAP_OKAY, + RMAP_ERROR +}; + + typedef enum { RMAP_RIP, RMAP_RIPNG, @@ -91,10 +113,10 @@ struct route_map_rule_cmd { const char *str; /* Function for value set or match. */ - route_map_result_t (*func_apply)(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object); + enum route_map_cmd_result_t (*func_apply)(void *rule, + const struct prefix *prefix, + route_map_object_t type, + void *object); /* Compile argument and return result as void *. */ void *(*func_compile)(const char *); diff --git a/lib/typerb.c b/lib/typerb.c index 4c48d6434f..3886fc678e 100644 --- a/lib/typerb.c +++ b/lib/typerb.c @@ -333,9 +333,10 @@ color: return (old); } -void typed_rb_remove(struct rbt_tree *rbt, struct rb_entry *rbe) +struct typed_rb_entry *typed_rb_remove(struct rbt_tree *rbt, + struct rb_entry *rbe) { - rbe_remove(rbt, rbe); + return rbe_remove(rbt, rbe); } struct typed_rb_entry *typed_rb_insert(struct rbt_tree *rbt, diff --git a/lib/typerb.h b/lib/typerb.h index ce8446f853..2d7b0ba637 100644 --- a/lib/typerb.h +++ b/lib/typerb.h @@ -38,29 +38,30 @@ struct typed_rb_root { size_t count; }; -struct typed_rb_entry *typed_rb_insert(struct typed_rb_root *, +struct typed_rb_entry *typed_rb_insert(struct typed_rb_root *rbt, struct typed_rb_entry *rbe, int (*cmpfn)( const struct typed_rb_entry *a, const struct typed_rb_entry *b)); -void typed_rb_remove(struct typed_rb_root *, struct typed_rb_entry *rbe); -struct typed_rb_entry *typed_rb_find(struct typed_rb_root *, +struct typed_rb_entry *typed_rb_remove(struct typed_rb_root *rbt, + struct typed_rb_entry *rbe); +struct typed_rb_entry *typed_rb_find(struct typed_rb_root *rbt, const struct typed_rb_entry *rbe, int (*cmpfn)( const struct typed_rb_entry *a, const struct typed_rb_entry *b)); -struct typed_rb_entry *typed_rb_find_gteq(struct typed_rb_root *, +struct typed_rb_entry *typed_rb_find_gteq(struct typed_rb_root *rbt, const struct typed_rb_entry *rbe, int (*cmpfn)( const struct typed_rb_entry *a, const struct typed_rb_entry *b)); -struct typed_rb_entry *typed_rb_find_lt(struct typed_rb_root *, +struct typed_rb_entry *typed_rb_find_lt(struct typed_rb_root *rbt, const struct typed_rb_entry *rbe, int (*cmpfn)( const struct typed_rb_entry *a, const struct typed_rb_entry *b)); -struct typed_rb_entry *typed_rb_min(struct typed_rb_root *); -struct typed_rb_entry *typed_rb_next(struct typed_rb_entry *); +struct typed_rb_entry *typed_rb_min(struct typed_rb_root *rbt); +struct typed_rb_entry *typed_rb_next(struct typed_rb_entry *rbe); #define _PREDECL_RBTREE(prefix) \ struct prefix ## _head { struct typed_rb_root rr; }; \ @@ -99,9 +100,11 @@ macro_inline type *prefix ## _find_lt(struct prefix##_head *h, \ re = typed_rb_find_lt(&h->rr, &item->field.re, cmpfn_nuq); \ return container_of_null(re, type, field.re); \ } \ -macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ +macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ { \ - typed_rb_remove(&h->rr, &item->field.re); \ + struct typed_rb_entry *re; \ + re = typed_rb_remove(&h->rr, &item->field.re); \ + return container_of_null(re, type, field.re); \ } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ { \ @@ -130,7 +133,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \ re = item ? typed_rb_next(&item->field.re) : NULL; \ return container_of_null(re, type, field.re); \ } \ -macro_pure size_t prefix ## _count(struct prefix##_head *h) \ +macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->rr.count; \ } \ diff --git a/lib/typesafe.c b/lib/typesafe.c index f2ca67b7c6..7e5939d5b3 100644 --- a/lib/typesafe.c +++ b/lib/typesafe.c @@ -341,13 +341,14 @@ struct sskip_item *typesafe_skiplist_find_lt(struct sskip_head *head, return best; } -void typesafe_skiplist_del(struct sskip_head *head, struct sskip_item *item, - int (*cmpfn)(const struct sskip_item *a, - const struct sskip_item *b)) +struct sskip_item *typesafe_skiplist_del( + struct sskip_head *head, struct sskip_item *item, + int (*cmpfn)(const struct sskip_item *a, const struct sskip_item *b)) { size_t level = SKIPLIST_MAXDEPTH; struct sskip_item *prev = &head->hitem, *next; int cmpval; + bool found = false; while (level) { next = sl_level_get(prev, level - 1); @@ -359,6 +360,7 @@ void typesafe_skiplist_del(struct sskip_head *head, struct sskip_item *item, sl_level_set(prev, level - 1, sl_level_get(item, level - 1)); level--; + found = true; continue; } cmpval = cmpfn(next, item); @@ -369,6 +371,9 @@ void typesafe_skiplist_del(struct sskip_head *head, struct sskip_item *item, level--; } + if (!found) + return NULL; + /* TBD: assert when trying to remove non-existing item? */ head->count--; @@ -379,6 +384,8 @@ void typesafe_skiplist_del(struct sskip_head *head, struct sskip_item *item, XFREE(MTYPE_SKIPLIST_OFLOW, oflow); } memset(item, 0, sizeof(*item)); + + return item; } struct sskip_item *typesafe_skiplist_pop(struct sskip_head *head) diff --git a/lib/typesafe.h b/lib/typesafe.h index 0a4ed69e4e..c30d73d1b3 100644 --- a/lib/typesafe.h +++ b/lib/typesafe.h @@ -109,17 +109,18 @@ macro_inline void prefix ## _add_after(struct prefix##_head *h, \ typesafe_list_add(&h->sh, nextp, &item->field.si); \ } \ /* TODO: del_hint */ \ -macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ +macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ { \ struct slist_item **iter = &h->sh.first; \ while (*iter && *iter != &item->field.si) \ iter = &(*iter)->next; \ if (!*iter) \ - return; \ + return NULL; \ h->sh.count--; \ *iter = item->field.si.next; \ if (!item->field.si.next) \ h->sh.last_next = iter; \ + return item; \ } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ { \ @@ -149,7 +150,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \ sitem = &item->field.si; \ return container_of_null(sitem->next, type, field.si); \ } \ -macro_pure size_t prefix ## _count(struct prefix##_head *h) \ +macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->sh.count; \ } \ @@ -212,13 +213,14 @@ macro_inline void prefix ## _add_after(struct prefix##_head *h, \ prev = after ? &after->field.di : &h->dh.hitem; \ typesafe_dlist_add(&h->dh, prev, &item->field.di); \ } \ -macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ +macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ { \ struct dlist_item *ditem = &item->field.di; \ ditem->prev->next = ditem->next; \ ditem->next->prev = ditem->prev; \ h->dh.count--; \ ditem->prev = ditem->next = NULL; \ + return item; \ } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ { \ @@ -250,7 +252,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \ return NULL; \ return prefix ## _next(h, item); \ } \ -macro_pure size_t prefix ## _count(struct prefix##_head *h) \ +macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->dh.count; \ } \ @@ -308,7 +310,7 @@ macro_inline type *prefix ## _add(struct prefix##_head *h, type *item) \ h->hh.count++; \ return NULL; \ } \ -macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ +macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ { \ struct heap_item *other; \ uint32_t index = item->field.hi.index; \ @@ -321,6 +323,7 @@ macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ typesafe_heap_pushdown(&h->hh, index, other, prefix ## __cmp); \ if (HEAP_RESIZE_TRESH_DN(h)) \ typesafe_heap_resize(&h->hh, false); \ + return item; \ } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ { \ @@ -354,7 +357,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \ return NULL; \ return prefix ## _next(h, item); \ } \ -macro_pure size_t prefix ## _count(struct prefix##_head *h) \ +macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->hh.count; \ } \ @@ -434,7 +437,7 @@ macro_inline type *prefix ## _find_gteq(struct prefix##_head *h, \ struct ssort_item *sitem = h->sh.first; \ int cmpval = 0; \ while (sitem && (cmpval = cmpfn_nuq( \ - container_of(sitem, type, field.si), item) < 0)) \ + container_of(sitem, type, field.si), item)) < 0) \ sitem = sitem->next; \ return container_of_null(sitem, type, field.si); \ } \ @@ -444,20 +447,21 @@ macro_inline type *prefix ## _find_lt(struct prefix##_head *h, \ struct ssort_item *prev = NULL, *sitem = h->sh.first; \ int cmpval = 0; \ while (sitem && (cmpval = cmpfn_nuq( \ - container_of(sitem, type, field.si), item) < 0)) \ + container_of(sitem, type, field.si), item)) < 0) \ sitem = (prev = sitem)->next; \ return container_of_null(prev, type, field.si); \ } \ /* TODO: del_hint */ \ -macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ +macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ { \ struct ssort_item **iter = &h->sh.first; \ while (*iter && *iter != &item->field.si) \ iter = &(*iter)->next; \ if (!*iter) \ - return; \ + return NULL; \ h->sh.count--; \ *iter = item->field.si.next; \ + return item; \ } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ { \ @@ -485,7 +489,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \ sitem = &item->field.si; \ return container_of_null(sitem->next, type, field.si); \ } \ -macro_pure size_t prefix ## _count(struct prefix##_head *h) \ +macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->sh.count; \ } \ @@ -499,7 +503,7 @@ macro_inline type *prefix ## _find(struct prefix##_head *h, const type *item) \ struct ssort_item *sitem = h->sh.first; \ int cmpval = 0; \ while (sitem && (cmpval = cmpfn( \ - container_of(sitem, type, field.si), item) < 0)) \ + container_of(sitem, type, field.si), item)) < 0) \ sitem = sitem->next; \ if (!sitem || cmpval > 0) \ return NULL; \ @@ -617,10 +621,10 @@ macro_inline type *prefix ## _find(struct prefix##_head *h, const type *item) \ } \ return NULL; \ } \ -macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ +macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ { \ if (!h->hh.tabshift) \ - return; \ + return NULL; \ uint32_t hval = item->field.hi.hashval, hbits = HASH_KEY(h->hh, hval); \ struct thash_item **np = &h->hh.entries[hbits]; \ while (*np && (*np)->hashval < hval) \ @@ -628,12 +632,13 @@ macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ while (*np && *np != &item->field.hi && (*np)->hashval == hval) \ np = &(*np)->next; \ if (*np != &item->field.hi) \ - return; \ + return NULL; \ *np = item->field.hi.next; \ item->field.hi.next = NULL; \ h->hh.count--; \ if (HASH_SHRINK_THRESHOLD(h->hh)) \ typesafe_hash_shrink(&h->hh); \ + return item; \ } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ { \ @@ -675,7 +680,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \ return NULL; \ return prefix ## _next(h, item); \ } \ -macro_pure size_t prefix ## _count(struct prefix##_head *h) \ +macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->hh.count; \ } \ @@ -751,9 +756,11 @@ macro_inline type *prefix ## _find_lt(struct prefix##_head *h, \ &item->field.si, cmpfn_nuq); \ return container_of_null(sitem, type, field.si); \ } \ -macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \ +macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \ { \ - typesafe_skiplist_del(&h->sh, &item->field.si, cmpfn_uq); \ + struct sskip_item *sitem = typesafe_skiplist_del(&h->sh, \ + &item->field.si, cmpfn_uq); \ + return container_of_null(sitem, type, field.si); \ } \ macro_inline type *prefix ## _pop(struct prefix##_head *h) \ { \ @@ -776,7 +783,7 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \ next = item ? item->field.si.next[0] : NULL; \ return container_of_null(next, type, field.si); \ } \ -macro_pure size_t prefix ## _count(struct prefix##_head *h) \ +macro_pure size_t prefix ## _count(const struct prefix##_head *h) \ { \ return h->sh.count; \ } \ @@ -848,8 +855,8 @@ extern struct sskip_item *typesafe_skiplist_find_lt(struct sskip_head *head, const struct sskip_item *item, int (*cmpfn)( const struct sskip_item *a, const struct sskip_item *b)); -extern void typesafe_skiplist_del(struct sskip_head *head, - struct sskip_item *item, int (*cmpfn)( +extern struct sskip_item *typesafe_skiplist_del( + struct sskip_head *head, struct sskip_item *item, int (*cmpfn)( const struct sskip_item *a, const struct sskip_item *b)); extern struct sskip_item *typesafe_skiplist_pop(struct sskip_head *head); |
