Annotation of embedaddon/quagga/ripngd/ripng_offset.c, revision 1.1

1.1     ! misho       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>