1
/* AS path filter list.
2
Copyright (C) 1999 Kunihiro Ishiguro
4
This file is part of GNU Zebra.
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
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.
16
You should have received a copy of the GNU General Public License
17
along with GNU Zebra; see the file COPYING. If not, write to the Free
18
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28
#include "bgpd/bgpd.h"
29
#include "bgpd/bgp_aspath.h"
30
#include "bgpd/bgp_regex.h"
31
#include "bgpd/bgp_filter.h"
33
/* List of AS filter list. */
40
/* AS path filter master. */
43
/* List of access_list which name is number. */
44
struct as_list_list num;
46
/* List of access_list which name is string. */
47
struct as_list_list str;
49
/* Hook function which is executed when new access_list is added. */
52
/* Hook function which is executed when access_list is deleted. */
53
void (*delete_hook) ();
56
/* Element of AS path filter. */
59
struct as_filter *next;
60
struct as_filter *prev;
62
enum as_filter_type type;
74
/* AS path filter list. */
79
enum as_list_type type;
84
struct as_filter *head;
85
struct as_filter *tail;
88
/* ip as-path access-list 10 permit AS1. */
90
static struct as_list_master as_list_master =
98
/* Allocate new AS filter. */
102
struct as_filter *new;
104
new = XMALLOC (MTYPE_AS_FILTER, sizeof (struct as_filter));
105
memset (new, 0, sizeof (struct as_filter));
109
/* Free allocated AS filter. */
111
as_filter_free (struct as_filter *asfilter)
114
bgp_regex_free (asfilter->reg);
115
if (asfilter->reg_str)
116
XFREE (MTYPE_AS_FILTER_STR, asfilter->reg_str);
117
XFREE (MTYPE_AS_FILTER, asfilter);
120
/* Make new AS filter. */
122
as_filter_make (regex_t *reg, const char *reg_str, enum as_filter_type type)
124
struct as_filter *asfilter;
126
asfilter = as_filter_new ();
128
asfilter->type = type;
129
asfilter->reg_str = XSTRDUP (MTYPE_AS_FILTER_STR, reg_str);
135
as_filter_lookup (struct as_list *aslist, const char *reg_str,
136
enum as_filter_type type)
138
struct as_filter *asfilter;
140
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
141
if (strcmp (reg_str, asfilter->reg_str) == 0)
147
as_list_filter_add (struct as_list *aslist, struct as_filter *asfilter)
149
asfilter->next = NULL;
150
asfilter->prev = aslist->tail;
153
aslist->tail->next = asfilter;
155
aslist->head = asfilter;
156
aslist->tail = asfilter;
159
/* Lookup as_list from list of as_list by name. */
161
as_list_lookup (const char *name)
163
struct as_list *aslist;
168
for (aslist = as_list_master.num.head; aslist; aslist = aslist->next)
169
if (strcmp (aslist->name, name) == 0)
172
for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
173
if (strcmp (aslist->name, name) == 0)
184
new = XMALLOC (MTYPE_AS_LIST, sizeof (struct as_list));
185
memset (new, 0, sizeof (struct as_list));
190
as_list_free (struct as_list *aslist)
192
XFREE (MTYPE_AS_LIST, aslist);
195
/* Insert new AS list to list of as_list. Each as_list is sorted by
198
as_list_insert (const char *name)
202
struct as_list *aslist;
203
struct as_list *point;
204
struct as_list_list *list;
206
/* Allocate new access_list and copy given name. */
207
aslist = as_list_new ();
208
aslist->name = strdup (name);
210
/* If name is made by all digit character. We treat it as
212
for (number = 0, i = 0; i < strlen (name); i++)
214
if (isdigit ((int) name[i]))
215
number = (number * 10) + (name[i] - '0');
220
/* In case of name is all digit character */
221
if (i == strlen (name))
223
aslist->type = ACCESS_TYPE_NUMBER;
225
/* Set access_list to number list. */
226
list = &as_list_master.num;
228
for (point = list->head; point; point = point->next)
229
if (atol (point->name) >= number)
234
aslist->type = ACCESS_TYPE_STRING;
236
/* Set access_list to string list. */
237
list = &as_list_master.str;
239
/* Set point to insertion point. */
240
for (point = list->head; point; point = point->next)
241
if (strcmp (point->name, name) >= 0)
245
/* In case of this is the first element of master. */
246
if (list->head == NULL)
248
list->head = list->tail = aslist;
252
/* In case of insertion is made at the tail of access_list. */
255
aslist->prev = list->tail;
256
list->tail->next = aslist;
261
/* In case of insertion is made at the head of access_list. */
262
if (point == list->head)
264
aslist->next = list->head;
265
list->head->prev = aslist;
270
/* Insertion is made at middle of the access_list. */
271
aslist->next = point;
272
aslist->prev = point->prev;
275
point->prev->next = aslist;
276
point->prev = aslist;
282
as_list_get (const char *name)
284
struct as_list *aslist;
286
aslist = as_list_lookup (name);
289
aslist = as_list_insert (name);
291
/* Run hook function. */
292
if (as_list_master.add_hook)
293
(*as_list_master.add_hook) ();
300
filter_type_str (enum as_filter_type type)
304
case AS_FILTER_PERMIT:
317
as_list_delete (struct as_list *aslist)
319
struct as_list_list *list;
320
struct as_filter *filter, *next;
322
for (filter = aslist->head; filter; filter = next)
325
as_filter_free (filter);
328
if (aslist->type == ACCESS_TYPE_NUMBER)
329
list = &as_list_master.num;
331
list = &as_list_master.str;
334
aslist->next->prev = aslist->prev;
336
list->tail = aslist->prev;
339
aslist->prev->next = aslist->next;
341
list->head = aslist->next;
343
as_list_free (aslist);
347
as_list_empty (struct as_list *aslist)
349
if (aslist->head == NULL && aslist->tail == NULL)
356
as_list_filter_delete (struct as_list *aslist, struct as_filter *asfilter)
359
asfilter->next->prev = asfilter->prev;
361
aslist->tail = asfilter->prev;
364
asfilter->prev->next = asfilter->next;
366
aslist->head = asfilter->next;
368
as_filter_free (asfilter);
370
/* If access_list becomes empty delete it from access_master. */
371
if (as_list_empty (aslist))
372
as_list_delete (aslist);
374
/* Run hook function. */
375
if (as_list_master.delete_hook)
376
(*as_list_master.delete_hook) ();
380
as_filter_match (struct as_filter *asfilter, struct aspath *aspath)
382
if (bgp_regexec (asfilter->reg, aspath) != REG_NOMATCH)
387
/* Apply AS path filter to AS. */
389
as_list_apply (struct as_list *aslist, void *object)
391
struct as_filter *asfilter;
392
struct aspath *aspath;
394
aspath = (struct aspath *) object;
397
return AS_FILTER_DENY;
399
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
401
if (as_filter_match (asfilter, aspath))
402
return asfilter->type;
404
return AS_FILTER_DENY;
407
/* Add hook function. */
409
as_list_add_hook (void (*func) ())
411
as_list_master.add_hook = func;
414
/* Delete hook function. */
416
as_list_delete_hook (void (*func) ())
418
as_list_master.delete_hook = func;
422
as_list_dup_check (struct as_list *aslist, struct as_filter *new)
424
struct as_filter *asfilter;
426
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
428
if (asfilter->type == new->type
429
&& strcmp (asfilter->reg_str, new->reg_str) == 0)
435
DEFUN (ip_as_path, ip_as_path_cmd,
436
"ip as-path access-list WORD (deny|permit) .LINE",
438
"BGP autonomous system path filter\n"
439
"Specify an access list name\n"
440
"Regular expression access list name\n"
441
"Specify packets to reject\n"
442
"Specify packets to forward\n"
443
"A regular-expression to match the BGP AS paths\n")
445
enum as_filter_type type;
446
struct as_filter *asfilter;
447
struct as_list *aslist;
451
/* Check the filter type. */
452
if (strncmp (argv[1], "p", 1) == 0)
453
type = AS_FILTER_PERMIT;
454
else if (strncmp (argv[1], "d", 1) == 0)
455
type = AS_FILTER_DENY;
458
vty_out (vty, "filter type must be [permit|deny]%s", VTY_NEWLINE);
462
/* Check AS path regex. */
463
regstr = argv_concat(argv, argc, 2);
465
regex = bgp_regcomp (regstr);
468
XFREE (MTYPE_TMP, regstr);
469
vty_out (vty, "can't compile regexp %s%s", argv[0],
474
asfilter = as_filter_make (regex, regstr, type);
476
XFREE (MTYPE_TMP, regstr);
478
/* Install new filter to the access_list. */
479
aslist = as_list_get (argv[0]);
481
/* Duplicate insertion check. */;
482
if (as_list_dup_check (aslist, asfilter))
483
as_filter_free (asfilter);
485
as_list_filter_add (aslist, asfilter);
490
DEFUN (no_ip_as_path,
492
"no ip as-path access-list WORD (deny|permit) .LINE",
495
"BGP autonomous system path filter\n"
496
"Specify an access list name\n"
497
"Regular expression access list name\n"
498
"Specify packets to reject\n"
499
"Specify packets to forward\n"
500
"A regular-expression to match the BGP AS paths\n")
502
enum as_filter_type type;
503
struct as_filter *asfilter;
504
struct as_list *aslist;
508
/* Lookup AS list from AS path list. */
509
aslist = as_list_lookup (argv[0]);
512
vty_out (vty, "ip as-path access-list %s doesn't exist%s", argv[0],
517
/* Check the filter type. */
518
if (strncmp (argv[1], "p", 1) == 0)
519
type = AS_FILTER_PERMIT;
520
else if (strncmp (argv[1], "d", 1) == 0)
521
type = AS_FILTER_DENY;
524
vty_out (vty, "filter type must be [permit|deny]%s", VTY_NEWLINE);
528
/* Compile AS path. */
529
regstr = argv_concat(argv, argc, 2);
531
regex = bgp_regcomp (regstr);
534
XFREE (MTYPE_TMP, regstr);
535
vty_out (vty, "can't compile regexp %s%s", argv[0],
540
/* Lookup asfilter. */
541
asfilter = as_filter_lookup (aslist, regstr, type);
543
XFREE (MTYPE_TMP, regstr);
544
bgp_regex_free (regex);
546
if (asfilter == NULL)
548
vty_out (vty, "%s", VTY_NEWLINE);
552
as_list_filter_delete (aslist, asfilter);
557
DEFUN (no_ip_as_path_all,
558
no_ip_as_path_all_cmd,
559
"no ip as-path access-list WORD",
562
"BGP autonomous system path filter\n"
563
"Specify an access list name\n"
564
"Regular expression access list name\n")
566
struct as_list *aslist;
568
aslist = as_list_lookup (argv[0]);
571
vty_out (vty, "ip as-path access-list %s doesn't exist%s", argv[0],
576
as_list_delete (aslist);
578
/* Run hook function. */
579
if (as_list_master.delete_hook)
580
(*as_list_master.delete_hook) ();
586
as_list_show (struct vty *vty, struct as_list *aslist)
588
struct as_filter *asfilter;
590
vty_out (vty, "AS path access list %s%s", aslist->name, VTY_NEWLINE);
592
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
594
vty_out (vty, " %s %s%s", filter_type_str (asfilter->type),
595
asfilter->reg_str, VTY_NEWLINE);
600
as_list_show_all (struct vty *vty)
602
struct as_list *aslist;
603
struct as_filter *asfilter;
605
for (aslist = as_list_master.num.head; aslist; aslist = aslist->next)
607
vty_out (vty, "AS path access list %s%s", aslist->name, VTY_NEWLINE);
609
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
611
vty_out (vty, " %s %s%s", filter_type_str (asfilter->type),
612
asfilter->reg_str, VTY_NEWLINE);
616
for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
618
vty_out (vty, "AS path access list %s%s", aslist->name, VTY_NEWLINE);
620
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
622
vty_out (vty, " %s %s%s", filter_type_str (asfilter->type),
623
asfilter->reg_str, VTY_NEWLINE);
628
DEFUN (show_ip_as_path_access_list,
629
show_ip_as_path_access_list_cmd,
630
"show ip as-path-access-list WORD",
633
"List AS path access lists\n"
634
"AS path access list name\n")
636
struct as_list *aslist;
638
aslist = as_list_lookup (argv[0]);
640
as_list_show (vty, aslist);
645
DEFUN (show_ip_as_path_access_list_all,
646
show_ip_as_path_access_list_all_cmd,
647
"show ip as-path-access-list",
650
"List AS path access lists\n")
652
as_list_show_all (vty);
657
config_write_as_list (struct vty *vty)
659
struct as_list *aslist;
660
struct as_filter *asfilter;
663
for (aslist = as_list_master.num.head; aslist; aslist = aslist->next)
664
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
666
vty_out (vty, "ip as-path access-list %s %s %s%s",
667
aslist->name, filter_type_str (asfilter->type),
673
for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
674
for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
676
vty_out (vty, "ip as-path access-list %s %s %s%s",
677
aslist->name, filter_type_str (asfilter->type),
685
struct cmd_node as_list_node =
692
/* Register functions. */
696
install_node (&as_list_node, config_write_as_list);
698
install_element (CONFIG_NODE, &ip_as_path_cmd);
699
install_element (CONFIG_NODE, &no_ip_as_path_cmd);
700
install_element (CONFIG_NODE, &no_ip_as_path_all_cmd);
702
install_element (VIEW_NODE, &show_ip_as_path_access_list_cmd);
703
install_element (VIEW_NODE, &show_ip_as_path_access_list_all_cmd);
704
install_element (ENABLE_NODE, &show_ip_as_path_access_list_cmd);
705
install_element (ENABLE_NODE, &show_ip_as_path_access_list_all_cmd);