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