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

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