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

1.1     ! misho       1: /* RIPv2 routemap.
        !             2:  * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com>
        !             3:  * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
        !             4:  *
        !             5:  * This file is part of GNU Zebra.
        !             6:  *
        !             7:  * GNU Zebra is free software; you can redistribute it and/or modify it
        !             8:  * under the terms of the GNU General Public License as published by the
        !             9:  * Free Software Foundation; either version 2, or (at your option) any
        !            10:  * later version.
        !            11:  *
        !            12:  * GNU Zebra is distributed in the hope that it will be useful, but
        !            13:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            15:  * General Public License for more details.
        !            16:  *
        !            17:  * You should have received a copy of the GNU General Public License
        !            18:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
        !            19:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
        !            20:  * 02111-1307, USA.  
        !            21:  */
        !            22: 
        !            23: #include <zebra.h>
        !            24: 
        !            25: #include "memory.h"
        !            26: #include "prefix.h"
        !            27: #include "routemap.h"
        !            28: #include "command.h"
        !            29: #include "filter.h"
        !            30: #include "log.h"
        !            31: #include "sockunion.h"         /* for inet_aton () */
        !            32: #include "plist.h"
        !            33: 
        !            34: #include "ripd/ripd.h"
        !            35: 
        !            36: struct rip_metric_modifier
        !            37: {
        !            38:   enum 
        !            39:   {
        !            40:     metric_increment,
        !            41:     metric_decrement,
        !            42:     metric_absolute
        !            43:   } type;
        !            44: 
        !            45:   u_char metric;
        !            46: };
        !            47: 
        !            48: /* Add rip route map rule. */
        !            49: static int
        !            50: rip_route_match_add (struct vty *vty, struct route_map_index *index,
        !            51:                     const char *command, const char *arg)
        !            52: {
        !            53:   int ret;
        !            54: 
        !            55:   ret = route_map_add_match (index, command, arg);
        !            56:   if (ret)
        !            57:     {
        !            58:       switch (ret)
        !            59:        {
        !            60:        case RMAP_RULE_MISSING:
        !            61:          vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
        !            62:          return CMD_WARNING;
        !            63:        case RMAP_COMPILE_ERROR:
        !            64:          vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
        !            65:          return CMD_WARNING;
        !            66:        }
        !            67:     }
        !            68:   return CMD_SUCCESS;
        !            69: }
        !            70: 
        !            71: /* Delete rip route map rule. */
        !            72: static int
        !            73: rip_route_match_delete (struct vty *vty, struct route_map_index *index,
        !            74:                        const char *command, const char *arg)
        !            75: {
        !            76:   int ret;
        !            77: 
        !            78:   ret = route_map_delete_match (index, command, arg);
        !            79:   if (ret)
        !            80:     {
        !            81:       switch (ret)
        !            82:        {
        !            83:        case RMAP_RULE_MISSING:
        !            84:          vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
        !            85:          return CMD_WARNING;
        !            86:        case RMAP_COMPILE_ERROR:
        !            87:          vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
        !            88:          return CMD_WARNING;
        !            89:        }
        !            90:     }
        !            91:   return CMD_SUCCESS;
        !            92: }
        !            93: 
        !            94: /* Add rip route map rule. */
        !            95: static int
        !            96: rip_route_set_add (struct vty *vty, struct route_map_index *index,
        !            97:                   const char *command, const char *arg)
        !            98: {
        !            99:   int ret;
        !           100: 
        !           101:   ret = route_map_add_set (index, command, arg);
        !           102:   if (ret)
        !           103:     {
        !           104:       switch (ret)
        !           105:        {
        !           106:        case RMAP_RULE_MISSING:
        !           107:          vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
        !           108:          return CMD_WARNING;
        !           109:        case RMAP_COMPILE_ERROR:
        !           110:          /* rip, ripng and other protocols share the set metric command
        !           111:             but only values from 0 to 16 are valid for rip and ripng
        !           112:             if metric is out of range for rip and ripng, it is not for
        !           113:             other protocols. Do not return an error */
        !           114:          if (strcmp(command, "metric")) {
        !           115:             vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
        !           116:             return CMD_WARNING;
        !           117:          }
        !           118:        }
        !           119:     }
        !           120:   return CMD_SUCCESS;
        !           121: }
        !           122: 
        !           123: /* Delete rip route map rule. */
        !           124: static int
        !           125: rip_route_set_delete (struct vty *vty, struct route_map_index *index,
        !           126:                      const char *command, const char *arg)
        !           127: {
        !           128:   int ret;
        !           129: 
        !           130:   ret = route_map_delete_set (index, command, arg);
        !           131:   if (ret)
        !           132:     {
        !           133:       switch (ret)
        !           134:        {
        !           135:        case RMAP_RULE_MISSING:
        !           136:          vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
        !           137:          return CMD_WARNING;
        !           138:        case RMAP_COMPILE_ERROR:
        !           139:          vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
        !           140:          return CMD_WARNING;
        !           141:        }
        !           142:     }
        !           143:   return CMD_SUCCESS;
        !           144: }
        !           145: 
        !           146: /* Hook function for updating route_map assignment. */
        !           147: /* ARGSUSED */
        !           148: static void
        !           149: rip_route_map_update (const char *notused)
        !           150: {
        !           151:   int i;
        !           152: 
        !           153:   if (rip) 
        !           154:     {
        !           155:       for (i = 0; i < ZEBRA_ROUTE_MAX; i++) 
        !           156:        {
        !           157:          if (rip->route_map[i].name)
        !           158:            rip->route_map[i].map = 
        !           159:              route_map_lookup_by_name (rip->route_map[i].name);
        !           160:        }
        !           161:     }
        !           162: }
        !           163: 
        !           164: /* `match metric METRIC' */
        !           165: /* Match function return 1 if match is success else return zero. */
        !           166: static route_map_result_t
        !           167: route_match_metric (void *rule, struct prefix *prefix, 
        !           168:                    route_map_object_t type, void *object)
        !           169: {
        !           170:   u_int32_t *metric;
        !           171:   u_int32_t  check;
        !           172:   struct rip_info *rinfo;
        !           173: 
        !           174:   if (type == RMAP_RIP)
        !           175:     {
        !           176:       metric = rule;
        !           177:       rinfo = object;
        !           178:     
        !           179:       /* If external metric is available, the route-map should
        !           180:          work on this one (for redistribute purpose)  */
        !           181:       check = (rinfo->external_metric) ? rinfo->external_metric :
        !           182:                                          rinfo->metric;
        !           183:       if (check == *metric)
        !           184:        return RMAP_MATCH;
        !           185:       else
        !           186:        return RMAP_NOMATCH;
        !           187:     }
        !           188:   return RMAP_NOMATCH;
        !           189: }
        !           190: 
        !           191: /* Route map `match metric' match statement. `arg' is METRIC value */
        !           192: static void *
        !           193: route_match_metric_compile (const char *arg)
        !           194: {
        !           195:   u_int32_t *metric;
        !           196: 
        !           197:   metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
        !           198:   *metric = atoi (arg);
        !           199: 
        !           200:   if(*metric > 0)
        !           201:     return metric;
        !           202: 
        !           203:   XFREE (MTYPE_ROUTE_MAP_COMPILED, metric);
        !           204:   return NULL;
        !           205: }
        !           206: 
        !           207: /* Free route map's compiled `match metric' value. */
        !           208: static void
        !           209: route_match_metric_free (void *rule)
        !           210: {
        !           211:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           212: }
        !           213: 
        !           214: /* Route map commands for metric matching. */
        !           215: struct route_map_rule_cmd route_match_metric_cmd =
        !           216: {
        !           217:   "metric",
        !           218:   route_match_metric,
        !           219:   route_match_metric_compile,
        !           220:   route_match_metric_free
        !           221: };
        !           222: 
        !           223: /* `match interface IFNAME' */
        !           224: /* Match function return 1 if match is success else return zero. */
        !           225: static route_map_result_t
        !           226: route_match_interface (void *rule, struct prefix *prefix,
        !           227:                       route_map_object_t type, void *object)
        !           228: {
        !           229:   struct rip_info *rinfo;
        !           230:   struct interface *ifp;
        !           231:   char *ifname;
        !           232: 
        !           233:   if (type == RMAP_RIP)
        !           234:     {
        !           235:       ifname = rule;
        !           236:       ifp = if_lookup_by_name(ifname);
        !           237: 
        !           238:       if (!ifp)
        !           239:        return RMAP_NOMATCH;
        !           240: 
        !           241:       rinfo = object;
        !           242: 
        !           243:       if (rinfo->ifindex_out == ifp->ifindex || rinfo->ifindex == ifp->ifindex)
        !           244:        return RMAP_MATCH;
        !           245:       else
        !           246:        return RMAP_NOMATCH;
        !           247:     }
        !           248:   return RMAP_NOMATCH;
        !           249: }
        !           250: 
        !           251: /* Route map `match interface' match statement. `arg' is IFNAME value */
        !           252: /* XXX I don`t know if I need to check does interface exist? */
        !           253: static void *
        !           254: route_match_interface_compile (const char *arg)
        !           255: {
        !           256:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
        !           257: }
        !           258: 
        !           259: /* Free route map's compiled `match interface' value. */
        !           260: static void
        !           261: route_match_interface_free (void *rule)
        !           262: {
        !           263:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           264: }
        !           265: 
        !           266: /* Route map commands for interface matching. */
        !           267: struct route_map_rule_cmd route_match_interface_cmd =
        !           268: {
        !           269:   "interface",
        !           270:   route_match_interface,
        !           271:   route_match_interface_compile,
        !           272:   route_match_interface_free
        !           273: };
        !           274: 
        !           275: /* `match ip next-hop IP_ACCESS_LIST' */
        !           276: 
        !           277: /* Match function return 1 if match is success else return zero. */
        !           278: static route_map_result_t
        !           279: route_match_ip_next_hop (void *rule, struct prefix *prefix,
        !           280:                        route_map_object_t type, void *object)
        !           281: {
        !           282:   struct access_list *alist;
        !           283:   struct rip_info *rinfo;
        !           284:   struct prefix_ipv4 p;
        !           285: 
        !           286:   if (type == RMAP_RIP)
        !           287:     {
        !           288:       rinfo = object;
        !           289:       p.family = AF_INET;
        !           290:       p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from;
        !           291:       p.prefixlen = IPV4_MAX_BITLEN;
        !           292: 
        !           293:       alist = access_list_lookup (AFI_IP, (char *) rule);
        !           294:       if (alist == NULL)
        !           295:        return RMAP_NOMATCH;
        !           296: 
        !           297:       return (access_list_apply (alist, &p) == FILTER_DENY ?
        !           298:              RMAP_NOMATCH : RMAP_MATCH);
        !           299:     }
        !           300:   return RMAP_NOMATCH;
        !           301: }
        !           302: 
        !           303: /* Route map `ip next-hop' match statement.  `arg' should be
        !           304:    access-list name. */
        !           305: static void *
        !           306: route_match_ip_next_hop_compile (const char *arg)
        !           307: {
        !           308:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
        !           309: }
        !           310: 
        !           311: /* Free route map's compiled `. */
        !           312: static void
        !           313: route_match_ip_next_hop_free (void *rule)
        !           314: {
        !           315:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           316: }
        !           317: 
        !           318: /* Route map commands for ip next-hop matching. */
        !           319: static struct route_map_rule_cmd route_match_ip_next_hop_cmd =
        !           320: {
        !           321:   "ip next-hop",
        !           322:   route_match_ip_next_hop,
        !           323:   route_match_ip_next_hop_compile,
        !           324:   route_match_ip_next_hop_free
        !           325: };
        !           326: 
        !           327: /* `match ip next-hop prefix-list PREFIX_LIST' */
        !           328: 
        !           329: static route_map_result_t
        !           330: route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
        !           331:                                     route_map_object_t type, void *object)
        !           332: {
        !           333:   struct prefix_list *plist;
        !           334:   struct rip_info *rinfo;
        !           335:   struct prefix_ipv4 p;
        !           336: 
        !           337:   if (type == RMAP_RIP)
        !           338:     {
        !           339:       rinfo = object;
        !           340:       p.family = AF_INET;
        !           341:       p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from;
        !           342:       p.prefixlen = IPV4_MAX_BITLEN;
        !           343: 
        !           344:       plist = prefix_list_lookup (AFI_IP, (char *) rule);
        !           345:       if (plist == NULL)
        !           346:         return RMAP_NOMATCH;
        !           347: 
        !           348:       return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
        !           349:               RMAP_NOMATCH : RMAP_MATCH);
        !           350:     }
        !           351:   return RMAP_NOMATCH;
        !           352: }
        !           353: 
        !           354: static void *
        !           355: route_match_ip_next_hop_prefix_list_compile (const char *arg)
        !           356: {
        !           357:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
        !           358: }
        !           359: 
        !           360: static void
        !           361: route_match_ip_next_hop_prefix_list_free (void *rule)
        !           362: {
        !           363:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           364: }
        !           365: 
        !           366: static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
        !           367: {
        !           368:   "ip next-hop prefix-list",
        !           369:   route_match_ip_next_hop_prefix_list,
        !           370:   route_match_ip_next_hop_prefix_list_compile,
        !           371:   route_match_ip_next_hop_prefix_list_free
        !           372: };
        !           373: 
        !           374: /* `match ip address IP_ACCESS_LIST' */
        !           375: 
        !           376: /* Match function should return 1 if match is success else return
        !           377:    zero. */
        !           378: static route_map_result_t
        !           379: route_match_ip_address (void *rule, struct prefix *prefix, 
        !           380:                        route_map_object_t type, void *object)
        !           381: {
        !           382:   struct access_list *alist;
        !           383: 
        !           384:   if (type == RMAP_RIP)
        !           385:     {
        !           386:       alist = access_list_lookup (AFI_IP, (char *) rule);
        !           387:       if (alist == NULL)
        !           388:        return RMAP_NOMATCH;
        !           389:     
        !           390:       return (access_list_apply (alist, prefix) == FILTER_DENY ?
        !           391:              RMAP_NOMATCH : RMAP_MATCH);
        !           392:     }
        !           393:   return RMAP_NOMATCH;
        !           394: }
        !           395: 
        !           396: /* Route map `ip address' match statement.  `arg' should be
        !           397:    access-list name. */
        !           398: static void *
        !           399: route_match_ip_address_compile (const char *arg)
        !           400: {
        !           401:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
        !           402: }
        !           403: 
        !           404: /* Free route map's compiled `ip address' value. */
        !           405: static void
        !           406: route_match_ip_address_free (void *rule)
        !           407: {
        !           408:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           409: }
        !           410: 
        !           411: /* Route map commands for ip address matching. */
        !           412: static struct route_map_rule_cmd route_match_ip_address_cmd =
        !           413: {
        !           414:   "ip address",
        !           415:   route_match_ip_address,
        !           416:   route_match_ip_address_compile,
        !           417:   route_match_ip_address_free
        !           418: };
        !           419: 
        !           420: /* `match ip address prefix-list PREFIX_LIST' */
        !           421: 
        !           422: static route_map_result_t
        !           423: route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, 
        !           424:                                    route_map_object_t type, void *object)
        !           425: {
        !           426:   struct prefix_list *plist;
        !           427: 
        !           428:   if (type == RMAP_RIP)
        !           429:     {
        !           430:       plist = prefix_list_lookup (AFI_IP, (char *) rule);
        !           431:       if (plist == NULL)
        !           432:        return RMAP_NOMATCH;
        !           433:     
        !           434:       return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
        !           435:              RMAP_NOMATCH : RMAP_MATCH);
        !           436:     }
        !           437:   return RMAP_NOMATCH;
        !           438: }
        !           439: 
        !           440: static void *
        !           441: route_match_ip_address_prefix_list_compile (const char *arg)
        !           442: {
        !           443:   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
        !           444: }
        !           445: 
        !           446: static void
        !           447: route_match_ip_address_prefix_list_free (void *rule)
        !           448: {
        !           449:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           450: }
        !           451: 
        !           452: static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
        !           453: {
        !           454:   "ip address prefix-list",
        !           455:   route_match_ip_address_prefix_list,
        !           456:   route_match_ip_address_prefix_list_compile,
        !           457:   route_match_ip_address_prefix_list_free
        !           458: };
        !           459: 
        !           460: /* `match tag TAG' */
        !           461: /* Match function return 1 if match is success else return zero. */
        !           462: static route_map_result_t
        !           463: route_match_tag (void *rule, struct prefix *prefix, 
        !           464:                    route_map_object_t type, void *object)
        !           465: {
        !           466:   u_short *tag;
        !           467:   struct rip_info *rinfo;
        !           468: 
        !           469:   if (type == RMAP_RIP)
        !           470:     {
        !           471:       tag = rule;
        !           472:       rinfo = object;
        !           473: 
        !           474:       /* The information stored by rinfo is host ordered. */
        !           475:       if (rinfo->tag == *tag)
        !           476:        return RMAP_MATCH;
        !           477:       else
        !           478:        return RMAP_NOMATCH;
        !           479:     }
        !           480:   return RMAP_NOMATCH;
        !           481: }
        !           482: 
        !           483: /* Route map `match tag' match statement. `arg' is TAG value */
        !           484: static void *
        !           485: route_match_tag_compile (const char *arg)
        !           486: {
        !           487:   u_short *tag;
        !           488: 
        !           489:   tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
        !           490:   *tag = atoi (arg);
        !           491: 
        !           492:   return tag;
        !           493: }
        !           494: 
        !           495: /* Free route map's compiled `match tag' value. */
        !           496: static void
        !           497: route_match_tag_free (void *rule)
        !           498: {
        !           499:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           500: }
        !           501: 
        !           502: /* Route map commands for tag matching. */
        !           503: struct route_map_rule_cmd route_match_tag_cmd =
        !           504: {
        !           505:   "tag",
        !           506:   route_match_tag,
        !           507:   route_match_tag_compile,
        !           508:   route_match_tag_free
        !           509: };
        !           510: 
        !           511: /* `set metric METRIC' */
        !           512: 
        !           513: /* Set metric to attribute. */
        !           514: static route_map_result_t
        !           515: route_set_metric (void *rule, struct prefix *prefix, 
        !           516:                  route_map_object_t type, void *object)
        !           517: {
        !           518:   if (type == RMAP_RIP)
        !           519:     {
        !           520:       struct rip_metric_modifier *mod;
        !           521:       struct rip_info *rinfo;
        !           522: 
        !           523:       mod = rule;
        !           524:       rinfo = object;
        !           525: 
        !           526:       if (mod->type == metric_increment)
        !           527:        rinfo->metric_out += mod->metric;
        !           528:       else if (mod->type == metric_decrement)
        !           529:        rinfo->metric_out -= mod->metric;
        !           530:       else if (mod->type == metric_absolute)
        !           531:        rinfo->metric_out = mod->metric;
        !           532: 
        !           533:       if ((signed int)rinfo->metric_out < 1)
        !           534:        rinfo->metric_out = 1;
        !           535:       if (rinfo->metric_out > RIP_METRIC_INFINITY)
        !           536:        rinfo->metric_out = RIP_METRIC_INFINITY;
        !           537: 
        !           538:       rinfo->metric_set = 1;
        !           539:     }
        !           540:   return RMAP_OKAY;
        !           541: }
        !           542: 
        !           543: /* set metric compilation. */
        !           544: static void *
        !           545: route_set_metric_compile (const char *arg)
        !           546: {
        !           547:   int len;
        !           548:   const char *pnt;
        !           549:   int type;
        !           550:   long metric;
        !           551:   char *endptr = NULL;
        !           552:   struct rip_metric_modifier *mod;
        !           553: 
        !           554:   len = strlen (arg);
        !           555:   pnt = arg;
        !           556: 
        !           557:   if (len == 0)
        !           558:     return NULL;
        !           559: 
        !           560:   /* Examine first character. */
        !           561:   if (arg[0] == '+')
        !           562:     {
        !           563:       type = metric_increment;
        !           564:       pnt++;
        !           565:     }
        !           566:   else if (arg[0] == '-')
        !           567:     {
        !           568:       type = metric_decrement;
        !           569:       pnt++;
        !           570:     }
        !           571:   else
        !           572:     type = metric_absolute;
        !           573: 
        !           574:   /* Check beginning with digit string. */
        !           575:   if (*pnt < '0' || *pnt > '9')
        !           576:     return NULL;
        !           577: 
        !           578:   /* Convert string to integer. */
        !           579:   metric = strtol (pnt, &endptr, 10);
        !           580: 
        !           581:   if (metric == LONG_MAX || *endptr != '\0')
        !           582:     return NULL;
        !           583:   if (metric < 0 || metric > RIP_METRIC_INFINITY)
        !           584:     return NULL;
        !           585: 
        !           586:   mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, 
        !           587:                 sizeof (struct rip_metric_modifier));
        !           588:   mod->type = type;
        !           589:   mod->metric = metric;
        !           590: 
        !           591:   return mod;
        !           592: }
        !           593: 
        !           594: /* Free route map's compiled `set metric' value. */
        !           595: static void
        !           596: route_set_metric_free (void *rule)
        !           597: {
        !           598:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           599: }
        !           600: 
        !           601: /* Set metric rule structure. */
        !           602: static struct route_map_rule_cmd route_set_metric_cmd = 
        !           603: {
        !           604:   "metric",
        !           605:   route_set_metric,
        !           606:   route_set_metric_compile,
        !           607:   route_set_metric_free,
        !           608: };
        !           609: 
        !           610: /* `set ip next-hop IP_ADDRESS' */
        !           611: 
        !           612: /* Set nexthop to object.  ojbect must be pointer to struct attr. */
        !           613: static route_map_result_t
        !           614: route_set_ip_nexthop (void *rule, struct prefix *prefix, 
        !           615:                      route_map_object_t type, void *object)
        !           616: {
        !           617:   struct in_addr *address;
        !           618:   struct rip_info *rinfo;
        !           619: 
        !           620:   if(type == RMAP_RIP)
        !           621:     {
        !           622:       /* Fetch routemap's rule information. */
        !           623:       address = rule;
        !           624:       rinfo = object;
        !           625:     
        !           626:       /* Set next hop value. */ 
        !           627:       rinfo->nexthop_out = *address;
        !           628:     }
        !           629: 
        !           630:   return RMAP_OKAY;
        !           631: }
        !           632: 
        !           633: /* Route map `ip nexthop' compile function.  Given string is converted
        !           634:    to struct in_addr structure. */
        !           635: static void *
        !           636: route_set_ip_nexthop_compile (const char *arg)
        !           637: {
        !           638:   int ret;
        !           639:   struct in_addr *address;
        !           640: 
        !           641:   address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
        !           642: 
        !           643:   ret = inet_aton (arg, address);
        !           644: 
        !           645:   if (ret == 0)
        !           646:     {
        !           647:       XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
        !           648:       return NULL;
        !           649:     }
        !           650: 
        !           651:   return address;
        !           652: }
        !           653: 
        !           654: /* Free route map's compiled `ip nexthop' value. */
        !           655: static void
        !           656: route_set_ip_nexthop_free (void *rule)
        !           657: {
        !           658:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           659: }
        !           660: 
        !           661: /* Route map commands for ip nexthop set. */
        !           662: static struct route_map_rule_cmd route_set_ip_nexthop_cmd =
        !           663: {
        !           664:   "ip next-hop",
        !           665:   route_set_ip_nexthop,
        !           666:   route_set_ip_nexthop_compile,
        !           667:   route_set_ip_nexthop_free
        !           668: };
        !           669: 
        !           670: /* `set tag TAG' */
        !           671: 
        !           672: /* Set tag to object.  ojbect must be pointer to struct attr. */
        !           673: static route_map_result_t
        !           674: route_set_tag (void *rule, struct prefix *prefix, 
        !           675:                      route_map_object_t type, void *object)
        !           676: {
        !           677:   u_short *tag;
        !           678:   struct rip_info *rinfo;
        !           679: 
        !           680:   if(type == RMAP_RIP)
        !           681:     {
        !           682:       /* Fetch routemap's rule information. */
        !           683:       tag = rule;
        !           684:       rinfo = object;
        !           685:     
        !           686:       /* Set next hop value. */ 
        !           687:       rinfo->tag_out = *tag;
        !           688:     }
        !           689: 
        !           690:   return RMAP_OKAY;
        !           691: }
        !           692: 
        !           693: /* Route map `tag' compile function.  Given string is converted
        !           694:    to u_short. */
        !           695: static void *
        !           696: route_set_tag_compile (const char *arg)
        !           697: {
        !           698:   u_short *tag;
        !           699: 
        !           700:   tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short));
        !           701:   *tag = atoi (arg);
        !           702: 
        !           703:   return tag;
        !           704: }
        !           705: 
        !           706: /* Free route map's compiled `ip nexthop' value. */
        !           707: static void
        !           708: route_set_tag_free (void *rule)
        !           709: {
        !           710:   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
        !           711: }
        !           712: 
        !           713: /* Route map commands for tag set. */
        !           714: static struct route_map_rule_cmd route_set_tag_cmd =
        !           715: {
        !           716:   "tag",
        !           717:   route_set_tag,
        !           718:   route_set_tag_compile,
        !           719:   route_set_tag_free
        !           720: };
        !           721: 
        !           722: #define MATCH_STR "Match values from routing table\n"
        !           723: #define SET_STR "Set values in destination routing protocol\n"
        !           724: 
        !           725: DEFUN (match_metric, 
        !           726:        match_metric_cmd,
        !           727:        "match metric <0-4294967295>",
        !           728:        MATCH_STR
        !           729:        "Match metric of route\n"
        !           730:        "Metric value\n")
        !           731: {
        !           732:   return rip_route_match_add (vty, vty->index, "metric", argv[0]);
        !           733: }
        !           734: 
        !           735: DEFUN (no_match_metric,
        !           736:        no_match_metric_cmd,
        !           737:        "no match metric",
        !           738:        NO_STR
        !           739:        MATCH_STR
        !           740:        "Match metric of route\n")
        !           741: {
        !           742:   if (argc == 0)
        !           743:     return rip_route_match_delete (vty, vty->index, "metric", NULL);
        !           744: 
        !           745:   return rip_route_match_delete (vty, vty->index, "metric", argv[0]);
        !           746: }
        !           747: 
        !           748: ALIAS (no_match_metric,
        !           749:        no_match_metric_val_cmd,
        !           750:        "no match metric <0-4294967295>",
        !           751:        NO_STR
        !           752:        MATCH_STR
        !           753:        "Match metric of route\n"
        !           754:        "Metric value\n")
        !           755: 
        !           756: DEFUN (match_interface,
        !           757:        match_interface_cmd,
        !           758:        "match interface WORD",
        !           759:        MATCH_STR
        !           760:        "Match first hop interface of route\n"
        !           761:        "Interface name\n")
        !           762: {
        !           763:   return rip_route_match_add (vty, vty->index, "interface", argv[0]);
        !           764: }
        !           765: 
        !           766: DEFUN (no_match_interface,
        !           767:        no_match_interface_cmd,
        !           768:        "no match interface",
        !           769:        NO_STR
        !           770:        MATCH_STR
        !           771:        "Match first hop interface of route\n")
        !           772: {
        !           773:   if (argc == 0)
        !           774:     return rip_route_match_delete (vty, vty->index, "interface", NULL);
        !           775: 
        !           776:   return rip_route_match_delete (vty, vty->index, "interface", argv[0]);
        !           777: }
        !           778: 
        !           779: ALIAS (no_match_interface,
        !           780:        no_match_interface_val_cmd,
        !           781:        "no match interface WORD",
        !           782:        NO_STR
        !           783:        MATCH_STR
        !           784:        "Match first hop interface of route\n"
        !           785:        "Interface name\n")
        !           786: 
        !           787: DEFUN (match_ip_next_hop,
        !           788:        match_ip_next_hop_cmd,
        !           789:        "match ip next-hop (<1-199>|<1300-2699>|WORD)",
        !           790:        MATCH_STR
        !           791:        IP_STR
        !           792:        "Match next-hop address of route\n"
        !           793:        "IP access-list number\n"
        !           794:        "IP access-list number (expanded range)\n"
        !           795:        "IP Access-list name\n")
        !           796: {
        !           797:   return rip_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
        !           798: }
        !           799: 
        !           800: DEFUN (no_match_ip_next_hop,
        !           801:        no_match_ip_next_hop_cmd,
        !           802:        "no match ip next-hop",
        !           803:        NO_STR
        !           804:        MATCH_STR
        !           805:        IP_STR
        !           806:        "Match next-hop address of route\n")
        !           807: {
        !           808:   if (argc == 0)
        !           809:     return rip_route_match_delete (vty, vty->index, "ip next-hop", NULL);
        !           810: 
        !           811:   return rip_route_match_delete (vty, vty->index, "ip next-hop", argv[0]);
        !           812: }
        !           813: 
        !           814: ALIAS (no_match_ip_next_hop,
        !           815:        no_match_ip_next_hop_val_cmd,
        !           816:        "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
        !           817:        NO_STR
        !           818:        MATCH_STR
        !           819:        IP_STR
        !           820:        "Match next-hop address of route\n"
        !           821:        "IP access-list number\n"
        !           822:        "IP access-list number (expanded range)\n"
        !           823:        "IP Access-list name\n")
        !           824: 
        !           825: DEFUN (match_ip_next_hop_prefix_list,
        !           826:        match_ip_next_hop_prefix_list_cmd,
        !           827:        "match ip next-hop prefix-list WORD",
        !           828:        MATCH_STR
        !           829:        IP_STR
        !           830:        "Match next-hop address of route\n"
        !           831:        "Match entries of prefix-lists\n"
        !           832:        "IP prefix-list name\n")
        !           833: {
        !           834:   return rip_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]);
        !           835: }
        !           836: 
        !           837: DEFUN (no_match_ip_next_hop_prefix_list,
        !           838:        no_match_ip_next_hop_prefix_list_cmd,
        !           839:        "no match ip next-hop prefix-list",
        !           840:        NO_STR
        !           841:        MATCH_STR
        !           842:        IP_STR
        !           843:        "Match next-hop address of route\n"
        !           844:        "Match entries of prefix-lists\n")
        !           845: {
        !           846:   if (argc == 0)
        !           847:     return rip_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL);
        !           848: 
        !           849:   return rip_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]);
        !           850: }
        !           851: 
        !           852: ALIAS (no_match_ip_next_hop_prefix_list,
        !           853:        no_match_ip_next_hop_prefix_list_val_cmd,
        !           854:        "no match ip next-hop prefix-list WORD",
        !           855:        NO_STR
        !           856:        MATCH_STR
        !           857:        IP_STR
        !           858:        "Match next-hop address of route\n"
        !           859:        "Match entries of prefix-lists\n"
        !           860:        "IP prefix-list name\n")
        !           861: 
        !           862: DEFUN (match_ip_address,
        !           863:        match_ip_address_cmd,
        !           864:        "match ip address (<1-199>|<1300-2699>|WORD)",
        !           865:        MATCH_STR
        !           866:        IP_STR
        !           867:        "Match address of route\n"
        !           868:        "IP access-list number\n"
        !           869:        "IP access-list number (expanded range)\n"
        !           870:        "IP Access-list name\n")
        !           871: 
        !           872: {
        !           873:   return rip_route_match_add (vty, vty->index, "ip address", argv[0]);
        !           874: }
        !           875: 
        !           876: DEFUN (no_match_ip_address, 
        !           877:        no_match_ip_address_cmd,
        !           878:        "no match ip address",
        !           879:        NO_STR
        !           880:        MATCH_STR
        !           881:        IP_STR
        !           882:        "Match address of route\n")
        !           883: {
        !           884:   if (argc == 0)
        !           885:     return rip_route_match_delete (vty, vty->index, "ip address", NULL);
        !           886: 
        !           887:   return rip_route_match_delete (vty, vty->index, "ip address", argv[0]);
        !           888: }
        !           889: 
        !           890: ALIAS (no_match_ip_address,
        !           891:        no_match_ip_address_val_cmd,
        !           892:        "no match ip address (<1-199>|<1300-2699>|WORD)",
        !           893:        NO_STR
        !           894:        MATCH_STR
        !           895:        IP_STR
        !           896:        "Match address of route\n"
        !           897:        "IP access-list number\n"
        !           898:        "IP access-list number (expanded range)\n"
        !           899:        "IP Access-list name\n")
        !           900: 
        !           901: DEFUN (match_ip_address_prefix_list, 
        !           902:        match_ip_address_prefix_list_cmd,
        !           903:        "match ip address prefix-list WORD",
        !           904:        MATCH_STR
        !           905:        IP_STR
        !           906:        "Match address of route\n"
        !           907:        "Match entries of prefix-lists\n"
        !           908:        "IP prefix-list name\n")
        !           909: {
        !           910:   return rip_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]);
        !           911: }
        !           912: 
        !           913: DEFUN (no_match_ip_address_prefix_list,
        !           914:        no_match_ip_address_prefix_list_cmd,
        !           915:        "no match ip address prefix-list",
        !           916:        NO_STR
        !           917:        MATCH_STR
        !           918:        IP_STR
        !           919:        "Match address of route\n"
        !           920:        "Match entries of prefix-lists\n")
        !           921: {
        !           922:   if (argc == 0)
        !           923:     return rip_route_match_delete (vty, vty->index, "ip address prefix-list", NULL);
        !           924: 
        !           925:   return rip_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]);
        !           926: }
        !           927: 
        !           928: ALIAS (no_match_ip_address_prefix_list,
        !           929:        no_match_ip_address_prefix_list_val_cmd,
        !           930:        "no match ip address prefix-list WORD",
        !           931:        NO_STR
        !           932:        MATCH_STR
        !           933:        IP_STR
        !           934:        "Match address of route\n"
        !           935:        "Match entries of prefix-lists\n"
        !           936:        "IP prefix-list name\n")
        !           937: 
        !           938: DEFUN (match_tag, 
        !           939:        match_tag_cmd,
        !           940:        "match tag <0-65535>",
        !           941:        MATCH_STR
        !           942:        "Match tag of route\n"
        !           943:        "Metric value\n")
        !           944: {
        !           945:   return rip_route_match_add (vty, vty->index, "tag", argv[0]);
        !           946: }
        !           947: 
        !           948: DEFUN (no_match_tag,
        !           949:        no_match_tag_cmd,
        !           950:        "no match tag",
        !           951:        NO_STR
        !           952:        MATCH_STR
        !           953:        "Match tag of route\n")
        !           954: {
        !           955:   if (argc == 0)
        !           956:     return rip_route_match_delete (vty, vty->index, "tag", NULL);
        !           957: 
        !           958:   return rip_route_match_delete (vty, vty->index, "tag", argv[0]);
        !           959: }
        !           960: 
        !           961: ALIAS (no_match_tag,
        !           962:        no_match_tag_val_cmd,
        !           963:        "no match tag <0-65535>",
        !           964:        NO_STR
        !           965:        MATCH_STR
        !           966:        "Match tag of route\n"
        !           967:        "Metric value\n")
        !           968: 
        !           969: /* set functions */
        !           970: 
        !           971: DEFUN (set_metric,
        !           972:        set_metric_cmd,
        !           973:        "set metric <0-4294967295>",
        !           974:        SET_STR
        !           975:        "Metric value for destination routing protocol\n"
        !           976:        "Metric value\n")
        !           977: {
        !           978:   return rip_route_set_add (vty, vty->index, "metric", argv[0]);
        !           979: }
        !           980: 
        !           981: ALIAS (set_metric,
        !           982:        set_metric_addsub_cmd,
        !           983:        "set metric <+/-metric>",
        !           984:        SET_STR
        !           985:        "Metric value for destination routing protocol\n"
        !           986:        "Add or subtract metric\n")
        !           987: 
        !           988: DEFUN (no_set_metric,
        !           989:        no_set_metric_cmd,
        !           990:        "no set metric",
        !           991:        NO_STR
        !           992:        SET_STR
        !           993:        "Metric value for destination routing protocol\n")
        !           994: {
        !           995:   if (argc == 0)
        !           996:     return rip_route_set_delete (vty, vty->index, "metric", NULL);
        !           997: 
        !           998:   return rip_route_set_delete (vty, vty->index, "metric", argv[0]);
        !           999: }
        !          1000: 
        !          1001: ALIAS (no_set_metric,
        !          1002:        no_set_metric_val_cmd,
        !          1003:        "no set metric (<0-4294967295>|<+/-metric>)",
        !          1004:        NO_STR
        !          1005:        SET_STR
        !          1006:        "Metric value for destination routing protocol\n"
        !          1007:        "Metric value\n"
        !          1008:        "Add or subtract metric\n")
        !          1009: 
        !          1010: DEFUN (set_ip_nexthop,
        !          1011:        set_ip_nexthop_cmd,
        !          1012:        "set ip next-hop A.B.C.D",
        !          1013:        SET_STR
        !          1014:        IP_STR
        !          1015:        "Next hop address\n"
        !          1016:        "IP address of next hop\n")
        !          1017: {
        !          1018:   union sockunion su;
        !          1019:   int ret;
        !          1020: 
        !          1021:   ret = str2sockunion (argv[0], &su);
        !          1022:   if (ret < 0)
        !          1023:     {
        !          1024:       vty_out (vty, "%% Malformed next-hop address%s", VTY_NEWLINE);
        !          1025:       return CMD_WARNING;
        !          1026:     }
        !          1027: 
        !          1028:   return rip_route_set_add (vty, vty->index, "ip next-hop", argv[0]);
        !          1029: }
        !          1030: 
        !          1031: DEFUN (no_set_ip_nexthop,
        !          1032:        no_set_ip_nexthop_cmd,
        !          1033:        "no set ip next-hop",
        !          1034:        NO_STR
        !          1035:        SET_STR
        !          1036:        IP_STR
        !          1037:        "Next hop address\n")
        !          1038: {
        !          1039:   if (argc == 0)
        !          1040:     return rip_route_set_delete (vty, vty->index, "ip next-hop", NULL);
        !          1041:   
        !          1042:   return rip_route_set_delete (vty, vty->index, "ip next-hop", argv[0]);
        !          1043: }
        !          1044: 
        !          1045: ALIAS (no_set_ip_nexthop,
        !          1046:        no_set_ip_nexthop_val_cmd,
        !          1047:        "no set ip next-hop A.B.C.D",
        !          1048:        NO_STR
        !          1049:        SET_STR
        !          1050:        IP_STR
        !          1051:        "Next hop address\n"
        !          1052:        "IP address of next hop\n")
        !          1053: 
        !          1054: DEFUN (set_tag,
        !          1055:        set_tag_cmd,
        !          1056:        "set tag <0-65535>",
        !          1057:        SET_STR
        !          1058:        "Tag value for routing protocol\n"
        !          1059:        "Tag value\n")
        !          1060: {
        !          1061:   return rip_route_set_add (vty, vty->index, "tag", argv[0]);
        !          1062: }
        !          1063: 
        !          1064: DEFUN (no_set_tag,
        !          1065:        no_set_tag_cmd,
        !          1066:        "no set tag",
        !          1067:        NO_STR
        !          1068:        SET_STR
        !          1069:        "Tag value for routing protocol\n")
        !          1070: {
        !          1071:   if (argc == 0)
        !          1072:     return rip_route_set_delete (vty, vty->index, "tag", NULL);
        !          1073:   
        !          1074:   return rip_route_set_delete (vty, vty->index, "tag", argv[0]);
        !          1075: }
        !          1076: 
        !          1077: ALIAS (no_set_tag,
        !          1078:        no_set_tag_val_cmd,
        !          1079:        "no set tag <0-65535>",
        !          1080:        NO_STR
        !          1081:        SET_STR
        !          1082:        "Tag value for routing protocol\n"
        !          1083:        "Tag value\n")
        !          1084: 
        !          1085: void
        !          1086: rip_route_map_reset ()
        !          1087: {
        !          1088:   ;
        !          1089: }
        !          1090: 
        !          1091: /* Route-map init */
        !          1092: void
        !          1093: rip_route_map_init ()
        !          1094: {
        !          1095:   route_map_init ();
        !          1096:   route_map_init_vty ();
        !          1097:   route_map_add_hook (rip_route_map_update);
        !          1098:   route_map_delete_hook (rip_route_map_update);
        !          1099: 
        !          1100:   route_map_install_match (&route_match_metric_cmd);
        !          1101:   route_map_install_match (&route_match_interface_cmd);
        !          1102:   route_map_install_match (&route_match_ip_next_hop_cmd);
        !          1103:   route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
        !          1104:   route_map_install_match (&route_match_ip_address_cmd);
        !          1105:   route_map_install_match (&route_match_ip_address_prefix_list_cmd);
        !          1106:   route_map_install_match (&route_match_tag_cmd);
        !          1107: 
        !          1108:   route_map_install_set (&route_set_metric_cmd);
        !          1109:   route_map_install_set (&route_set_ip_nexthop_cmd);
        !          1110:   route_map_install_set (&route_set_tag_cmd);
        !          1111: 
        !          1112:   install_element (RMAP_NODE, &match_metric_cmd);
        !          1113:   install_element (RMAP_NODE, &no_match_metric_cmd);
        !          1114:   install_element (RMAP_NODE, &no_match_metric_val_cmd);
        !          1115:   install_element (RMAP_NODE, &match_interface_cmd);
        !          1116:   install_element (RMAP_NODE, &no_match_interface_cmd);
        !          1117:   install_element (RMAP_NODE, &no_match_interface_val_cmd);
        !          1118:   install_element (RMAP_NODE, &match_ip_next_hop_cmd);
        !          1119:   install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
        !          1120:   install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd);
        !          1121:   install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
        !          1122:   install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
        !          1123:   install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
        !          1124:   install_element (RMAP_NODE, &match_ip_address_cmd);
        !          1125:   install_element (RMAP_NODE, &no_match_ip_address_cmd);
        !          1126:   install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
        !          1127:   install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
        !          1128:   install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
        !          1129:   install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
        !          1130:   install_element (RMAP_NODE, &match_tag_cmd);
        !          1131:   install_element (RMAP_NODE, &no_match_tag_cmd);
        !          1132:   install_element (RMAP_NODE, &no_match_tag_val_cmd);
        !          1133: 
        !          1134:   install_element (RMAP_NODE, &set_metric_cmd);
        !          1135:   install_element (RMAP_NODE, &set_metric_addsub_cmd);
        !          1136:   install_element (RMAP_NODE, &no_set_metric_cmd);
        !          1137:   install_element (RMAP_NODE, &no_set_metric_val_cmd);
        !          1138:   install_element (RMAP_NODE, &set_ip_nexthop_cmd);
        !          1139:   install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
        !          1140:   install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd);
        !          1141:   install_element (RMAP_NODE, &set_tag_cmd);
        !          1142:   install_element (RMAP_NODE, &no_set_tag_cmd);
        !          1143:   install_element (RMAP_NODE, &no_set_tag_val_cmd);
        !          1144: }

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