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