]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_filter.c
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[mirror_frr.git] / bgpd / bgp_filter.c
CommitLineData
718e3744 1/* AS path filter list.
896014f4
DL
2 * Copyright (C) 1999 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
718e3744 20
21#include <zebra.h>
22
23#include "command.h"
24#include "log.h"
25#include "memory.h"
26#include "buffer.h"
3f9c7369 27#include "queue.h"
039f3a34 28#include "filter.h"
718e3744 29
30#include "bgpd/bgpd.h"
31#include "bgpd/bgp_aspath.h"
32#include "bgpd/bgp_regex.h"
33#include "bgpd/bgp_filter.h"
34
35/* List of AS filter list. */
d62a17ae 36struct as_list_list {
37 struct as_list *head;
38 struct as_list *tail;
718e3744 39};
40
41/* AS path filter master. */
d62a17ae 42struct as_list_master {
d62a17ae 43 /* List of access_list which name is string. */
44 struct as_list_list str;
718e3744 45
d62a17ae 46 /* Hook function which is executed when new access_list is added. */
47 void (*add_hook)(char *);
718e3744 48
d62a17ae 49 /* Hook function which is executed when access_list is deleted. */
50 void (*delete_hook)(const char *);
718e3744 51};
52
53/* Element of AS path filter. */
d62a17ae 54struct as_filter {
55 struct as_filter *next;
56 struct as_filter *prev;
718e3744 57
d62a17ae 58 enum as_filter_type type;
718e3744 59
d62a17ae 60 regex_t *reg;
61 char *reg_str;
9b6f73ee
CS
62
63 /* Sequence number. */
64 int64_t seq;
718e3744 65};
66
718e3744 67/* AS path filter list. */
d62a17ae 68struct as_list {
69 char *name;
718e3744 70
d62a17ae 71 struct as_list *next;
72 struct as_list *prev;
718e3744 73
d62a17ae 74 struct as_filter *head;
75 struct as_filter *tail;
718e3744 76};
6b0655a2 77
9b6f73ee
CS
78
79/* Calculate new sequential number. */
80static int64_t bgp_alist_new_seq_get(struct as_list *list)
81{
82 int64_t maxseq;
83 int64_t newseq;
84 struct as_filter *entry;
85
86 maxseq = 0;
87
88 for (entry = list->head; entry; entry = entry->next) {
89 if (maxseq < entry->seq)
90 maxseq = entry->seq;
91 }
92
93 newseq = ((maxseq / 5) * 5) + 5;
94
95 return (newseq > UINT_MAX) ? UINT_MAX : newseq;
96}
97
98/* Return as-list entry which has same seq number. */
99static struct as_filter *bgp_aslist_seq_check(struct as_list *list, int64_t seq)
100{
101 struct as_filter *entry;
102
103 for (entry = list->head; entry; entry = entry->next)
104 if (entry->seq == seq)
105 return entry;
106
107 return NULL;
108}
109
7336e101 110/* as-path access-list 10 permit AS1. */
718e3744 111
d62a17ae 112static struct as_list_master as_list_master = {{NULL, NULL},
d62a17ae 113 NULL,
114 NULL};
718e3744 115
116/* Allocate new AS filter. */
d62a17ae 117static struct as_filter *as_filter_new(void)
718e3744 118{
d62a17ae 119 return XCALLOC(MTYPE_AS_FILTER, sizeof(struct as_filter));
718e3744 120}
121
122/* Free allocated AS filter. */
d62a17ae 123static void as_filter_free(struct as_filter *asfilter)
718e3744 124{
d62a17ae 125 if (asfilter->reg)
126 bgp_regex_free(asfilter->reg);
0a22ddfb 127 XFREE(MTYPE_AS_FILTER_STR, asfilter->reg_str);
d62a17ae 128 XFREE(MTYPE_AS_FILTER, asfilter);
718e3744 129}
130
131/* Make new AS filter. */
d62a17ae 132static struct as_filter *as_filter_make(regex_t *reg, const char *reg_str,
133 enum as_filter_type type)
718e3744 134{
d62a17ae 135 struct as_filter *asfilter;
718e3744 136
d62a17ae 137 asfilter = as_filter_new();
138 asfilter->reg = reg;
139 asfilter->type = type;
140 asfilter->reg_str = XSTRDUP(MTYPE_AS_FILTER_STR, reg_str);
718e3744 141
d62a17ae 142 return asfilter;
718e3744 143}
144
d62a17ae 145static struct as_filter *as_filter_lookup(struct as_list *aslist,
146 const char *reg_str,
147 enum as_filter_type type)
718e3744 148{
d62a17ae 149 struct as_filter *asfilter;
718e3744 150
d62a17ae 151 for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
152 if (strcmp(reg_str, asfilter->reg_str) == 0)
153 return asfilter;
154 return NULL;
718e3744 155}
156
9b6f73ee
CS
157static void as_filter_entry_replace(struct as_list *list,
158 struct as_filter *replace,
159 struct as_filter *entry)
160{
161 if (replace->next) {
162 entry->next = replace->next;
163 replace->next->prev = entry;
164 } else {
165 entry->next = NULL;
166 list->tail = entry;
167 }
168
169 if (replace->prev) {
170 entry->prev = replace->prev;
171 replace->prev->next = entry;
172 } else {
173 entry->prev = NULL;
174 list->head = entry;
175 }
176
177 as_filter_free(replace);
178}
179
d62a17ae 180static void as_list_filter_add(struct as_list *aslist,
181 struct as_filter *asfilter)
718e3744 182{
9b6f73ee
CS
183 struct as_filter *point;
184 struct as_filter *replace;
718e3744 185
9b6f73ee
CS
186 if (aslist->tail && asfilter->seq > aslist->tail->seq)
187 point = NULL;
188 else {
189 replace = bgp_aslist_seq_check(aslist, asfilter->seq);
190 if (replace) {
191 as_filter_entry_replace(aslist, replace, asfilter);
f709b31b 192 goto hook;
9b6f73ee
CS
193 }
194
195 /* Check insert point. */
196 for (point = aslist->head; point; point = point->next)
197 if (point->seq >= asfilter->seq)
198 break;
199 }
200
201 asfilter->next = point;
202
203 if (point) {
204 if (point->prev)
205 point->prev->next = asfilter;
206 else
207 aslist->head = asfilter;
208
209 asfilter->prev = point->prev;
210 point->prev = asfilter;
211 } else {
212 if (aslist->tail)
213 aslist->tail->next = asfilter;
214 else
215 aslist->head = asfilter;
216
217 asfilter->prev = aslist->tail;
218 aslist->tail = asfilter;
219 }
518f0eb1 220
f709b31b 221hook:
d62a17ae 222 /* Run hook function. */
223 if (as_list_master.add_hook)
224 (*as_list_master.add_hook)(aslist->name);
718e3744 225}
226
227/* Lookup as_list from list of as_list by name. */
d62a17ae 228struct as_list *as_list_lookup(const char *name)
718e3744 229{
d62a17ae 230 struct as_list *aslist;
718e3744 231
d62a17ae 232 if (name == NULL)
233 return NULL;
718e3744 234
d62a17ae 235 for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
236 if (strcmp(aslist->name, name) == 0)
237 return aslist;
718e3744 238
d62a17ae 239 return NULL;
718e3744 240}
241
d62a17ae 242static struct as_list *as_list_new(void)
718e3744 243{
d62a17ae 244 return XCALLOC(MTYPE_AS_LIST, sizeof(struct as_list));
718e3744 245}
246
d62a17ae 247static void as_list_free(struct as_list *aslist)
718e3744 248{
e1b36e13 249 XFREE(MTYPE_AS_STR, aslist->name);
d62a17ae 250 XFREE(MTYPE_AS_LIST, aslist);
718e3744 251}
252
253/* Insert new AS list to list of as_list. Each as_list is sorted by
254 the name. */
d62a17ae 255static struct as_list *as_list_insert(const char *name)
256{
d62a17ae 257 struct as_list *aslist;
258 struct as_list *point;
259 struct as_list_list *list;
260
261 /* Allocate new access_list and copy given name. */
262 aslist = as_list_new();
263 aslist->name = XSTRDUP(MTYPE_AS_STR, name);
264 assert(aslist->name);
265
3eff8e2f
IR
266 /* Set access_list to string list. */
267 list = &as_list_master.str;
d62a17ae 268
3eff8e2f
IR
269 /* Set point to insertion point. */
270 for (point = list->head; point; point = point->next)
271 if (strcmp(point->name, name) >= 0)
272 break;
d62a17ae 273
274 /* In case of this is the first element of master. */
275 if (list->head == NULL) {
276 list->head = list->tail = aslist;
277 return aslist;
278 }
279
280 /* In case of insertion is made at the tail of access_list. */
281 if (point == NULL) {
282 aslist->prev = list->tail;
283 list->tail->next = aslist;
284 list->tail = aslist;
285 return aslist;
286 }
287
288 /* In case of insertion is made at the head of access_list. */
289 if (point == list->head) {
290 aslist->next = list->head;
291 list->head->prev = aslist;
292 list->head = aslist;
293 return aslist;
294 }
295
296 /* Insertion is made at middle of the access_list. */
297 aslist->next = point;
298 aslist->prev = point->prev;
299
300 if (point->prev)
301 point->prev->next = aslist;
302 point->prev = aslist;
303
304 return aslist;
718e3744 305}
306
d62a17ae 307static struct as_list *as_list_get(const char *name)
718e3744 308{
d62a17ae 309 struct as_list *aslist;
718e3744 310
d62a17ae 311 aslist = as_list_lookup(name);
312 if (aslist == NULL)
313 aslist = as_list_insert(name);
718e3744 314
d62a17ae 315 return aslist;
718e3744 316}
317
d62a17ae 318static const char *filter_type_str(enum as_filter_type type)
718e3744 319{
d62a17ae 320 switch (type) {
321 case AS_FILTER_PERMIT:
322 return "permit";
323 case AS_FILTER_DENY:
324 return "deny";
325 default:
326 return "";
327 }
718e3744 328}
329
d62a17ae 330static void as_list_delete(struct as_list *aslist)
718e3744 331{
d62a17ae 332 struct as_list_list *list;
333 struct as_filter *filter, *next;
334
335 for (filter = aslist->head; filter; filter = next) {
336 next = filter->next;
337 as_filter_free(filter);
338 }
339
3eff8e2f 340 list = &as_list_master.str;
d62a17ae 341
342 if (aslist->next)
343 aslist->next->prev = aslist->prev;
344 else
345 list->tail = aslist->prev;
346
347 if (aslist->prev)
348 aslist->prev->next = aslist->next;
349 else
350 list->head = aslist->next;
351
352 as_list_free(aslist);
718e3744 353}
354
3dc339cd 355static bool as_list_empty(struct as_list *aslist)
718e3744 356{
3dc339cd 357 return aslist->head == NULL && aslist->tail == NULL;
718e3744 358}
359
d62a17ae 360static void as_list_filter_delete(struct as_list *aslist,
361 struct as_filter *asfilter)
718e3744 362{
d62a17ae 363 char *name = XSTRDUP(MTYPE_AS_STR, aslist->name);
518f0eb1 364
d62a17ae 365 if (asfilter->next)
366 asfilter->next->prev = asfilter->prev;
367 else
368 aslist->tail = asfilter->prev;
718e3744 369
d62a17ae 370 if (asfilter->prev)
371 asfilter->prev->next = asfilter->next;
372 else
373 aslist->head = asfilter->next;
718e3744 374
d62a17ae 375 as_filter_free(asfilter);
718e3744 376
d62a17ae 377 /* If access_list becomes empty delete it from access_master. */
378 if (as_list_empty(aslist))
379 as_list_delete(aslist);
718e3744 380
d62a17ae 381 /* Run hook function. */
382 if (as_list_master.delete_hook)
383 (*as_list_master.delete_hook)(name);
0a22ddfb 384 XFREE(MTYPE_AS_STR, name);
718e3744 385}
6b0655a2 386
3dc339cd 387static bool as_filter_match(struct as_filter *asfilter, struct aspath *aspath)
718e3744 388{
3dc339cd 389 return bgp_regexec(asfilter->reg, aspath) != REG_NOMATCH;
718e3744 390}
391
392/* Apply AS path filter to AS. */
d62a17ae 393enum as_filter_type as_list_apply(struct as_list *aslist, void *object)
718e3744 394{
d62a17ae 395 struct as_filter *asfilter;
396 struct aspath *aspath;
718e3744 397
d62a17ae 398 aspath = (struct aspath *)object;
718e3744 399
d62a17ae 400 if (aslist == NULL)
401 return AS_FILTER_DENY;
718e3744 402
d62a17ae 403 for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) {
404 if (as_filter_match(asfilter, aspath))
405 return asfilter->type;
406 }
407 return AS_FILTER_DENY;
718e3744 408}
409
410/* Add hook function. */
d62a17ae 411void as_list_add_hook(void (*func)(char *))
718e3744 412{
d62a17ae 413 as_list_master.add_hook = func;
718e3744 414}
415
416/* Delete hook function. */
d62a17ae 417void as_list_delete_hook(void (*func)(const char *))
718e3744 418{
d62a17ae 419 as_list_master.delete_hook = func;
718e3744 420}
6b0655a2 421
3dc339cd 422static bool as_list_dup_check(struct as_list *aslist, struct as_filter *new)
718e3744 423{
d62a17ae 424 struct as_filter *asfilter;
425
426 for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) {
427 if (asfilter->type == new->type
428 && strcmp(asfilter->reg_str, new->reg_str) == 0)
3dc339cd 429 return true;
d62a17ae 430 }
3dc339cd 431 return false;
718e3744 432}
433
3dc339cd 434bool config_bgp_aspath_validate(const char *regstr)
672c2d75 435{
da6035e9 436 char valid_chars[] = "1234567890_^|[,{}() ]$*+.?-\\";
672c2d75
DA
437
438 if (strspn(regstr, valid_chars) == strlen(regstr))
3dc339cd
DA
439 return true;
440 return false;
672c2d75
DA
441}
442
7336e101 443DEFUN(as_path, bgp_as_path_cmd,
2a342b35 444 "bgp as-path access-list AS_PATH_FILTER_NAME [seq (0-4294967295)] <deny|permit> LINE...",
7336e101 445 BGP_STR
672c2d75
DA
446 "BGP autonomous system path filter\n"
447 "Specify an access list name\n"
448 "Regular expression access list name\n"
9b6f73ee
CS
449 "Sequence number of an entry\n"
450 "Sequence number\n"
672c2d75
DA
451 "Specify packets to reject\n"
452 "Specify packets to forward\n"
a818ea74 453 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
718e3744 454{
d62a17ae 455 int idx = 0;
456 enum as_filter_type type;
457 struct as_filter *asfilter;
458 struct as_list *aslist;
459 regex_t *regex;
460 char *regstr;
9b6f73ee 461 int64_t seqnum = ASPATH_SEQ_NUMBER_AUTO;
d62a17ae 462
463 /* Retrieve access list name */
2a342b35 464 argv_find(argv, argc, "AS_PATH_FILTER_NAME", &idx);
e991f75c 465 char *alname = argv[idx]->arg;
d62a17ae 466
9b6f73ee
CS
467 if (argv_find(argv, argc, "(0-4294967295)", &idx))
468 seqnum = (int64_t)atol(argv[idx]->arg);
469
d62a17ae 470 /* Check the filter type. */
471 type = argv_find(argv, argc, "deny", &idx) ? AS_FILTER_DENY
472 : AS_FILTER_PERMIT;
473
474 /* Check AS path regex. */
475 argv_find(argv, argc, "LINE", &idx);
476 regstr = argv_concat(argv, argc, idx);
477
478 regex = bgp_regcomp(regstr);
479 if (!regex) {
480 vty_out(vty, "can't compile regexp %s\n", regstr);
481 XFREE(MTYPE_TMP, regstr);
482 return CMD_WARNING_CONFIG_FAILED;
483 }
484
672c2d75
DA
485 if (!config_bgp_aspath_validate(regstr)) {
486 vty_out(vty, "Invalid character in as-path access-list %s\n",
487 regstr);
e88307cf 488 XFREE(MTYPE_TMP, regstr);
672c2d75
DA
489 return CMD_WARNING_CONFIG_FAILED;
490 }
491
d62a17ae 492 asfilter = as_filter_make(regex, regstr, type);
493
494 XFREE(MTYPE_TMP, regstr);
495
496 /* Install new filter to the access_list. */
497 aslist = as_list_get(alname);
498
9b6f73ee
CS
499 if (seqnum == ASPATH_SEQ_NUMBER_AUTO)
500 seqnum = bgp_alist_new_seq_get(aslist);
501
502 asfilter->seq = seqnum;
503
d62a17ae 504 /* Duplicate insertion check. */;
505 if (as_list_dup_check(aslist, asfilter))
506 as_filter_free(asfilter);
507 else
508 as_list_filter_add(aslist, asfilter);
509
510 return CMD_SUCCESS;
718e3744 511}
512
7336e101 513DEFUN(no_as_path, no_bgp_as_path_cmd,
2a342b35 514 "no bgp as-path access-list AS_PATH_FILTER_NAME [seq (0-4294967295)] <deny|permit> LINE...",
7336e101
SP
515 NO_STR
516 BGP_STR
672c2d75
DA
517 "BGP autonomous system path filter\n"
518 "Specify an access list name\n"
519 "Regular expression access list name\n"
9b6f73ee
CS
520 "Sequence number of an entry\n"
521 "Sequence number\n"
672c2d75
DA
522 "Specify packets to reject\n"
523 "Specify packets to forward\n"
a818ea74 524 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n")
718e3744 525{
d62a17ae 526 int idx = 0;
527 enum as_filter_type type;
528 struct as_filter *asfilter;
529 struct as_list *aslist;
530 char *regstr;
531 regex_t *regex;
532
533 char *aslistname =
2a342b35 534 argv_find(argv, argc, "AS_PATH_FILTER_NAME", &idx) ? argv[idx]->arg : NULL;
d62a17ae 535
536 /* Lookup AS list from AS path list. */
537 aslist = as_list_lookup(aslistname);
538 if (aslist == NULL) {
7336e101 539 vty_out(vty, "bgp as-path access-list %s doesn't exist\n",
d62a17ae 540 aslistname);
541 return CMD_WARNING_CONFIG_FAILED;
542 }
543
544 /* Check the filter type. */
545 if (argv_find(argv, argc, "permit", &idx))
546 type = AS_FILTER_PERMIT;
547 else if (argv_find(argv, argc, "deny", &idx))
548 type = AS_FILTER_DENY;
549 else {
550 vty_out(vty, "filter type must be [permit|deny]\n");
551 return CMD_WARNING_CONFIG_FAILED;
552 }
553
554 /* Compile AS path. */
555 argv_find(argv, argc, "LINE", &idx);
556 regstr = argv_concat(argv, argc, idx);
557
672c2d75
DA
558 if (!config_bgp_aspath_validate(regstr)) {
559 vty_out(vty, "Invalid character in as-path access-list %s\n",
560 regstr);
561 return CMD_WARNING_CONFIG_FAILED;
562 }
563
d62a17ae 564 regex = bgp_regcomp(regstr);
565 if (!regex) {
566 vty_out(vty, "can't compile regexp %s\n", regstr);
567 XFREE(MTYPE_TMP, regstr);
568 return CMD_WARNING_CONFIG_FAILED;
569 }
570
571 /* Lookup asfilter. */
572 asfilter = as_filter_lookup(aslist, regstr, type);
573
d62a17ae 574 bgp_regex_free(regex);
575
576 if (asfilter == NULL) {
17b4e8c4
IR
577 vty_out(vty, "Regex entered %s does not exist\n", regstr);
578 XFREE(MTYPE_TMP, regstr);
d62a17ae 579 return CMD_WARNING_CONFIG_FAILED;
580 }
581
17b4e8c4
IR
582 XFREE(MTYPE_TMP, regstr);
583
d62a17ae 584 as_list_filter_delete(aslist, asfilter);
585
586 return CMD_SUCCESS;
718e3744 587}
588
7336e101
SP
589DEFUN (no_as_path_all,
590 no_bgp_as_path_all_cmd,
2a342b35 591 "no bgp as-path access-list AS_PATH_FILTER_NAME",
718e3744 592 NO_STR
7336e101 593 BGP_STR
718e3744 594 "BGP autonomous system path filter\n"
595 "Specify an access list name\n"
596 "Regular expression access list name\n")
597{
d62a17ae 598 int idx_word = 4;
599 struct as_list *aslist;
718e3744 600
d62a17ae 601 aslist = as_list_lookup(argv[idx_word]->arg);
602 if (aslist == NULL) {
7336e101 603 vty_out(vty, "bgp as-path access-list %s doesn't exist\n",
d62a17ae 604 argv[idx_word]->arg);
605 return CMD_WARNING_CONFIG_FAILED;
606 }
718e3744 607
d62a17ae 608 as_list_delete(aslist);
718e3744 609
d62a17ae 610 /* Run hook function. */
611 if (as_list_master.delete_hook)
612 (*as_list_master.delete_hook)(argv[idx_word]->arg);
e0701b79 613
d62a17ae 614 return CMD_SUCCESS;
718e3744 615}
616
b15e8360
RW
617static void as_list_show(struct vty *vty, struct as_list *aslist,
618 json_object *json)
4f991ef0 619{
d62a17ae 620 struct as_filter *asfilter;
b15e8360 621 json_object *json_aslist = NULL;
4f991ef0 622
b15e8360
RW
623 if (json) {
624 json_aslist = json_object_new_array();
625 json_object_object_add(json, aslist->name, json_aslist);
626 } else
627 vty_out(vty, "AS path access list %s\n", aslist->name);
4f991ef0 628
d62a17ae 629 for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) {
b15e8360
RW
630 if (json) {
631 json_object *json_asfilter = json_object_new_object();
632
633 json_object_int_add(json_asfilter, "sequenceNumber",
634 asfilter->seq);
635 json_object_string_add(json_asfilter, "type",
636 filter_type_str(asfilter->type));
637 json_object_string_add(json_asfilter, "regExp",
638 asfilter->reg_str);
639
640 json_object_array_add(json_aslist, json_asfilter);
641 } else
642 vty_out(vty, " %s %s\n",
643 filter_type_str(asfilter->type),
644 asfilter->reg_str);
d62a17ae 645 }
4f991ef0 646}
647
b15e8360 648static void as_list_show_all(struct vty *vty, json_object *json)
4f991ef0 649{
d62a17ae 650 struct as_list *aslist;
4f991ef0 651
b15e8360
RW
652 for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
653 as_list_show(vty, aslist, json);
4f991ef0 654}
655
7336e101
SP
656DEFUN (show_as_path_access_list,
657 show_bgp_as_path_access_list_cmd,
2a342b35 658 "show bgp as-path-access-list AS_PATH_FILTER_NAME [json]",
4f991ef0 659 SHOW_STR
7336e101 660 BGP_STR
4f991ef0 661 "List AS path access lists\n"
b15e8360
RW
662 "AS path access list name\n"
663 JSON_STR)
4f991ef0 664{
d62a17ae 665 int idx_word = 3;
666 struct as_list *aslist;
b15e8360
RW
667 bool uj = use_json(argc, argv);
668 json_object *json = NULL;
669
670 if (uj)
671 json = json_object_new_object();
4f991ef0 672
d62a17ae 673 aslist = as_list_lookup(argv[idx_word]->arg);
674 if (aslist)
b15e8360
RW
675 as_list_show(vty, aslist, json);
676
c48349e3 677 if (uj)
75eeda93 678 vty_json(vty, json);
4f991ef0 679
d62a17ae 680 return CMD_SUCCESS;
4f991ef0 681}
682
7336e101
SP
683ALIAS (show_as_path_access_list,
684 show_ip_as_path_access_list_cmd,
2a342b35 685 "show ip as-path-access-list AS_PATH_FILTER_NAME [json]",
4f991ef0 686 SHOW_STR
687 IP_STR
7336e101 688 "List AS path access lists\n"
b15e8360
RW
689 "AS path access list name\n"
690 JSON_STR)
7336e101
SP
691
692DEFUN (show_as_path_access_list_all,
693 show_bgp_as_path_access_list_all_cmd,
b15e8360 694 "show bgp as-path-access-list [json]",
7336e101
SP
695 SHOW_STR
696 BGP_STR
b15e8360
RW
697 "List AS path access lists\n"
698 JSON_STR)
4f991ef0 699{
b15e8360
RW
700 bool uj = use_json(argc, argv);
701 json_object *json = NULL;
702
703 if (uj)
704 json = json_object_new_object();
705
706 as_list_show_all(vty, json);
707
c48349e3 708 if (uj)
75eeda93 709 vty_json(vty, json);
b15e8360 710
d62a17ae 711 return CMD_SUCCESS;
4f991ef0 712}
713
7336e101
SP
714ALIAS (show_as_path_access_list_all,
715 show_ip_as_path_access_list_all_cmd,
b15e8360 716 "show ip as-path-access-list [json]",
7336e101
SP
717 SHOW_STR
718 IP_STR
b15e8360
RW
719 "List AS path access lists\n"
720 JSON_STR)
7336e101 721
d62a17ae 722static int config_write_as_list(struct vty *vty)
723{
724 struct as_list *aslist;
725 struct as_filter *asfilter;
726 int write = 0;
727
d62a17ae 728 for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
729 for (asfilter = aslist->head; asfilter;
730 asfilter = asfilter->next) {
9b6f73ee
CS
731 vty_out(vty,
732 "bgp as-path access-list %s seq %" PRId64
733 " %s %s\n",
734 aslist->name, asfilter->seq,
735 filter_type_str(asfilter->type),
d62a17ae 736 asfilter->reg_str);
737 write++;
738 }
739 return write;
718e3744 740}
741
612c2c15 742static int config_write_as_list(struct vty *vty);
62b346ee 743static struct cmd_node as_list_node = {
f4b8291f 744 .name = "as list",
62b346ee
DL
745 .node = AS_LIST_NODE,
746 .prompt = "",
612c2c15 747 .config_write = config_write_as_list,
62b346ee 748};
718e3744 749
2a342b35
DA
750static void bgp_aspath_filter_cmd_completion(vector comps,
751 struct cmd_token *token)
752{
753 struct as_list *aslist;
754
755 for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
756 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, aslist->name));
757}
758
759static const struct cmd_variable_handler aspath_filter_handlers[] = {
760 {.tokenname = "AS_PATH_FILTER_NAME",
761 .completions = bgp_aspath_filter_cmd_completion},
762 {.completions = NULL}};
763
718e3744 764/* Register functions. */
d62a17ae 765void bgp_filter_init(void)
718e3744 766{
612c2c15 767 install_node(&as_list_node);
718e3744 768
7336e101 769 install_element(CONFIG_NODE, &bgp_as_path_cmd);
7336e101 770 install_element(CONFIG_NODE, &no_bgp_as_path_cmd);
7336e101 771 install_element(CONFIG_NODE, &no_bgp_as_path_all_cmd);
4f991ef0 772
7336e101 773 install_element(VIEW_NODE, &show_bgp_as_path_access_list_cmd);
d62a17ae 774 install_element(VIEW_NODE, &show_ip_as_path_access_list_cmd);
7336e101 775 install_element(VIEW_NODE, &show_bgp_as_path_access_list_all_cmd);
d62a17ae 776 install_element(VIEW_NODE, &show_ip_as_path_access_list_all_cmd);
2a342b35
DA
777
778 cmd_variable_handler_register(aspath_filter_handlers);
718e3744 779}
228da428 780
d62a17ae 781void bgp_filter_reset(void)
228da428 782{
d62a17ae 783 struct as_list *aslist;
784 struct as_list *next;
785
d62a17ae 786 for (aslist = as_list_master.str.head; aslist; aslist = next) {
787 next = aslist->next;
788 as_list_delete(aslist);
789 }
790
d62a17ae 791 assert(as_list_master.str.head == NULL);
792 assert(as_list_master.str.tail == NULL);
228da428 793}