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

网络

开发平台:

Unix_Linux

  1. /* Distribute list functions
  2.  * Copyright (C) 1998, 1999 Kunihiro Ishiguro
  3.  *
  4.  * This file is part of GNU Zebra.
  5.  *
  6.  * GNU Zebra is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published
  8.  * by the Free Software Foundation; either version 2, or (at your
  9.  * option) any 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
  18.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19.  * Boston, MA 02111-1307, USA.
  20.  */
  21. #include <zebra.h>
  22. #include "hash.h"
  23. #include "if.h"
  24. #include "filter.h"
  25. #include "command.h"
  26. #include "distribute.h"
  27. #include "memory.h"
  28. /* Hash of distribute list. */
  29. struct hash *disthash;
  30. /* Hook functions. */
  31. void (*distribute_add_hook) (struct distribute *);
  32. void (*distribute_delete_hook) (struct distribute *);
  33. struct distribute *
  34. distribute_new ()
  35. {
  36.   struct distribute *new;
  37.   new = XMALLOC (MTYPE_DISTRIBUTE, sizeof (struct distribute));
  38.   memset (new, 0, sizeof (struct distribute));
  39.   return new;
  40. }
  41. /* Free distribute object. */
  42. void
  43. distribute_free (struct distribute *dist)
  44. {
  45.   if (dist->ifname)
  46.     free (dist->ifname);
  47.   if (dist->list[DISTRIBUTE_IN])
  48.     free (dist->list[DISTRIBUTE_IN]);
  49.   if (dist->list[DISTRIBUTE_OUT])
  50.     free (dist->list[DISTRIBUTE_OUT]);
  51.   if (dist->prefix[DISTRIBUTE_IN])
  52.     free (dist->prefix[DISTRIBUTE_IN]);
  53.   if (dist->prefix[DISTRIBUTE_OUT])
  54.     free (dist->prefix[DISTRIBUTE_OUT]);
  55.   XFREE (MTYPE_DISTRIBUTE, dist);
  56. }
  57. /* Lookup interface's distribute list. */
  58. struct distribute *
  59. distribute_lookup (char *ifname)
  60. {
  61.   struct distribute key;
  62.   struct distribute *dist;
  63.   key.ifname = ifname;
  64.   dist = hash_lookup (disthash, &key);
  65.   
  66.   return dist;
  67. }
  68. void
  69. distribute_list_add_hook (void (*func) (struct distribute *))
  70. {
  71.   distribute_add_hook = func;
  72. }
  73. void
  74. distribute_list_delete_hook (void (*func) (struct distribute *))
  75. {
  76.   distribute_delete_hook = func;
  77. }
  78. void *
  79. distribute_hash_alloc (struct distribute *arg)
  80. {
  81.   struct distribute *dist;
  82.   dist = distribute_new ();
  83.   if (arg->ifname)
  84.     dist->ifname = strdup (arg->ifname);
  85.   else
  86.     dist->ifname = NULL;
  87.   return dist;
  88. }
  89. /* Make new distribute list and push into hash. */
  90. struct distribute *
  91. distribute_get (char *ifname)
  92. {
  93.   struct distribute key;
  94.   key.ifname = ifname;
  95.   return hash_get (disthash, &key, distribute_hash_alloc);
  96. }
  97. unsigned int
  98. distribute_hash_make (struct distribute *dist)
  99. {
  100.   unsigned int key;
  101.   int i;
  102.   key = 0;
  103.   if (dist->ifname)
  104.     for (i = 0; i < strlen (dist->ifname); i++)
  105.       key += dist->ifname[i];
  106.   return key;
  107. }
  108. /* If two distribute-list have same value then return 1 else return
  109.    0. This function is used by hash package. */
  110. int
  111. distribute_cmp (struct distribute *dist1, struct distribute *dist2)
  112. {
  113.   if (dist1->ifname && dist2->ifname)
  114.     if (strcmp (dist1->ifname, dist2->ifname) == 0)
  115.       return 1;
  116.   if (! dist1->ifname && ! dist2->ifname)
  117.     return 1;
  118.   return 0;
  119. }
  120. /* Set access-list name to the distribute list. */
  121. struct distribute *
  122. distribute_list_set (char *ifname, enum distribute_type type, char *alist_name)
  123. {
  124.   struct distribute *dist;
  125.   dist = distribute_get (ifname);
  126.   if (type == DISTRIBUTE_IN)
  127.     {
  128.       if (dist->list[DISTRIBUTE_IN])
  129. free (dist->list[DISTRIBUTE_IN]);
  130.       dist->list[DISTRIBUTE_IN] = strdup (alist_name);
  131.     }
  132.   if (type == DISTRIBUTE_OUT)
  133.     {
  134.       if (dist->list[DISTRIBUTE_OUT])
  135. free (dist->list[DISTRIBUTE_OUT]);
  136.       dist->list[DISTRIBUTE_OUT] = strdup (alist_name);
  137.     }
  138.   /* Apply this distribute-list to the interface. */
  139.   (*distribute_add_hook) (dist);
  140.   
  141.   return dist;
  142. }
  143. /* Unset distribute-list.  If matched distribute-list exist then
  144.    return 1. */
  145. int
  146. distribute_list_unset (char *ifname, enum distribute_type type, 
  147.        char *alist_name)
  148. {
  149.   struct distribute *dist;
  150.   dist = distribute_lookup (ifname);
  151.   if (!dist)
  152.     return 0;
  153.   if (type == DISTRIBUTE_IN)
  154.     {
  155.       if (!dist->list[DISTRIBUTE_IN])
  156. return 0;
  157.       if (strcmp (dist->list[DISTRIBUTE_IN], alist_name) != 0)
  158. return 0;
  159.       free (dist->list[DISTRIBUTE_IN]);
  160.       dist->list[DISTRIBUTE_IN] = NULL;      
  161.     }
  162.   if (type == DISTRIBUTE_OUT)
  163.     {
  164.       if (!dist->list[DISTRIBUTE_OUT])
  165. return 0;
  166.       if (strcmp (dist->list[DISTRIBUTE_OUT], alist_name) != 0)
  167. return 0;
  168.       free (dist->list[DISTRIBUTE_OUT]);
  169.       dist->list[DISTRIBUTE_OUT] = NULL;      
  170.     }
  171.   /* Apply this distribute-list to the interface. */
  172.   (*distribute_delete_hook) (dist);
  173.   /* If both out and in is NULL then free distribute list. */
  174.   if (dist->list[DISTRIBUTE_IN] == NULL &&
  175.       dist->list[DISTRIBUTE_OUT] == NULL &&
  176.       dist->prefix[DISTRIBUTE_IN] == NULL &&
  177.       dist->prefix[DISTRIBUTE_OUT] == NULL)
  178.     {
  179.       hash_release (disthash, dist);
  180.       distribute_free (dist);
  181.     }
  182.   return 1;
  183. }
  184. /* Set access-list name to the distribute list. */
  185. struct distribute *
  186. distribute_list_prefix_set (char *ifname, enum distribute_type type,
  187.     char *plist_name)
  188. {
  189.   struct distribute *dist;
  190.   dist = distribute_get (ifname);
  191.   if (type == DISTRIBUTE_IN)
  192.     {
  193.       if (dist->prefix[DISTRIBUTE_IN])
  194. free (dist->prefix[DISTRIBUTE_IN]);
  195.       dist->prefix[DISTRIBUTE_IN] = strdup (plist_name);
  196.     }
  197.   if (type == DISTRIBUTE_OUT)
  198.     {
  199.       if (dist->prefix[DISTRIBUTE_OUT])
  200. free (dist->prefix[DISTRIBUTE_OUT]);
  201.       dist->prefix[DISTRIBUTE_OUT] = strdup (plist_name);
  202.     }
  203.   /* Apply this distribute-list to the interface. */
  204.   (*distribute_add_hook) (dist);
  205.   
  206.   return dist;
  207. }
  208. /* Unset distribute-list.  If matched distribute-list exist then
  209.    return 1. */
  210. int
  211. distribute_list_prefix_unset (char *ifname, enum distribute_type type,
  212.       char *plist_name)
  213. {
  214.   struct distribute *dist;
  215.   dist = distribute_lookup (ifname);
  216.   if (!dist)
  217.     return 0;
  218.   if (type == DISTRIBUTE_IN)
  219.     {
  220.       if (!dist->prefix[DISTRIBUTE_IN])
  221. return 0;
  222.       if (strcmp (dist->prefix[DISTRIBUTE_IN], plist_name) != 0)
  223. return 0;
  224.       free (dist->prefix[DISTRIBUTE_IN]);
  225.       dist->prefix[DISTRIBUTE_IN] = NULL;      
  226.     }
  227.   if (type == DISTRIBUTE_OUT)
  228.     {
  229.       if (!dist->prefix[DISTRIBUTE_OUT])
  230. return 0;
  231.       if (strcmp (dist->prefix[DISTRIBUTE_OUT], plist_name) != 0)
  232. return 0;
  233.       free (dist->prefix[DISTRIBUTE_OUT]);
  234.       dist->prefix[DISTRIBUTE_OUT] = NULL;      
  235.     }
  236.   /* Apply this distribute-list to the interface. */
  237.   (*distribute_delete_hook) (dist);
  238.   /* If both out and in is NULL then free distribute list. */
  239.   if (dist->list[DISTRIBUTE_IN] == NULL &&
  240.       dist->list[DISTRIBUTE_OUT] == NULL &&
  241.       dist->prefix[DISTRIBUTE_IN] == NULL &&
  242.       dist->prefix[DISTRIBUTE_OUT] == NULL)
  243.     {
  244.       hash_release (disthash, dist);
  245.       distribute_free (dist);
  246.     }
  247.   return 1;
  248. }
  249. DEFUN (distribute_list_all,
  250.        distribute_list_all_cmd,
  251.        "distribute-list WORD (in|out)",
  252.        "Filter networks in routing updatesn"
  253.        "Access-list namen"
  254.        "Filter incoming routing updatesn"
  255.        "Filter outgoing routing updatesn")
  256. {
  257.   enum distribute_type type;
  258.   struct distribute *dist;
  259.   /* Check of distribute list type. */
  260.   if (strncmp (argv[1], "i", 1) == 0)
  261.     type = DISTRIBUTE_IN;
  262.   else if (strncmp (argv[1], "o", 1) == 0)
  263.     type = DISTRIBUTE_OUT;
  264.   else
  265.     {
  266.       vty_out (vty, "distribute list direction must be [in|out]%s",
  267.        VTY_NEWLINE);
  268.       return CMD_WARNING;
  269.     }
  270.   /* Get interface name corresponding distribute list. */
  271.   dist = distribute_list_set (NULL, type, argv[0]);
  272.   return CMD_SUCCESS;
  273. }
  274. ALIAS (distribute_list_all,
  275.        ipv6_distribute_list_all_cmd,
  276.        "distribute-list WORD (in|out)",
  277.        "Filter networks in routing updatesn"
  278.        "Access-list namen"
  279.        "Filter incoming routing updatesn"
  280.        "Filter outgoing routing updatesn");
  281. DEFUN (no_distribute_list_all,
  282.        no_distribute_list_all_cmd,
  283.        "no distribute-list WORD (in|out)",
  284.        NO_STR
  285.        "Filter networks in routing updatesn"
  286.        "Access-list namen"
  287.        "Filter incoming routing updatesn"
  288.        "Filter outgoing routing updatesn")
  289. {
  290.   int ret;
  291.   enum distribute_type type;
  292.   /* Check of distribute list type. */
  293.   if (strncmp (argv[1], "i", 1) == 0)
  294.     type = DISTRIBUTE_IN;
  295.   else if (strncmp (argv[1], "o", 1) == 0)
  296.     type = DISTRIBUTE_OUT;
  297.   else
  298.     {
  299.       vty_out (vty, "distribute list direction must be [in|out]%s",
  300.        VTY_NEWLINE);
  301.       return CMD_WARNING;
  302.     }
  303.   ret = distribute_list_unset (NULL, type, argv[0]);
  304.   if (! ret)
  305.     {
  306.       vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
  307.       return CMD_WARNING;
  308.     }
  309.   return CMD_SUCCESS;
  310. }
  311. ALIAS (no_distribute_list_all,
  312.        no_ipv6_distribute_list_all_cmd,
  313.        "no distribute-list WORD (in|out)",
  314.        NO_STR
  315.        "Filter networks in routing updatesn"
  316.        "Access-list namen"
  317.        "Filter incoming routing updatesn"
  318.        "Filter outgoing routing updatesn");
  319. DEFUN (distribute_list,
  320.        distribute_list_cmd,
  321.        "distribute-list WORD (in|out) WORD",
  322.        "Filter networks in routing updatesn"
  323.        "Access-list namen"
  324.        "Filter incoming routing updatesn"
  325.        "Filter outgoing routing updatesn"
  326.        "Interface namen")
  327. {
  328.   enum distribute_type type;
  329.   struct distribute *dist;
  330.   /* Check of distribute list type. */
  331.   if (strncmp (argv[1], "i", 1) == 0)
  332.     type = DISTRIBUTE_IN;
  333.   else if (strncmp (argv[1], "o", 1) == 0)
  334.     type = DISTRIBUTE_OUT;
  335.   else
  336.     {
  337.       vty_out (vty, "distribute list direction must be [in|out]%s", VTY_NEWLINE);
  338.       return CMD_WARNING;
  339.     }
  340.   /* Get interface name corresponding distribute list. */
  341.   dist = distribute_list_set (argv[2], type, argv[0]);
  342.   return CMD_SUCCESS;
  343. }       
  344. ALIAS (distribute_list,
  345.        ipv6_distribute_list_cmd,
  346.        "distribute-list WORD (in|out) WORD",
  347.        "Filter networks in routing updatesn"
  348.        "Access-list namen"
  349.        "Filter incoming routing updatesn"
  350.        "Filter outgoing routing updatesn"
  351.        "Interface namen");
  352. DEFUN (no_districute_list,
  353.        no_distribute_list_cmd,
  354.        "no distribute-list WORD (in|out) WORD",
  355.        NO_STR
  356.        "Filter networks in routing updatesn"
  357.        "Access-list namen"
  358.        "Filter incoming routing updatesn"
  359.        "Filter outgoing routing updatesn"
  360.        "Interface namen")
  361. {
  362.   int ret;
  363.   enum distribute_type type;
  364.   /* Check of distribute list type. */
  365.   if (strncmp (argv[1], "i", 1) == 0)
  366.     type = DISTRIBUTE_IN;
  367.   else if (strncmp (argv[1], "o", 1) == 0)
  368.     type = DISTRIBUTE_OUT;
  369.   else
  370.     {
  371.       vty_out (vty, "distribute list direction must be [in|out]%s", VTY_NEWLINE);
  372.       return CMD_WARNING;
  373.     }
  374.   ret = distribute_list_unset (argv[2], type, argv[0]);
  375.   if (! ret)
  376.     {
  377.       vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
  378.       return CMD_WARNING;
  379.     }
  380.   return CMD_SUCCESS;
  381. }       
  382. ALIAS (no_districute_list,
  383.        no_ipv6_distribute_list_cmd,
  384.        "no distribute-list WORD (in|out) WORD",
  385.        NO_STR
  386.        "Filter networks in routing updatesn"
  387.        "Access-list namen"
  388.        "Filter incoming routing updatesn"
  389.        "Filter outgoing routing updatesn"
  390.        "Interface namen");
  391. DEFUN (districute_list_prefix_all,
  392.        distribute_list_prefix_all_cmd,
  393.        "distribute-list prefix WORD (in|out)",
  394.        "Filter networks in routing updatesn"
  395.        "Filter prefixes in routing updatesn"
  396.        "Name of an IP prefix-listn"
  397.        "Filter incoming routing updatesn"
  398.        "Filter outgoing routing updatesn")
  399. {
  400.   enum distribute_type type;
  401.   struct distribute *dist;
  402.   /* Check of distribute list type. */
  403.   if (strncmp (argv[1], "i", 1) == 0)
  404.     type = DISTRIBUTE_IN;
  405.   else if (strncmp (argv[1], "o", 1) == 0)
  406.     type = DISTRIBUTE_OUT;
  407.   else
  408.     {
  409.       vty_out (vty, "distribute list direction must be [in|out]%s", 
  410.        VTY_NEWLINE);
  411.       return CMD_WARNING;
  412.     }
  413.   /* Get interface name corresponding distribute list. */
  414.   dist = distribute_list_prefix_set (NULL, type, argv[0]);
  415.   return CMD_SUCCESS;
  416. }       
  417. ALIAS (districute_list_prefix_all,
  418.        ipv6_distribute_list_prefix_all_cmd,
  419.        "distribute-list prefix WORD (in|out)",
  420.        "Filter networks in routing updatesn"
  421.        "Filter prefixes in routing updatesn"
  422.        "Name of an IP prefix-listn"
  423.        "Filter incoming routing updatesn"
  424.        "Filter outgoing routing updatesn");
  425. DEFUN (no_districute_list_prefix_all,
  426.        no_distribute_list_prefix_all_cmd,
  427.        "no distribute-list prefix WORD (in|out)",
  428.        NO_STR
  429.        "Filter networks in routing updatesn"
  430.        "Filter prefixes in routing updatesn"
  431.        "Name of an IP prefix-listn"
  432.        "Filter incoming routing updatesn"
  433.        "Filter outgoing routing updatesn")
  434. {
  435.   int ret;
  436.   enum distribute_type type;
  437.   /* Check of distribute list type. */
  438.   if (strncmp (argv[1], "i", 1) == 0)
  439.     type = DISTRIBUTE_IN;
  440.   else if (strncmp (argv[1], "o", 1) == 0)
  441.     type = DISTRIBUTE_OUT;
  442.   else
  443.     {
  444.       vty_out (vty, "distribute list direction must be [in|out]%s", 
  445.        VTY_NEWLINE);
  446.       return CMD_WARNING;
  447.     }
  448.   ret = distribute_list_prefix_unset (NULL, type, argv[0]);
  449.   if (! ret)
  450.     {
  451.       vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
  452.       return CMD_WARNING;
  453.     }
  454.   return CMD_SUCCESS;
  455. }       
  456. ALIAS (no_districute_list_prefix_all,
  457.        no_ipv6_distribute_list_prefix_all_cmd,
  458.        "no distribute-list prefix WORD (in|out)",
  459.        NO_STR
  460.        "Filter networks in routing updatesn"
  461.        "Filter prefixes in routing updatesn"
  462.        "Name of an IP prefix-listn"
  463.        "Filter incoming routing updatesn"
  464.        "Filter outgoing routing updatesn");
  465. DEFUN (districute_list_prefix, distribute_list_prefix_cmd,
  466.        "distribute-list prefix WORD (in|out) WORD",
  467.        "Filter networks in routing updatesn"
  468.        "Filter prefixes in routing updatesn"
  469.        "Name of an IP prefix-listn"
  470.        "Filter incoming routing updatesn"
  471.        "Filter outgoing routing updatesn"
  472.        "Interface namen")
  473. {
  474.   enum distribute_type type;
  475.   struct distribute *dist;
  476.   /* Check of distribute list type. */
  477.   if (strncmp (argv[1], "i", 1) == 0)
  478.     type = DISTRIBUTE_IN;
  479.   else if (strncmp (argv[1], "o", 1) == 0)
  480.     type = DISTRIBUTE_OUT;
  481.   else
  482.     {
  483.       vty_out (vty, "distribute list direction must be [in|out]%s", 
  484.        VTY_NEWLINE);
  485.       return CMD_WARNING;
  486.     }
  487.   /* Get interface name corresponding distribute list. */
  488.   dist = distribute_list_prefix_set (argv[2], type, argv[0]);
  489.   return CMD_SUCCESS;
  490. }       
  491. ALIAS (districute_list_prefix,
  492.        ipv6_distribute_list_prefix_cmd,
  493.        "distribute-list prefix WORD (in|out) WORD",
  494.        "Filter networks in routing updatesn"
  495.        "Filter prefixes in routing updatesn"
  496.        "Name of an IP prefix-listn"
  497.        "Filter incoming routing updatesn"
  498.        "Filter outgoing routing updatesn"
  499.        "Interface namen");
  500. DEFUN (no_districute_list_prefix,
  501.        no_distribute_list_prefix_cmd,
  502.        "no distribute-list prefix WORD (in|out) WORD",
  503.        NO_STR
  504.        "Filter networks in routing updatesn"
  505.        "Filter prefixes in routing updatesn"
  506.        "Name of an IP prefix-listn"
  507.        "Filter incoming routing updatesn"
  508.        "Filter outgoing routing updatesn"
  509.        "Interface namen")
  510. {
  511.   int ret;
  512.   enum distribute_type type;
  513.   /* Check of distribute list type. */
  514.   if (strncmp (argv[1], "i", 1) == 0)
  515.     type = DISTRIBUTE_IN;
  516.   else if (strncmp (argv[1], "o", 1) == 0)
  517.     type = DISTRIBUTE_OUT;
  518.   else
  519.     {
  520.       vty_out (vty, "distribute list direction must be [in|out]%s", 
  521.        VTY_NEWLINE);
  522.       return CMD_WARNING;
  523.     }
  524.   ret = distribute_list_prefix_unset (argv[2], type, argv[0]);
  525.   if (! ret)
  526.     {
  527.       vty_out (vty, "distribute list doesn't exist%s", VTY_NEWLINE);
  528.       return CMD_WARNING;
  529.     }
  530.   return CMD_SUCCESS;
  531. }       
  532. ALIAS (no_districute_list_prefix,
  533.        no_ipv6_distribute_list_prefix_cmd,
  534.        "no distribute-list prefix WORD (in|out) WORD",
  535.        NO_STR
  536.        "Filter networks in routing updatesn"
  537.        "Filter prefixes in routing updatesn"
  538.        "Name of an IP prefix-listn"
  539.        "Filter incoming routing updatesn"
  540.        "Filter outgoing routing updatesn"
  541.        "Interface namen");
  542. int
  543. config_show_distribute (struct vty *vty)
  544. {
  545.   int i;
  546.   struct hash_backet *mp;
  547.   struct distribute *dist;
  548.   /* Output filter configuration. */
  549.   dist = distribute_lookup (NULL);
  550.   if (dist && (dist->list[DISTRIBUTE_OUT] || dist->prefix[DISTRIBUTE_OUT]))
  551.     {
  552.       vty_out (vty, "  Outgoing update filter list for all interface is");
  553.       if (dist->list[DISTRIBUTE_OUT])
  554. vty_out (vty, " %s", dist->list[DISTRIBUTE_OUT]);
  555.       if (dist->prefix[DISTRIBUTE_OUT])
  556. vty_out (vty, "%s (prefix-list) %s",
  557.  dist->list[DISTRIBUTE_OUT] ? "," : "",
  558.  dist->prefix[DISTRIBUTE_OUT]);
  559.       vty_out (vty, "%s", VTY_NEWLINE);
  560.     }
  561.   else
  562.     vty_out (vty, "  Outgoing update filter list for all interface is not set%s", VTY_NEWLINE);
  563.   for (i = 0; i < disthash->size; i++)
  564.     for (mp = disthash->index[i]; mp; mp = mp->next)
  565.       {
  566. dist = mp->data;
  567. if (dist->ifname)
  568.   if (dist->list[DISTRIBUTE_OUT] || dist->prefix[DISTRIBUTE_OUT])
  569.     {
  570.       vty_out (vty, "    %s filtered by", dist->ifname);
  571.       if (dist->list[DISTRIBUTE_OUT])
  572. vty_out (vty, " %s", dist->list[DISTRIBUTE_OUT]);
  573.       if (dist->prefix[DISTRIBUTE_OUT])
  574. vty_out (vty, "%s (prefix-list) %s",
  575.  dist->list[DISTRIBUTE_OUT] ? "," : "",
  576.  dist->prefix[DISTRIBUTE_OUT]);
  577.       vty_out (vty, "%s", VTY_NEWLINE);
  578.     }
  579.       }
  580.   /* Input filter configuration. */
  581.   dist = distribute_lookup (NULL);
  582.   if (dist && (dist->list[DISTRIBUTE_IN] || dist->prefix[DISTRIBUTE_IN]))
  583.     {
  584.       vty_out (vty, "  Incoming update filter list for all interface is");
  585.       if (dist->list[DISTRIBUTE_IN])
  586. vty_out (vty, " %s", dist->list[DISTRIBUTE_IN]);
  587.       if (dist->prefix[DISTRIBUTE_IN])
  588. vty_out (vty, "%s (prefix-list) %s",
  589.  dist->list[DISTRIBUTE_IN] ? "," : "",
  590.  dist->prefix[DISTRIBUTE_IN]);
  591.       vty_out (vty, "%s", VTY_NEWLINE);
  592.     }
  593.   else
  594.     vty_out (vty, "  Incoming update filter list for all interface is not set%s", VTY_NEWLINE);
  595.   for (i = 0; i < disthash->size; i++)
  596.     for (mp = disthash->index[i]; mp; mp = mp->next)
  597.       {
  598. dist = mp->data;
  599. if (dist->ifname)
  600.   if (dist->list[DISTRIBUTE_IN] || dist->prefix[DISTRIBUTE_IN])
  601.     {
  602.       vty_out (vty, "    %s filtered by", dist->ifname);
  603.       if (dist->list[DISTRIBUTE_IN])
  604. vty_out (vty, " %s", dist->list[DISTRIBUTE_IN]);
  605.       if (dist->prefix[DISTRIBUTE_IN])
  606. vty_out (vty, "%s (prefix-list) %s",
  607.  dist->list[DISTRIBUTE_IN] ? "," : "",
  608.  dist->prefix[DISTRIBUTE_IN]);
  609.       vty_out (vty, "%s", VTY_NEWLINE);
  610.     }
  611.       }
  612.   return 0;
  613. }
  614. /* Configuration write function. */
  615. int
  616. config_write_distribute (struct vty *vty)
  617. {
  618.   int i;
  619.   struct hash_backet *mp;
  620.   int write = 0;
  621.   for (i = 0; i < disthash->size; i++)
  622.     for (mp = disthash->index[i]; mp; mp = mp->next)
  623.       {
  624. struct distribute *dist;
  625. dist = mp->data;
  626. if (dist->list[DISTRIBUTE_IN])
  627.   {
  628.     vty_out (vty, " distribute-list %s in %s%s", 
  629.      dist->list[DISTRIBUTE_IN],
  630.      dist->ifname ? dist->ifname : "",
  631.      VTY_NEWLINE);
  632.     write++;
  633.   }
  634. if (dist->list[DISTRIBUTE_OUT])
  635.   {
  636.     vty_out (vty, " distribute-list %s out %s%s", 
  637.      dist->list[DISTRIBUTE_OUT],
  638.      dist->ifname ? dist->ifname : "",
  639.      VTY_NEWLINE);
  640.     write++;
  641.   }
  642. if (dist->prefix[DISTRIBUTE_IN])
  643.   {
  644.     vty_out (vty, " distribute-list prefix %s in %s%s",
  645.      dist->prefix[DISTRIBUTE_IN],
  646.      dist->ifname ? dist->ifname : "",
  647.      VTY_NEWLINE);
  648.     write++;
  649.   }
  650. if (dist->prefix[DISTRIBUTE_OUT])
  651.   {
  652.     vty_out (vty, " distribute-list prefix %s out %s%s",
  653.      dist->prefix[DISTRIBUTE_OUT],
  654.      dist->ifname ? dist->ifname : "",
  655.      VTY_NEWLINE);
  656.     write++;
  657.   }
  658.       }
  659.   return write;
  660. }
  661. /* Clear all distribute list. */
  662. void
  663. distribute_list_reset ()
  664. {
  665.   hash_clean (disthash, (void (*) (void *)) distribute_free);
  666. }
  667. /* Initialize distribute list related hash. */
  668. void
  669. distribute_list_init (int node)
  670. {
  671.   disthash = hash_create (distribute_hash_make, distribute_cmp);
  672.   if (node == RIP_NODE)
  673.     {
  674.       install_element (RIP_NODE, &distribute_list_all_cmd);
  675.       install_element (RIP_NODE, &no_distribute_list_all_cmd);
  676.       install_element (RIP_NODE, &distribute_list_cmd);
  677.       install_element (RIP_NODE, &no_distribute_list_cmd);
  678.       install_element (RIP_NODE, &distribute_list_prefix_all_cmd);
  679.       install_element (RIP_NODE, &no_distribute_list_prefix_all_cmd);
  680.       install_element (RIP_NODE, &distribute_list_prefix_cmd);
  681.       install_element (RIP_NODE, &no_distribute_list_prefix_cmd);
  682.     }
  683.   else
  684.     {
  685.       install_element (RIPNG_NODE, &ipv6_distribute_list_all_cmd);
  686.       install_element (RIPNG_NODE, &no_ipv6_distribute_list_all_cmd);
  687.       install_element (RIPNG_NODE, &ipv6_distribute_list_cmd);
  688.       install_element (RIPNG_NODE, &no_ipv6_distribute_list_cmd);
  689.       install_element (RIPNG_NODE, &ipv6_distribute_list_prefix_all_cmd);
  690.       install_element (RIPNG_NODE, &no_ipv6_distribute_list_prefix_all_cmd);
  691.       install_element (RIPNG_NODE, &ipv6_distribute_list_prefix_cmd);
  692.       install_element (RIPNG_NODE, &no_ipv6_distribute_list_prefix_cmd);
  693.     }
  694. }