Annotation of embedaddon/quagga/ripd/rip_offset.c, revision 1.1

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