usbmodeswitch: Updated to v.1.2.6 from shibby's branch.
[tomato.git] / release / src / router / zebra / bgpd / bgp_filter.c
blob7a8fb039cffbf670adaea922a9b4d095711aec8a
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
9 later version.
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
19 02111-1307, USA. */
21 #include <zebra.h>
23 #include "command.h"
24 #include "log.h"
25 #include "memory.h"
26 #include "buffer.h"
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. */
34 struct as_list_list
36 struct as_list *head;
37 struct as_list *tail;
40 /* AS path filter master. */
41 struct as_list_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. */
50 void (*add_hook) ();
52 /* Hook function which is executed when access_list is deleted. */
53 void (*delete_hook) ();
56 /* Element of AS path filter. */
57 struct as_filter
59 struct as_filter *next;
60 struct as_filter *prev;
62 enum as_filter_type type;
64 regex_t *reg;
65 char *reg_str;
68 enum as_list_type
70 ACCESS_TYPE_STRING,
71 ACCESS_TYPE_NUMBER
74 /* AS path filter list. */
75 struct as_list
77 char *name;
79 enum as_list_type type;
81 struct as_list *next;
82 struct as_list *prev;
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 =
92 {NULL, NULL},
93 {NULL, NULL},
94 NULL,
95 NULL
98 /* Allocate new AS filter. */
99 struct as_filter *
100 as_filter_new ()
102 struct as_filter *new;
104 new = XMALLOC (MTYPE_AS_FILTER, sizeof (struct as_filter));
105 memset (new, 0, sizeof (struct as_filter));
106 return new;
109 /* Free allocated AS filter. */
110 void
111 as_filter_free (struct as_filter *asfilter)
113 if (asfilter->reg)
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. */
121 struct as_filter *
122 as_filter_make (regex_t *reg, char *reg_str, enum as_filter_type type)
124 struct as_filter *asfilter;
126 asfilter = as_filter_new ();
127 asfilter->reg = reg;
128 asfilter->type = type;
129 asfilter->reg_str = XSTRDUP (MTYPE_AS_FILTER_STR, reg_str);
131 return asfilter;
134 struct as_filter *
135 as_filter_lookup (struct as_list *aslist, 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)
142 return asfilter;
143 return NULL;
146 void
147 as_list_filter_add (struct as_list *aslist, struct as_filter *asfilter)
149 asfilter->next = NULL;
150 asfilter->prev = aslist->tail;
152 if (aslist->tail)
153 aslist->tail->next = asfilter;
154 else
155 aslist->head = asfilter;
156 aslist->tail = asfilter;
159 /* Lookup as_list from list of as_list by name. */
160 struct as_list *
161 as_list_lookup (char *name)
163 struct as_list *aslist;
165 if (name == NULL)
166 return NULL;
168 for (aslist = as_list_master.num.head; aslist; aslist = aslist->next)
169 if (strcmp (aslist->name, name) == 0)
170 return aslist;
172 for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
173 if (strcmp (aslist->name, name) == 0)
174 return aslist;
176 return NULL;
179 struct as_list *
180 as_list_new ()
182 struct as_list *new;
184 new = XMALLOC (MTYPE_AS_LIST, sizeof (struct as_list));
185 memset (new, 0, sizeof (struct as_list));
186 return new;
189 void
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
196 the name. */
197 struct as_list *
198 as_list_insert (char *name)
200 int i;
201 long number;
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
211 number. */
212 for (number = 0, i = 0; i < strlen (name); i++)
214 if (isdigit ((int) name[i]))
215 number = (number * 10) + (name[i] - '0');
216 else
217 break;
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)
230 break;
232 else
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)
242 break;
245 /* In case of this is the first element of master. */
246 if (list->head == NULL)
248 list->head = list->tail = aslist;
249 return aslist;
252 /* In case of insertion is made at the tail of access_list. */
253 if (point == NULL)
255 aslist->prev = list->tail;
256 list->tail->next = aslist;
257 list->tail = aslist;
258 return 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;
266 list->head = aslist;
267 return aslist;
270 /* Insertion is made at middle of the access_list. */
271 aslist->next = point;
272 aslist->prev = point->prev;
274 if (point->prev)
275 point->prev->next = aslist;
276 point->prev = aslist;
278 return aslist;
281 struct as_list *
282 as_list_get (char *name)
284 struct as_list *aslist;
286 aslist = as_list_lookup (name);
287 if (aslist == NULL)
289 aslist = as_list_insert (name);
291 /* Run hook function. */
292 if (as_list_master.add_hook)
293 (*as_list_master.add_hook) ();
296 return aslist;
299 static char *
300 filter_type_str (enum as_filter_type type)
302 switch (type)
304 case AS_FILTER_PERMIT:
305 return "permit";
306 break;
307 case AS_FILTER_DENY:
308 return "deny";
309 break;
310 default:
311 return "";
312 break;
316 void
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)
324 next = filter->next;
325 as_filter_free (filter);
328 if (aslist->type == ACCESS_TYPE_NUMBER)
329 list = &as_list_master.num;
330 else
331 list = &as_list_master.str;
333 if (aslist->next)
334 aslist->next->prev = aslist->prev;
335 else
336 list->tail = aslist->prev;
338 if (aslist->prev)
339 aslist->prev->next = aslist->next;
340 else
341 list->head = aslist->next;
343 as_list_free (aslist);
346 static int
347 as_list_empty (struct as_list *aslist)
349 if (aslist->head == NULL && aslist->tail == NULL)
350 return 1;
351 else
352 return 0;
355 void
356 as_list_filter_delete (struct as_list *aslist, struct as_filter *asfilter)
358 if (asfilter->next)
359 asfilter->next->prev = asfilter->prev;
360 else
361 aslist->tail = asfilter->prev;
363 if (asfilter->prev)
364 asfilter->prev->next = asfilter->next;
365 else
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) ();
379 static int
380 as_filter_match (struct as_filter *asfilter, struct aspath *aspath)
382 if (bgp_regexec (asfilter->reg, aspath) != REG_NOMATCH)
383 return 1;
384 return 0;
387 /* Apply AS path filter to AS. */
388 enum as_filter_type
389 as_list_apply (struct as_list *aslist, void *object)
391 struct as_filter *asfilter;
392 struct aspath *aspath;
394 aspath = (struct aspath *) object;
396 if (aslist == NULL)
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. */
408 void
409 as_list_add_hook (void (*func) ())
411 as_list_master.add_hook = func;
414 /* Delete hook function. */
415 void
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)
430 return 1;
432 return 0;
435 DEFUN (ip_as_path, ip_as_path_cmd,
436 "ip as-path access-list WORD (deny|permit) .LINE",
437 IP_STR
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;
448 regex_t *regex;
449 struct buffer *b;
450 int i;
451 char *regstr;
452 int first = 0;
454 /* Check the filter type. */
455 if (strncmp (argv[1], "p", 1) == 0)
456 type = AS_FILTER_PERMIT;
457 else if (strncmp (argv[1], "d", 1) == 0)
458 type = AS_FILTER_DENY;
459 else
461 vty_out (vty, "filter type must be [permit|deny]%s", VTY_NEWLINE);
462 return CMD_WARNING;
465 /* Check AS path regex. */
466 b = buffer_new (1024);
467 for (i = 2; i < argc; i++)
469 if (first)
470 buffer_putc (b, ' ');
471 else
472 first = 1;
474 buffer_putstr (b, argv[i]);
476 buffer_putc (b, '\0');
478 regstr = buffer_getstr (b);
479 buffer_free (b);
481 regex = bgp_regcomp (regstr);
482 if (!regex)
484 free (regstr);
485 vty_out (vty, "can't compile regexp %s%s", argv[0],
486 VTY_NEWLINE);
487 return CMD_WARNING;
490 asfilter = as_filter_make (regex, regstr, type);
492 free (regstr);
494 /* Install new filter to the access_list. */
495 aslist = as_list_get (argv[0]);
497 /* Duplicate insertion check. */;
498 if (as_list_dup_check (aslist, asfilter))
499 as_filter_free (asfilter);
500 else
501 as_list_filter_add (aslist, asfilter);
503 return CMD_SUCCESS;
506 DEFUN (no_ip_as_path,
507 no_ip_as_path_cmd,
508 "no ip as-path access-list WORD (deny|permit) .LINE",
509 NO_STR
510 IP_STR
511 "BGP autonomous system path filter\n"
512 "Specify an access list name\n"
513 "Regular expression access list name\n"
514 "Specify packets to reject\n"
515 "Specify packets to forward\n"
516 "A regular-expression to match the BGP AS paths\n")
518 enum as_filter_type type;
519 struct as_filter *asfilter;
520 struct as_list *aslist;
521 struct buffer *b;
522 int i;
523 int first = 0;
524 char *regstr;
525 regex_t *regex;
527 /* Lookup AS list from AS path list. */
528 aslist = as_list_lookup (argv[0]);
529 if (aslist == NULL)
531 vty_out (vty, "ip as-path access-list %s doesn't exist%s", argv[0],
532 VTY_NEWLINE);
533 return CMD_WARNING;
536 /* Check the filter type. */
537 if (strncmp (argv[1], "p", 1) == 0)
538 type = AS_FILTER_PERMIT;
539 else if (strncmp (argv[1], "d", 1) == 0)
540 type = AS_FILTER_DENY;
541 else
543 vty_out (vty, "filter type must be [permit|deny]%s", VTY_NEWLINE);
544 return CMD_WARNING;
547 /* Compile AS path. */
548 b = buffer_new (1024);
549 for (i = 2; i < argc; i++)
551 if (first)
552 buffer_putc (b, ' ');
553 else
554 first = 1;
556 buffer_putstr (b, argv[i]);
558 buffer_putc (b, '\0');
560 regstr = buffer_getstr (b);
561 buffer_free (b);
563 regex = bgp_regcomp (regstr);
564 if (!regex)
566 free (regstr);
567 vty_out (vty, "can't compile regexp %s%s", argv[0],
568 VTY_NEWLINE);
569 return CMD_WARNING;
572 /* Lookup asfilter. */
573 asfilter = as_filter_lookup (aslist, regstr, type);
575 free (regstr);
576 bgp_regex_free (regex);
578 if (asfilter == NULL)
580 vty_out (vty, "%s", VTY_NEWLINE);
581 return CMD_WARNING;
584 as_list_filter_delete (aslist, asfilter);
586 return CMD_SUCCESS;
589 DEFUN (no_ip_as_path_all,
590 no_ip_as_path_all_cmd,
591 "no ip as-path access-list WORD",
592 NO_STR
593 IP_STR
594 "BGP autonomous system path filter\n"
595 "Specify an access list name\n"
596 "Regular expression access list name\n")
598 struct as_list *aslist;
600 aslist = as_list_lookup (argv[0]);
601 if (aslist == NULL)
603 vty_out (vty, "ip as-path access-list %s doesn't exist%s", argv[0],
604 VTY_NEWLINE);
605 return CMD_WARNING;
608 as_list_delete (aslist);
610 /* Run hook function. */
611 if (as_list_master.delete_hook)
612 (*as_list_master.delete_hook) ();
614 return CMD_SUCCESS;
617 void
618 as_list_show (struct vty *vty, struct as_list *aslist)
620 struct as_filter *asfilter;
622 vty_out (vty, "AS path access list %s%s", aslist->name, VTY_NEWLINE);
624 for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
626 vty_out (vty, " %s %s%s", filter_type_str (asfilter->type),
627 asfilter->reg_str, VTY_NEWLINE);
631 void
632 as_list_show_all (struct vty *vty)
634 struct as_list *aslist;
635 struct as_filter *asfilter;
637 for (aslist = as_list_master.num.head; aslist; aslist = aslist->next)
639 vty_out (vty, "AS path access list %s%s", aslist->name, VTY_NEWLINE);
641 for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
643 vty_out (vty, " %s %s%s", filter_type_str (asfilter->type),
644 asfilter->reg_str, VTY_NEWLINE);
648 for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
650 vty_out (vty, "AS path access list %s%s", aslist->name, VTY_NEWLINE);
652 for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
654 vty_out (vty, " %s %s%s", filter_type_str (asfilter->type),
655 asfilter->reg_str, VTY_NEWLINE);
660 DEFUN (show_ip_as_path_access_list,
661 show_ip_as_path_access_list_cmd,
662 "show ip as-path-access-list WORD",
663 SHOW_STR
664 IP_STR
665 "List AS path access lists\n"
666 "AS path access list name\n")
668 struct as_list *aslist;
670 aslist = as_list_lookup (argv[0]);
671 if (aslist)
672 as_list_show (vty, aslist);
674 return CMD_SUCCESS;
677 DEFUN (show_ip_as_path_access_list_all,
678 show_ip_as_path_access_list_all_cmd,
679 "show ip as-path-access-list",
680 SHOW_STR
681 IP_STR
682 "List AS path access lists\n")
684 as_list_show_all (vty);
685 return CMD_SUCCESS;
689 config_write_as_list (struct vty *vty)
691 struct as_list *aslist;
692 struct as_filter *asfilter;
693 int write = 0;
695 for (aslist = as_list_master.num.head; aslist; aslist = aslist->next)
696 for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
698 vty_out (vty, "ip as-path access-list %s %s %s%s",
699 aslist->name, filter_type_str (asfilter->type),
700 asfilter->reg_str,
701 VTY_NEWLINE);
702 write++;
705 for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
706 for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
708 vty_out (vty, "ip as-path access-list %s %s %s%s",
709 aslist->name, filter_type_str (asfilter->type),
710 asfilter->reg_str,
711 VTY_NEWLINE);
712 write++;
714 return write;
717 struct cmd_node as_list_node =
719 AS_LIST_NODE,
724 /* Register functions. */
725 void
726 bgp_filter_init ()
728 install_node (&as_list_node, config_write_as_list);
730 install_element (CONFIG_NODE, &ip_as_path_cmd);
731 install_element (CONFIG_NODE, &no_ip_as_path_cmd);
732 install_element (CONFIG_NODE, &no_ip_as_path_all_cmd);
734 install_element (VIEW_NODE, &show_ip_as_path_access_list_cmd);
735 install_element (VIEW_NODE, &show_ip_as_path_access_list_all_cmd);
736 install_element (ENABLE_NODE, &show_ip_as_path_access_list_cmd);
737 install_element (ENABLE_NODE, &show_ip_as_path_access_list_all_cmd);