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