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