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

网络

开发平台:

Unix_Linux

  1. /* RIP offset-list
  2.  * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
  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
  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.  
  20.  */
  21. #include <zebra.h>
  22. #include "if.h"
  23. #include "prefix.h"
  24. #include "filter.h"
  25. #include "command.h"
  26. #include "linklist.h"
  27. #include "memory.h"
  28. #define RIP_OFFSET_LIST_IN  0
  29. #define RIP_OFFSET_LIST_OUT 1
  30. #define RIP_OFFSET_LIST_MAX 2
  31. struct rip_offset_list
  32. {
  33.   char *ifname;
  34.   struct 
  35.   {
  36.     char *alist_name;
  37.     /* struct access_list *alist; */
  38.     int metric;
  39.   } direct[RIP_OFFSET_LIST_MAX];
  40. };
  41. static struct list *rip_offset_list_master;
  42. int
  43. strcmp_safe (char *s1, char *s2)
  44. {
  45.   if (s1 == NULL && s2 == NULL)
  46.     return 0;
  47.   if (s1 == NULL)
  48.     return -1;
  49.   if (s2 == NULL)
  50.     return 1;
  51.   return strcmp (s1, s2);
  52. }
  53. struct rip_offset_list *
  54. rip_offset_list_new ()
  55. {
  56.   struct rip_offset_list *new;
  57.   new = XMALLOC (MTYPE_RIP_OFFSET_LIST, sizeof (struct rip_offset_list));
  58.   memset (new, 0, sizeof (struct rip_offset_list));
  59.   return new;
  60. }
  61. void
  62. rip_offset_list_free (struct rip_offset_list *offset)
  63. {
  64.   XFREE (MTYPE_RIP_OFFSET_LIST, offset);
  65. }
  66. struct rip_offset_list *
  67. rip_offset_list_lookup (char *ifname)
  68. {
  69.   struct rip_offset_list *offset;
  70.   struct listnode *nn;
  71.   LIST_LOOP (rip_offset_list_master, offset, nn)
  72.     {
  73.       if (strcmp_safe (offset->ifname, ifname) == 0)
  74. return offset;
  75.     }
  76.   return NULL;
  77. }
  78. struct rip_offset_list *
  79. rip_offset_list_get (char *ifname)
  80. {
  81.   struct rip_offset_list *offset;
  82.   
  83.   offset = rip_offset_list_lookup (ifname);
  84.   if (offset)
  85.     return offset;
  86.   offset = rip_offset_list_new ();
  87.   if (ifname)
  88.     offset->ifname = strdup (ifname);
  89.   listnode_add_sort (rip_offset_list_master, offset);
  90.   return offset;
  91. }
  92. int
  93. rip_offset_list_set (struct vty *vty, char *alist, char *direct_str,
  94.      char *metric_str, char *ifname)
  95. {
  96.   int direct;
  97.   int metric;
  98.   struct rip_offset_list *offset;
  99.   /* Check direction. */
  100.   if (strncmp (direct_str, "i", 1) == 0)
  101.     direct = RIP_OFFSET_LIST_IN;
  102.   else if (strncmp (direct_str, "o", 1) == 0)
  103.     direct = RIP_OFFSET_LIST_OUT;
  104.   else
  105.     {
  106.       vty_out (vty, "Invalid direction: %s%s", direct_str, VTY_NEWLINE);
  107.       return CMD_WARNING;
  108.     }
  109.   /* Check metric. */
  110.   metric = atoi (metric_str);
  111.   if (metric < 0 || metric > 16)
  112.     {
  113.       vty_out (vty, "Invalid metric: %s%s", metric_str, VTY_NEWLINE);
  114.       return CMD_WARNING;
  115.     }
  116.   /* Get offset-list structure with interface name. */
  117.   offset = rip_offset_list_get (ifname);
  118.   if (offset->direct[direct].alist_name)
  119.     free (offset->direct[direct].alist_name);
  120.   offset->direct[direct].alist_name = strdup (alist);
  121.   offset->direct[direct].metric = metric;
  122.   return CMD_SUCCESS;
  123. }
  124. int
  125. rip_offset_list_unset (struct vty *vty, char *alist, char *direct_str,
  126.        char *metric_str, char *ifname)
  127. {
  128.   int direct;
  129.   int metric;
  130.   struct rip_offset_list *offset;
  131.   /* Check direction. */
  132.   if (strncmp (direct_str, "i", 1) == 0)
  133.     direct = RIP_OFFSET_LIST_IN;
  134.   else if (strncmp (direct_str, "o", 1) == 0)
  135.     direct = RIP_OFFSET_LIST_OUT;
  136.   else
  137.     {
  138.       vty_out (vty, "Invalid direction: %s%s", direct_str, VTY_NEWLINE);
  139.       return CMD_WARNING;
  140.     }
  141.   /* Check metric. */
  142.   metric = atoi (metric_str);
  143.   if (metric < 0 || metric > 16)
  144.     {
  145.       vty_out (vty, "Invalid metric: %s%s", metric_str, VTY_NEWLINE);
  146.       return CMD_WARNING;
  147.     }
  148.   /* Get offset-list structure with interface name. */
  149.   offset = rip_offset_list_lookup (ifname);
  150.   if (offset)
  151.     {
  152.       if (offset->direct[direct].alist_name)
  153. free (offset->direct[direct].alist_name);
  154.       offset->direct[direct].alist_name = NULL;
  155.       if (offset->direct[RIP_OFFSET_LIST_IN].alist_name == NULL &&
  156.   offset->direct[RIP_OFFSET_LIST_OUT].alist_name == NULL)
  157. {
  158.   listnode_delete (rip_offset_list_master, offset);
  159.   if (offset->ifname)
  160.     free (offset->ifname);
  161.   rip_offset_list_free (offset);
  162. }
  163.     }
  164.   else
  165.     {
  166.       vty_out (vty, "Can't find offset-list%s", VTY_NEWLINE);
  167.       return CMD_WARNING;
  168.     }
  169.   return CMD_SUCCESS;
  170. }
  171. #define OFFSET_LIST_IN_NAME(O)  ((O)->direct[RIP_OFFSET_LIST_IN].alist_name)
  172. #define OFFSET_LIST_IN_METRIC(O)  ((O)->direct[RIP_OFFSET_LIST_IN].metric)
  173. #define OFFSET_LIST_OUT_NAME(O)  ((O)->direct[RIP_OFFSET_LIST_OUT].alist_name)
  174. #define OFFSET_LIST_OUT_METRIC(O)  ((O)->direct[RIP_OFFSET_LIST_OUT].metric)
  175. /* If metric is modifed return 1. */
  176. int
  177. rip_offset_list_apply_in (struct prefix_ipv4 *p, struct interface *ifp,
  178.   u_int32_t *metric)
  179. {
  180.   struct rip_offset_list *offset;
  181.   struct access_list *alist;
  182.   /* Look up offset-list with interface name. */
  183.   offset = rip_offset_list_lookup (ifp->name);
  184.   if (offset && OFFSET_LIST_IN_NAME (offset))
  185.     {
  186.       alist = access_list_lookup (AFI_IP, OFFSET_LIST_IN_NAME (offset));
  187.       if (alist 
  188.   && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
  189. {
  190.   *metric += OFFSET_LIST_IN_METRIC (offset);
  191.   return 1;
  192. }
  193.       return 0;
  194.     }
  195.   /* Look up offset-list without interface name. */
  196.   offset = rip_offset_list_lookup (NULL);
  197.   if (offset && OFFSET_LIST_IN_NAME (offset))
  198.     {
  199.       alist = access_list_lookup (AFI_IP, OFFSET_LIST_IN_NAME (offset));
  200.       if (alist 
  201.   && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
  202. {
  203.   *metric += OFFSET_LIST_IN_METRIC (offset);
  204.   return 1;
  205. }
  206.       return 0;
  207.     }
  208.   return 0;
  209. }
  210. /* If metric is modifed return 1. */
  211. int
  212. rip_offset_list_apply_out (struct prefix_ipv4 *p, struct interface *ifp,
  213.   u_int32_t *metric)
  214. {
  215.   struct rip_offset_list *offset;
  216.   struct access_list *alist;
  217.   /* Look up offset-list with interface name. */
  218.   offset = rip_offset_list_lookup (ifp->name);
  219.   if (offset && OFFSET_LIST_OUT_NAME (offset))
  220.     {
  221.       alist = access_list_lookup (AFI_IP, OFFSET_LIST_OUT_NAME (offset));
  222.       if (alist 
  223.   && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
  224. {
  225.   *metric += OFFSET_LIST_OUT_METRIC (offset);
  226.   return 1;
  227. }
  228.       return 0;
  229.     }
  230.   /* Look up offset-list without interface name. */
  231.   offset = rip_offset_list_lookup (NULL);
  232.   if (offset && OFFSET_LIST_OUT_NAME (offset))
  233.     {
  234.       alist = access_list_lookup (AFI_IP, OFFSET_LIST_OUT_NAME (offset));
  235.       if (alist 
  236.   && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
  237. {
  238.   *metric += OFFSET_LIST_OUT_METRIC (offset);
  239.   return 1;
  240. }
  241.       return 0;
  242.     }
  243.   return 0;
  244. }
  245. DEFUN (rip_offset_list,
  246.        rip_offset_list_cmd,
  247.        "offset-list WORD (in|out) <0-16>",
  248.        "Modify RIP metricn"
  249.        "Access-list namen"
  250.        "For incoming updatesn"
  251.        "For outgoing updatesn"
  252.        "Metric valuen")
  253. {
  254.   return rip_offset_list_set (vty, argv[0], argv[1], argv[2], NULL);
  255. }
  256. DEFUN (rip_offset_list_ifname,
  257.        rip_offset_list_ifname_cmd,
  258.        "offset-list WORD (in|out) <0-16> IFNAME",
  259.        "Modify RIP metricn"
  260.        "Access-list namen"
  261.        "For incoming updatesn"
  262.        "For outgoing updatesn"
  263.        "Metric valuen"
  264.        "Interface to matchn")
  265. {
  266.   return rip_offset_list_set (vty, argv[0], argv[1], argv[2], argv[3]);
  267. }
  268. DEFUN (no_rip_offset_list,
  269.        no_rip_offset_list_cmd,
  270.        "no offset-list WORD (in|out) <0-16>",
  271.        NO_STR
  272.        "Modify RIP metricn"
  273.        "Access-list namen"
  274.        "For incoming updatesn"
  275.        "For outgoing updatesn"
  276.        "Metric valuen")
  277. {
  278.   return rip_offset_list_unset (vty, argv[0], argv[1], argv[2], NULL);
  279. }
  280. DEFUN (no_rip_offset_list_ifname,
  281.        no_rip_offset_list_ifname_cmd,
  282.        "no offset-list WORD (in|out) <0-16> IFNAME",
  283.        NO_STR
  284.        "Modify RIP metricn"
  285.        "Access-list namen"
  286.        "For incoming updatesn"
  287.        "For outgoing updatesn"
  288.        "Metric valuen"
  289.        "Interface to matchn")
  290. {
  291.   return rip_offset_list_unset (vty, argv[0], argv[1], argv[2], argv[3]);
  292. }
  293. int
  294. offset_list_cmp (struct rip_offset_list *o1, struct rip_offset_list *o2)
  295. {
  296.   return strcmp_safe (o1->ifname, o2->ifname);
  297. }
  298. void
  299. offset_list_del (struct rip_offset_list *offset)
  300. {
  301.   if (OFFSET_LIST_IN_NAME (offset))
  302.     free (OFFSET_LIST_IN_NAME (offset));
  303.   if (OFFSET_LIST_OUT_NAME (offset))
  304.     free (OFFSET_LIST_OUT_NAME (offset));
  305.   if (offset->ifname)
  306.     free (offset->ifname);
  307.   rip_offset_list_free (offset);
  308. }
  309. void
  310. rip_offset_init ()
  311. {
  312.   rip_offset_list_master = list_new ();
  313.   rip_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp;
  314.   rip_offset_list_master->del = (void (*)(void *)) offset_list_del;
  315.   install_element (RIP_NODE, &rip_offset_list_cmd);
  316.   install_element (RIP_NODE, &rip_offset_list_ifname_cmd);
  317.   install_element (RIP_NODE, &no_rip_offset_list_cmd);
  318.   install_element (RIP_NODE, &no_rip_offset_list_ifname_cmd);
  319. }
  320. void
  321. rip_offset_clean ()
  322. {
  323.   list_delete (rip_offset_list_master);
  324.   rip_offset_list_master = list_new ();
  325.   rip_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp;
  326.   rip_offset_list_master->del = (void (*)(void *)) offset_list_del;
  327. }
  328. int
  329. config_write_rip_offset_list (struct vty *vty)
  330. {
  331.   struct listnode *nn;
  332.   struct rip_offset_list *offset;
  333.   LIST_LOOP (rip_offset_list_master, offset, nn)
  334.     {
  335.       if (! offset->ifname)
  336. {
  337.   if (offset->direct[RIP_OFFSET_LIST_IN].alist_name)
  338.     vty_out (vty, " offset-list %s in %d%s",
  339.      offset->direct[RIP_OFFSET_LIST_IN].alist_name,
  340.      offset->direct[RIP_OFFSET_LIST_IN].metric,
  341.      VTY_NEWLINE);
  342.   if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name)
  343.     vty_out (vty, " offset-list %s out %d%s",
  344.      offset->direct[RIP_OFFSET_LIST_OUT].alist_name,
  345.      offset->direct[RIP_OFFSET_LIST_OUT].metric,
  346.      VTY_NEWLINE);
  347. }
  348.       else
  349. {
  350.   if (offset->direct[RIP_OFFSET_LIST_IN].alist_name)
  351.     vty_out (vty, " offset-list %s in %d %s%s",
  352.      offset->direct[RIP_OFFSET_LIST_IN].alist_name,
  353.      offset->direct[RIP_OFFSET_LIST_IN].metric,
  354.      offset->ifname, VTY_NEWLINE);
  355.   if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name)
  356.     vty_out (vty, " offset-list %s out %d %s%s",
  357.      offset->direct[RIP_OFFSET_LIST_OUT].alist_name,
  358.      offset->direct[RIP_OFFSET_LIST_OUT].metric,
  359.      offset->ifname, VTY_NEWLINE);
  360. }
  361.     }
  362.   return 0;
  363. }