Annotation of embedaddon/quagga/ripd/rip_offset.c, revision 1.1.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>