bgp_filter.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:16k
源码类别:

网络

开发平台:

Unix_Linux

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