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