File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ripd / rip_offset.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:12 2012 UTC (12 years, 4 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, v0_99_22p0, v0_99_22, v0_99_21, v0_99_20_1, v0_99_20, HEAD
quagga

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>