Diff for /embedaddon/quagga/bgpd/bgp_routemap.c between versions 1.1 and 1.1.1.4

version 1.1, 2012/02/21 17:26:11 version 1.1.1.4, 2016/11/02 10:09:10
Line 93  o Cisco route-map Line 93  o Cisco route-map
       tag               :  (This will not be implemented by bgpd)        tag               :  (This will not be implemented by bgpd)
       weight            :  Done        weight            :  Done
   
o Local extentiono Local extensions
   
   set ipv6 next-hop global: Done    set ipv6 next-hop global: Done
   set ipv6 next-hop local : Done    set ipv6 next-hop local : Done
   set as-path exclude     : Done    set as-path exclude     : Done
   
 */   */ 
  /* generic value manipulation to be shared in multiple rules */
 
 #define RMAP_VALUE_SET 0
 #define RMAP_VALUE_ADD 1
 #define RMAP_VALUE_SUB 2
 
 struct rmap_value
 {
   u_int8_t action;
   u_int8_t variable;
   u_int32_t value;
 };
 
 static int
 route_value_match (struct rmap_value *rv, u_int32_t value)
 {
   if (rv->variable == 0 && value == rv->value)
     return RMAP_MATCH;
 
   return RMAP_NOMATCH;
 }
 
 static u_int32_t
 route_value_adjust (struct rmap_value *rv, u_int32_t current, struct peer *peer)
 {
   u_int32_t value;
 
   switch (rv->variable)
     {
     case 1:
       value = peer->rtt;
       break;
     default:
       value = rv->value;
       break;
     }
 
   switch (rv->action)
     {
     case RMAP_VALUE_ADD:
       if (current > UINT32_MAX-value)
         return UINT32_MAX;
       return current + value;
     case RMAP_VALUE_SUB:
       if (current <= value)
         return 0;
       return current - value;
     default:
       return value;
     }
 }
 
 static void *
 route_value_compile (const char *arg)
 {
   u_int8_t action = RMAP_VALUE_SET, var = 0;
   unsigned long larg = 0;
   char *endptr = NULL;
   struct rmap_value *rv;
 
   if (arg[0] == '+')
     {
       action = RMAP_VALUE_ADD;
       arg++;
     }
   else if (arg[0] == '-')
     {
       action = RMAP_VALUE_SUB;
       arg++;
     }
 
   if (all_digit(arg))
     {
       errno = 0;
       larg = strtoul (arg, &endptr, 10);
       if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
         return NULL;
     }
   else
     {
       if (strcmp(arg, "rtt") == 0)
         var = 1;
       else
         return NULL;
     }
 
   rv = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
   if (!rv)
     return NULL;
 
   rv->action = action;
   rv->variable = var;
   rv->value = larg;
   return rv;
 }
 
 static void
 route_value_free (void *rule)
 {
   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 }
 
  /* generic as path object to be shared in multiple rules */
 
 static void *
 route_aspath_compile (const char *arg)
 {
   struct aspath *aspath;
 
   aspath = aspath_str2aspath (arg);
   if (! aspath)
     return NULL;
   return aspath;
 }
 
 static void
 route_aspath_free (void *rule)
 {
   struct aspath *aspath = rule;
   aspath_free (aspath);
 }
 
  /* 'match peer (A.B.C.D|X:X::X:X)' */   /* 'match peer (A.B.C.D|X:X::X:X)' */
   
 /* Compares the peer specified in the 'match peer' clause with the peer  /* Compares the peer specified in the 'match peer' clause with the peer
Line 111  route_match_peer (void *rule, struct prefix *prefix, r Line 233  route_match_peer (void *rule, struct prefix *prefix, r
       void *object)        void *object)
 {  {
   union sockunion *su;    union sockunion *su;
  union sockunion *su2;  union sockunion su_def = { .sin = { .sin_family = AF_INET,
                                       .sin_addr.s_addr = INADDR_ANY } };
   struct peer_group *group;    struct peer_group *group;
   struct peer *peer;    struct peer *peer;
   struct listnode *node, *nnode;    struct listnode *node, *nnode;
Line 127  route_match_peer (void *rule, struct prefix *prefix, r Line 250  route_match_peer (void *rule, struct prefix *prefix, r
   
       /* If su='0.0.0.0' (command 'match peer local'), and it's a NETWORK,        /* If su='0.0.0.0' (command 'match peer local'), and it's a NETWORK,
           REDISTRIBUTE or DEFAULT_GENERATED route => return RMAP_MATCH */            REDISTRIBUTE or DEFAULT_GENERATED route => return RMAP_MATCH */
      su2 = sockunion_str2su ("0.0.0.0");      if (sockunion_same (su, &su_def))
      if ( sockunion_same (su, su2) ) 
         {          {
           int ret;            int ret;
           if ( CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_NETWORK) ||            if ( CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_NETWORK) ||
Line 137  route_match_peer (void *rule, struct prefix *prefix, r Line 259  route_match_peer (void *rule, struct prefix *prefix, r
             ret = RMAP_MATCH;              ret = RMAP_MATCH;
           else            else
             ret = RMAP_NOMATCH;              ret = RMAP_NOMATCH;
             
           sockunion_free (su2);  
           return ret;            return ret;
         }          }
      sockunion_free (su2);
       
       if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))        if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
         {          {
           if (sockunion_same (su, &peer->su))            if (sockunion_same (su, &peer->su))
Line 172  route_match_peer_compile (const char *arg) Line 291  route_match_peer_compile (const char *arg)
   
   su = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union sockunion));    su = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (union sockunion));
   
  ret = str2sockunion ( (arg)? arg : "0.0.0.0", su);  ret = str2sockunion (strcmp(arg, "local") ? arg : "0.0.0.0", su);
   if (ret < 0) {    if (ret < 0) {
     XFREE (MTYPE_ROUTE_MAP_COMPILED, su);      XFREE (MTYPE_ROUTE_MAP_COMPILED, su);
     return NULL;      return NULL;
Line 243  struct route_map_rule_cmd route_match_ip_address_cmd = Line 362  struct route_map_rule_cmd route_match_ip_address_cmd =
   route_match_ip_address_compile,    route_match_ip_address_compile,
   route_match_ip_address_free    route_match_ip_address_free
 };  };
 /* `match ip next-hop IP_ADDRESS' */  /* `match ip next-hop IP_ADDRESS' */
   
 /* Match function return 1 if match is success else return zero. */  /* Match function return 1 if match is success else return zero. */
Line 295  struct route_map_rule_cmd route_match_ip_next_hop_cmd  Line 414  struct route_map_rule_cmd route_match_ip_next_hop_cmd 
   route_match_ip_next_hop_compile,    route_match_ip_next_hop_compile,
   route_match_ip_next_hop_free    route_match_ip_next_hop_free
 };  };
 /* `match ip route-source ACCESS-LIST' */  /* `match ip route-source ACCESS-LIST' */
   
 /* Match function return 1 if match is success else return zero. */  /* Match function return 1 if match is success else return zero. */
Line 353  struct route_map_rule_cmd route_match_ip_route_source_ Line 472  struct route_map_rule_cmd route_match_ip_route_source_
   route_match_ip_route_source_compile,    route_match_ip_route_source_compile,
   route_match_ip_route_source_free    route_match_ip_route_source_free
 };  };
 /* `match ip address prefix-list PREFIX_LIST' */  /* `match ip address prefix-list PREFIX_LIST' */
   
 static route_map_result_t  static route_map_result_t
Line 393  struct route_map_rule_cmd route_match_ip_address_prefi Line 512  struct route_map_rule_cmd route_match_ip_address_prefi
   route_match_ip_address_prefix_list_compile,    route_match_ip_address_prefix_list_compile,
   route_match_ip_address_prefix_list_free    route_match_ip_address_prefix_list_free
 };  };
 /* `match ip next-hop prefix-list PREFIX_LIST' */  /* `match ip next-hop prefix-list PREFIX_LIST' */
   
 static route_map_result_t  static route_map_result_t
Line 440  struct route_map_rule_cmd route_match_ip_next_hop_pref Line 559  struct route_map_rule_cmd route_match_ip_next_hop_pref
   route_match_ip_next_hop_prefix_list_compile,    route_match_ip_next_hop_prefix_list_compile,
   route_match_ip_next_hop_prefix_list_free    route_match_ip_next_hop_prefix_list_free
 };  };
 /* `match ip route-source prefix-list PREFIX_LIST' */  /* `match ip route-source prefix-list PREFIX_LIST' */
   
 static route_map_result_t  static route_map_result_t
Line 493  struct route_map_rule_cmd route_match_ip_route_source_ Line 612  struct route_map_rule_cmd route_match_ip_route_source_
   route_match_ip_route_source_prefix_list_compile,    route_match_ip_route_source_prefix_list_compile,
   route_match_ip_route_source_prefix_list_free    route_match_ip_route_source_prefix_list_free
 };  };
 /* `match metric METRIC' */  /* `match metric METRIC' */
   
 /* Match function return 1 if match is success else return zero. */  /* Match function return 1 if match is success else return zero. */
Line 501  static route_map_result_t Line 620  static route_map_result_t
 route_match_metric (void *rule, struct prefix *prefix,   route_match_metric (void *rule, struct prefix *prefix, 
                     route_map_object_t type, void *object)                      route_map_object_t type, void *object)
 {  {
  u_int32_t *med;  struct rmap_value *rv;
   struct bgp_info *bgp_info;    struct bgp_info *bgp_info;
   
   if (type == RMAP_BGP)    if (type == RMAP_BGP)
     {      {
      med = rule;      rv = rule;
       bgp_info = object;        bgp_info = object;
          return route_value_match(rv, bgp_info->attr->med);
      if (bgp_info->attr->med == *med) 
        return RMAP_MATCH; 
      else 
        return RMAP_NOMATCH; 
     }      }
   return RMAP_NOMATCH;    return RMAP_NOMATCH;
 }  }
   
 /* Route map `match metric' match statement. `arg' is MED value */  
 static void *  
 route_match_metric_compile (const char *arg)  
 {  
   u_int32_t *med;  
   char *endptr = NULL;  
   unsigned long tmpval;  
   
   tmpval = strtoul (arg, &endptr, 10);  
   if (*endptr != '\0' || tmpval == ULONG_MAX || tmpval > UINT32_MAX)  
     return NULL;  
       
   med = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));  
     
   if (!med)  
     return med;  
     
   *med = tmpval;  
   return med;  
 }  
   
 /* Free route map's compiled `match metric' value. */  
 static void  
 route_match_metric_free (void *rule)  
 {  
   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);  
 }  
   
 /* Route map commands for metric matching. */  /* Route map commands for metric matching. */
 struct route_map_rule_cmd route_match_metric_cmd =  struct route_map_rule_cmd route_match_metric_cmd =
 {  {
   "metric",    "metric",
   route_match_metric,    route_match_metric,
  route_match_metric_compile,  route_value_compile,
  route_match_metric_free  route_value_free,
 };  };
 /* `match as-path ASPATH' */  /* `match as-path ASPATH' */
   
 /* Match function for as-path match.  I assume given object is */  /* Match function for as-path match.  I assume given object is */
Line 601  struct route_map_rule_cmd route_match_aspath_cmd =  Line 688  struct route_map_rule_cmd route_match_aspath_cmd = 
   route_match_aspath_compile,    route_match_aspath_compile,
   route_match_aspath_free    route_match_aspath_free
 };  };
 /* `match community COMMUNIY' */  /* `match community COMMUNIY' */
 struct rmap_community  struct rmap_community
 {  {
Line 685  struct route_map_rule_cmd route_match_community_cmd =  Line 772  struct route_map_rule_cmd route_match_community_cmd = 
   route_match_community_compile,    route_match_community_compile,
   route_match_community_free    route_match_community_free
 };  };
 /* Match function for extcommunity match. */  /* Match function for extcommunity match. */
 static route_map_result_t  static route_map_result_t
 route_match_ecommunity (void *rule, struct prefix *prefix,   route_match_ecommunity (void *rule, struct prefix *prefix, 
Line 734  struct route_map_rule_cmd route_match_ecommunity_cmd = Line 821  struct route_map_rule_cmd route_match_ecommunity_cmd =
   route_match_ecommunity_compile,    route_match_ecommunity_compile,
   route_match_ecommunity_free    route_match_ecommunity_free
 };  };
 /* `match nlri` and `set nlri` are replaced by `address-family ipv4`  /* `match nlri` and `set nlri` are replaced by `address-family ipv4`
    and `address-family vpnv4'.  */     and `address-family vpnv4'.  */
 /* `match origin' */  /* `match origin' */
 static route_map_result_t  static route_map_result_t
 route_match_origin (void *rule, struct prefix *prefix,   route_match_origin (void *rule, struct prefix *prefix, 
Line 790  struct route_map_rule_cmd route_match_origin_cmd = Line 877  struct route_map_rule_cmd route_match_origin_cmd =
   route_match_origin_compile,    route_match_origin_compile,
   route_match_origin_free    route_match_origin_free
 };  };
   
   /* match probability  { */
   
   static route_map_result_t
   route_match_probability (void *rule, struct prefix *prefix,
                       route_map_object_t type, void *object)
   {
     long r = random();
   
     switch (*(long *) rule)
     {
       case 0: break;
       case RAND_MAX: return RMAP_MATCH;
       default:
         if (r < *(long *) rule)
           {
             return RMAP_MATCH;
           }
     }
   
     return RMAP_NOMATCH;
   }
   
   static void *
   route_match_probability_compile (const char *arg)
   {
     long *lobule;
     unsigned  perc;
   
     perc    = atoi (arg);
     lobule  = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (long));
   
     switch (perc)
       {
         case 0:   *lobule = 0; break;
         case 100: *lobule = RAND_MAX; break;
         default:  *lobule = RAND_MAX / 100 * perc;
       }
   
     return lobule;
   }
   
   static void
   route_match_probability_free (void *rule)
   {
     XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
   }
   
   struct route_map_rule_cmd route_match_probability_cmd =
   {
     "probability",
     route_match_probability,
     route_match_probability_compile,
     route_match_probability_free
   };
   
   /* } */
   
 /* `set ip next-hop IP_ADDRESS' */  /* `set ip next-hop IP_ADDRESS' */
   
 /* Set nexthop to object.  ojbect must be pointer to struct attr. */  /* Set nexthop to object.  ojbect must be pointer to struct attr. */
Line 804  route_set_ip_nexthop (void *rule, struct prefix *prefi Line 949  route_set_ip_nexthop (void *rule, struct prefix *prefi
                       route_map_object_t type, void *object)                        route_map_object_t type, void *object)
 {  {
   struct rmap_ip_nexthop_set *rins = rule;    struct rmap_ip_nexthop_set *rins = rule;
   struct in_addr peer_address;  
   struct bgp_info *bgp_info;    struct bgp_info *bgp_info;
   struct peer *peer;    struct peer *peer;
   
Line 820  route_set_ip_nexthop (void *rule, struct prefix *prefi Line 964  route_set_ip_nexthop (void *rule, struct prefix *prefi
               && peer->su_remote                 && peer->su_remote 
               && sockunion_family (peer->su_remote) == AF_INET)                && sockunion_family (peer->su_remote) == AF_INET)
             {              {
              inet_aton (sockunion_su2str (peer->su_remote), &peer_address);              bgp_info->attr->nexthop.s_addr = sockunion2ip (peer->su_remote);
              bgp_info->attr->nexthop = peer_address; 
               bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);                bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
             }              }
           else if (CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT)            else if (CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT)
                    && peer->su_local                     && peer->su_local
                    && sockunion_family (peer->su_local) == AF_INET)                     && sockunion_family (peer->su_local) == AF_INET)
             {              {
              inet_aton (sockunion_su2str (peer->su_local), &peer_address);              bgp_info->attr->nexthop.s_addr = sockunion2ip (peer->su_local);
              bgp_info->attr->nexthop = peer_address; 
               bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);                bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
             }              }
         }          }
Line 896  struct route_map_rule_cmd route_set_ip_nexthop_cmd = Line 1038  struct route_map_rule_cmd route_set_ip_nexthop_cmd =
   route_set_ip_nexthop_compile,    route_set_ip_nexthop_compile,
   route_set_ip_nexthop_free    route_set_ip_nexthop_free
 };  };
 /* `set local-preference LOCAL_PREF' */  /* `set local-preference LOCAL_PREF' */
   
 /* Set local preference. */  /* Set local preference. */
Line 904  static route_map_result_t Line 1046  static route_map_result_t
 route_set_local_pref (void *rule, struct prefix *prefix,  route_set_local_pref (void *rule, struct prefix *prefix,
                       route_map_object_t type, void *object)                        route_map_object_t type, void *object)
 {  {
  u_int32_t *local_pref;  struct rmap_value *rv;
   struct bgp_info *bgp_info;    struct bgp_info *bgp_info;
     u_int32_t locpref = 0;
   
   if (type == RMAP_BGP)    if (type == RMAP_BGP)
     {      {
       /* Fetch routemap's rule information. */        /* Fetch routemap's rule information. */
      local_pref = rule;      rv = rule;
       bgp_info = object;        bgp_info = object;
           
       /* Set local preference value. */         /* Set local preference value. */ 
         if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
           locpref = bgp_info->attr->local_pref;
   
       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);        bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
      bgp_info->attr->local_pref = *local_pref;      bgp_info->attr->local_pref = route_value_adjust(rv, locpref, bgp_info->peer);
     }      }
   
   return RMAP_OKAY;    return RMAP_OKAY;
 }  }
   
 /* set local preference compilation. */  
 static void *  
 route_set_local_pref_compile (const char *arg)  
 {  
   unsigned long tmp;  
   u_int32_t *local_pref;  
   char *endptr = NULL;  
   
   /* Local preference value shoud be integer. */  
   if (! all_digit (arg))  
     return NULL;  
     
   tmp = strtoul (arg, &endptr, 10);  
   if (*endptr != '\0' || tmp == ULONG_MAX || tmp > UINT32_MAX)  
     return NULL;  
      
   local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));   
     
   if (!local_pref)  
     return local_pref;  
     
   *local_pref = tmp;  
     
   return local_pref;  
 }  
   
 /* Free route map's local preference value. */  
 static void  
 route_set_local_pref_free (void *rule)  
 {  
   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);  
 }  
   
 /* Set local preference rule structure. */  /* Set local preference rule structure. */
 struct route_map_rule_cmd route_set_local_pref_cmd =   struct route_map_rule_cmd route_set_local_pref_cmd = 
 {  {
   "local-preference",    "local-preference",
   route_set_local_pref,    route_set_local_pref,
  route_set_local_pref_compile,  route_value_compile,
  route_set_local_pref_free,  route_value_free,
 };  };
 /* `set weight WEIGHT' */  /* `set weight WEIGHT' */
   
 /* Set weight. */  /* Set weight. */
Line 970  static route_map_result_t Line 1083  static route_map_result_t
 route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,  route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
                   void *object)                    void *object)
 {  {
  u_int32_t *weight;  struct rmap_value *rv;
   struct bgp_info *bgp_info;    struct bgp_info *bgp_info;
     u_int32_t weight;
   
   if (type == RMAP_BGP)    if (type == RMAP_BGP)
     {      {
       /* Fetch routemap's rule information. */        /* Fetch routemap's rule information. */
      weight = rule;      rv = rule;
       bgp_info = object;        bgp_info = object;
           
       /* Set weight value. */         /* Set weight value. */ 
      if (*weight)      weight = route_value_adjust(rv, 0, bgp_info->peer);
        (bgp_attr_extra_get (bgp_info->attr))->weight = *weight;      if (weight)
         (bgp_attr_extra_get (bgp_info->attr))->weight = weight;
       else if (bgp_info->attr->extra)        else if (bgp_info->attr->extra)
         bgp_info->attr->extra->weight = 0;          bgp_info->attr->extra->weight = 0;
     }      }
Line 989  route_set_weight (void *rule, struct prefix *prefix, r Line 1104  route_set_weight (void *rule, struct prefix *prefix, r
   return RMAP_OKAY;    return RMAP_OKAY;
 }  }
   
 /* set local preference compilation. */  
 static void *  
 route_set_weight_compile (const char *arg)  
 {  
   unsigned long tmp;  
   u_int32_t *weight;  
   char *endptr = NULL;  
   
   /* Local preference value shoud be integer. */  
   if (! all_digit (arg))  
     return NULL;  
   
   
   tmp = strtoul (arg, &endptr, 10);  
   if (*endptr != '\0' || tmp == ULONG_MAX || tmp > UINT32_MAX)  
     return NULL;  
     
   weight = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));  
     
   if (weight == NULL)  
     return weight;  
     
   *weight = tmp;    
     
   return weight;  
 }  
   
 /* Free route map's local preference value. */  
 static void  
 route_set_weight_free (void *rule)  
 {  
   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);  
 }  
   
 /* Set local preference rule structure. */  /* Set local preference rule structure. */
 struct route_map_rule_cmd route_set_weight_cmd =   struct route_map_rule_cmd route_set_weight_cmd = 
 {  {
   "weight",    "weight",
   route_set_weight,    route_set_weight,
  route_set_weight_compile,  route_value_compile,
  route_set_weight_free,  route_value_free,
 };  };
 /* `set metric METRIC' */  /* `set metric METRIC' */
   
 /* Set metric to attribute. */  /* Set metric to attribute. */
Line 1039  static route_map_result_t Line 1120  static route_map_result_t
 route_set_metric (void *rule, struct prefix *prefix,   route_set_metric (void *rule, struct prefix *prefix, 
                   route_map_object_t type, void *object)                    route_map_object_t type, void *object)
 {  {
  char *metric;  struct rmap_value *rv;
  u_int32_t metric_val; 
   struct bgp_info *bgp_info;    struct bgp_info *bgp_info;
     u_int32_t med = 0;
   
   if (type == RMAP_BGP)    if (type == RMAP_BGP)
     {      {
       /* Fetch routemap's rule information. */        /* Fetch routemap's rule information. */
      metric = rule;      rv = rule;
       bgp_info = object;        bgp_info = object;
   
      if (! (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)))      if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
        bgp_info->attr->med = 0;        med = bgp_info->attr->med;
      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); 
   
      if (all_digit (metric))      bgp_info->attr->med = route_value_adjust(rv, med, bgp_info->peer);
        {      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
          metric_val = strtoul (metric, (char **)NULL, 10); 
          bgp_info->attr->med = metric_val; 
        } 
      else 
        { 
          metric_val = strtoul (metric+1, (char **)NULL, 10); 
 
          if (strncmp (metric, "+", 1) == 0) 
            { 
              if (bgp_info->attr->med/2 + metric_val/2 > BGP_MED_MAX/2) 
                bgp_info->attr->med = BGP_MED_MAX - 1; 
              else 
                bgp_info->attr->med += metric_val; 
            } 
          else if (strncmp (metric, "-", 1) == 0) 
            { 
              if (bgp_info->attr->med <= metric_val) 
                bgp_info->attr->med = 0; 
              else 
                bgp_info->attr->med -= metric_val; 
            } 
        } 
     }      }
   return RMAP_OKAY;    return RMAP_OKAY;
 }  }
   
 /* set metric compilation. */  
 static void *  
 route_set_metric_compile (const char *arg)  
 {  
   u_int32_t metric;  
   unsigned long larg;  
   char *endptr = NULL;  
   
   if (all_digit (arg))  
     {  
       /* set metric value check*/  
       larg = strtoul (arg, &endptr, 10);  
       if (*endptr != '\0' || larg == ULONG_MAX || larg > UINT32_MAX)  
         return NULL;  
       metric = larg;  
     }  
   else  
     {  
       /* set metric +/-value check */  
       if ((strncmp (arg, "+", 1) != 0  
            && strncmp (arg, "-", 1) != 0)  
            || (! all_digit (arg+1)))  
         return NULL;  
   
       larg = strtoul (arg+1, &endptr, 10);  
       if (*endptr != '\0' || larg == ULONG_MAX || larg > UINT32_MAX)  
         return NULL;  
       metric = larg;  
     }  
   
   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);  
 }  
   
 /* Free route map's compiled `set metric' value. */  
 static void  
 route_set_metric_free (void *rule)  
 {  
   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);  
 }  
   
 /* Set metric rule structure. */  /* Set metric rule structure. */
 struct route_map_rule_cmd route_set_metric_cmd =   struct route_map_rule_cmd route_set_metric_cmd = 
 {  {
   "metric",    "metric",
   route_set_metric,    route_set_metric,
  route_set_metric_compile,  route_value_compile,
  route_set_metric_free,  route_value_free,
 };  };
 /* `set as-path prepend ASPATH' */  /* `set as-path prepend ASPATH' */
   
 /* For AS path prepend mechanism. */  /* For AS path prepend mechanism. */
Line 1142  route_set_aspath_prepend (void *rule, struct prefix *p Line 1160  route_set_aspath_prepend (void *rule, struct prefix *p
   
   if (type == RMAP_BGP)    if (type == RMAP_BGP)
     {      {
       aspath = rule;  
       binfo = object;        binfo = object;
           
       if (binfo->attr->aspath->refcnt)        if (binfo->attr->aspath->refcnt)
Line 1150  route_set_aspath_prepend (void *rule, struct prefix *p Line 1167  route_set_aspath_prepend (void *rule, struct prefix *p
       else        else
         new = binfo->attr->aspath;          new = binfo->attr->aspath;
   
      aspath_prepend (aspath, new);      if ((uintptr_t)rule > 10)
       {
         aspath = rule;
         aspath_prepend (aspath, new);
       }
       else
       {
         as_t as = aspath_leftmost(new);
         if (!as) as = binfo->peer->as;
         new = aspath_add_seq_n (new, as, (uintptr_t) rule);
       }
 
       binfo->attr->aspath = new;        binfo->attr->aspath = new;
     }      }
   
   return RMAP_OKAY;    return RMAP_OKAY;
 }  }
   
 /* Compile function for as-path prepend. */  
 static void *  static void *
 route_set_aspath_prepend_compile (const char *arg)  route_set_aspath_prepend_compile (const char *arg)
 {  {
  struct aspath *aspath;  unsigned int num;
   
  aspath = aspath_str2aspath (arg);  if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num < 10)
  if (! aspath)    return (void*)(uintptr_t)num;
    return NULL;
  return aspath;  return route_aspath_compile(arg);
 }  }
   
 /* Compile function for as-path prepend. */  
 static void  static void
 route_set_aspath_prepend_free (void *rule)  route_set_aspath_prepend_free (void *rule)
 {  {
  struct aspath *aspath = rule;  if ((uintptr_t)rule > 10)
  aspath_free (aspath);    route_aspath_free(rule);
 }  }
   
/* Set metric rule structure. */
 /* Set as-path prepend rule structure. */
 struct route_map_rule_cmd route_set_aspath_prepend_cmd =   struct route_map_rule_cmd route_set_aspath_prepend_cmd = 
 {  {
   "as-path prepend",    "as-path prepend",
Line 1185  struct route_map_rule_cmd route_set_aspath_prepend_cmd Line 1212  struct route_map_rule_cmd route_set_aspath_prepend_cmd
   route_set_aspath_prepend_compile,    route_set_aspath_prepend_compile,
   route_set_aspath_prepend_free,    route_set_aspath_prepend_free,
 };  };
 /* `set as-path exclude ASn' */  /* `set as-path exclude ASn' */
   
 /* For ASN exclude mechanism.  /* For ASN exclude mechanism.
Line 1211  route_set_aspath_exclude (void *rule, struct prefix *d Line 1238  route_set_aspath_exclude (void *rule, struct prefix *d
   return RMAP_OKAY;    return RMAP_OKAY;
 }  }
   
 /* FIXME: consider using route_set_aspath_prepend_compile() and  
  * route_set_aspath_prepend_free(), which two below function are  
  * exact clones of.  
  */  
   
 /* Compile function for as-path exclude. */  
 static void *  
 route_set_aspath_exclude_compile (const char *arg)  
 {  
   struct aspath *aspath;  
   
   aspath = aspath_str2aspath (arg);  
   if (! aspath)  
     return NULL;  
   return aspath;  
 }  
   
 static void  
 route_set_aspath_exclude_free (void *rule)  
 {  
   struct aspath *aspath = rule;  
   aspath_free (aspath);  
 }  
   
 /* Set ASn exlude rule structure. */  /* Set ASn exlude rule structure. */
 struct route_map_rule_cmd route_set_aspath_exclude_cmd =   struct route_map_rule_cmd route_set_aspath_exclude_cmd = 
 {  {
   "as-path exclude",    "as-path exclude",
   route_set_aspath_exclude,    route_set_aspath_exclude,
  route_set_aspath_exclude_compile,  route_aspath_compile,
  route_set_aspath_exclude_free,  route_aspath_free,
 };  };
 /* `set community COMMUNITY' */  /* `set community COMMUNITY' */
 struct rmap_com_set  struct rmap_com_set
 {  {
Line 1276  route_set_community (void *rule, struct prefix *prefix Line 1279  route_set_community (void *rule, struct prefix *prefix
         {          {
           attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));            attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
           attr->community = NULL;            attr->community = NULL;
             /* See the longer comment down below. */
             if (old && old->refcnt == 0)
               community_free(old);
           return RMAP_OKAY;            return RMAP_OKAY;
         }          }
   
Line 1364  struct route_map_rule_cmd route_set_community_cmd =  Line 1370  struct route_map_rule_cmd route_set_community_cmd = 
   route_set_community_compile,    route_set_community_compile,
   route_set_community_free,    route_set_community_free,
 };  };
 /* `set comm-list (<1-99>|<100-500>|WORD) delete' */  /* `set comm-list (<1-99>|<100-500>|WORD) delete' */
   
 /* For community set mechanism. */  /* For community set mechanism. */
Line 1453  struct route_map_rule_cmd route_set_community_delete_c Line 1459  struct route_map_rule_cmd route_set_community_delete_c
   route_set_community_delete_compile,    route_set_community_delete_compile,
   route_set_community_delete_free,    route_set_community_delete_free,
 };  };
 /* `set extcommunity rt COMMUNITY' */  /* `set extcommunity rt COMMUNITY' */
   
/* For community set mechanism. *//* For community set mechanism.  Used by _rt and _soo. */
 static route_map_result_t  static route_map_result_t
route_set_ecommunity_rt (void *rule, struct prefix *prefix, route_set_ecommunity (void *rule, struct prefix *prefix,
                         route_map_object_t type, void *object)                      route_map_object_t type, void *object)
 {  {
   struct ecommunity *ecom;    struct ecommunity *ecom;
   struct ecommunity *new_ecom;    struct ecommunity *new_ecom;
Line 1478  route_set_ecommunity_rt (void *rule, struct prefix *pr Line 1484  route_set_ecommunity_rt (void *rule, struct prefix *pr
       old_ecom = (bgp_attr_extra_get (bgp_info->attr))->ecommunity;        old_ecom = (bgp_attr_extra_get (bgp_info->attr))->ecommunity;
   
       if (old_ecom)        if (old_ecom)
        new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);        {
           new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);
 
           /* old_ecom->refcnt = 1 => owned elsewhere, e.g. bgp_update_receive()
            *         ->refcnt = 0 => set by a previous route-map statement */
           if (!old_ecom->refcnt)
             ecommunity_free (&old_ecom);
         }
       else        else
         new_ecom = ecommunity_dup (ecom);          new_ecom = ecommunity_dup (ecom);
   
      bgp_info->attr->extra->ecommunity = ecommunity_intern (new_ecom);      /* will be intern()'d or attr_flush()'d by bgp_update_main() */
       bgp_info->attr->extra->ecommunity = new_ecom;
   
       if (old_ecom)  
         ecommunity_unintern (&old_ecom);  
   
       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);        bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
     }      }
   return RMAP_OKAY;    return RMAP_OKAY;
Line 1504  route_set_ecommunity_rt_compile (const char *arg) Line 1515  route_set_ecommunity_rt_compile (const char *arg)
   return ecommunity_intern (ecom);    return ecommunity_intern (ecom);
 }  }
   
/* Free function for set community. *//* Free function for set community.  Used by _rt and _soo */
 static void  static void
route_set_ecommunity_rt_free (void *rule)route_set_ecommunity_free (void *rule)
 {  {
   struct ecommunity *ecom = rule;    struct ecommunity *ecom = rule;
   ecommunity_unintern (&ecom);    ecommunity_unintern (&ecom);
Line 1516  route_set_ecommunity_rt_free (void *rule) Line 1527  route_set_ecommunity_rt_free (void *rule)
 struct route_map_rule_cmd route_set_ecommunity_rt_cmd =   struct route_map_rule_cmd route_set_ecommunity_rt_cmd = 
 {  {
   "extcommunity rt",    "extcommunity rt",
  route_set_ecommunity_rt,  route_set_ecommunity,
   route_set_ecommunity_rt_compile,    route_set_ecommunity_rt_compile,
  route_set_ecommunity_rt_free,  route_set_ecommunity_free,
 };  };
   
 /* `set extcommunity soo COMMUNITY' */  /* `set extcommunity soo COMMUNITY' */
   
 /* For community set mechanism. */  
 static route_map_result_t  
 route_set_ecommunity_soo (void *rule, struct prefix *prefix,   
                          route_map_object_t type, void *object)  
 {  
   struct ecommunity *ecom, *old_ecom, *new_ecom;  
   struct bgp_info *bgp_info;  
   
   if (type == RMAP_BGP)  
     {  
       ecom = rule;  
       bgp_info = object;  
       
       if (! ecom)  
         return RMAP_OKAY;  
       
       old_ecom = (bgp_attr_extra_get (bgp_info->attr))->ecommunity;  
         
       if (old_ecom)  
         new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);  
       else  
         new_ecom = ecommunity_dup (ecom);  
   
       bgp_info->attr->extra->ecommunity = ecommunity_intern (new_ecom);  
   
       if (old_ecom)  
         ecommunity_unintern (&old_ecom);  
   
       bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);  
     }  
   return RMAP_OKAY;  
 }  
   
 /* Compile function for set community. */  /* Compile function for set community. */
 static void *  static void *
 route_set_ecommunity_soo_compile (const char *arg)  route_set_ecommunity_soo_compile (const char *arg)
Line 1569  route_set_ecommunity_soo_compile (const char *arg) Line 1547  route_set_ecommunity_soo_compile (const char *arg)
   return ecommunity_intern (ecom);    return ecommunity_intern (ecom);
 }  }
   
 /* Free function for set community. */  
 static void  
 route_set_ecommunity_soo_free (void *rule)  
 {  
   struct ecommunity *ecom = rule;  
   ecommunity_unintern (&ecom);  
 }  
   
 /* Set community rule structure. */  /* Set community rule structure. */
 struct route_map_rule_cmd route_set_ecommunity_soo_cmd =   struct route_map_rule_cmd route_set_ecommunity_soo_cmd = 
 {  {
   "extcommunity soo",    "extcommunity soo",
  route_set_ecommunity_soo,  route_set_ecommunity,
   route_set_ecommunity_soo_compile,    route_set_ecommunity_soo_compile,
  route_set_ecommunity_soo_free,  route_set_ecommunity_free,
 };  };
 /* `set origin ORIGIN' */  /* `set origin ORIGIN' */
   
 /* For origin set. */  /* For origin set. */
Line 1631  route_set_origin_free (void *rule) Line 1601  route_set_origin_free (void *rule)
   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);    XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 }  }
   
/* Set metric rule structure. *//* Set origin rule structure. */
 struct route_map_rule_cmd route_set_origin_cmd =   struct route_map_rule_cmd route_set_origin_cmd = 
 {  {
   "origin",    "origin",
Line 1639  struct route_map_rule_cmd route_set_origin_cmd =  Line 1609  struct route_map_rule_cmd route_set_origin_cmd = 
   route_set_origin_compile,    route_set_origin_compile,
   route_set_origin_free,    route_set_origin_free,
 };  };
 /* `set atomic-aggregate' */  /* `set atomic-aggregate' */
   
 /* For atomic aggregate set. */  /* For atomic aggregate set. */
Line 1680  struct route_map_rule_cmd route_set_atomic_aggregate_c Line 1650  struct route_map_rule_cmd route_set_atomic_aggregate_c
   route_set_atomic_aggregate_compile,    route_set_atomic_aggregate_compile,
   route_set_atomic_aggregate_free,    route_set_atomic_aggregate_free,
 };  };
 /* `set aggregator as AS A.B.C.D' */  /* `set aggregator as AS A.B.C.D' */
 struct aggregator  struct aggregator
 {  {
Line 1739  struct route_map_rule_cmd route_set_aggregator_as_cmd  Line 1709  struct route_map_rule_cmd route_set_aggregator_as_cmd 
   route_set_aggregator_as_compile,    route_set_aggregator_as_compile,
   route_set_aggregator_as_free,    route_set_aggregator_as_free,
 };  };
#ifdef HAVE_IPV6 
 /* `match ipv6 address IP_ACCESS_LIST' */  /* `match ipv6 address IP_ACCESS_LIST' */
   
 static route_map_result_t  static route_map_result_t
Line 1781  struct route_map_rule_cmd route_match_ipv6_address_cmd Line 1750  struct route_map_rule_cmd route_match_ipv6_address_cmd
   route_match_ipv6_address_compile,    route_match_ipv6_address_compile,
   route_match_ipv6_address_free    route_match_ipv6_address_free
 };  };
 /* `match ipv6 next-hop IP_ADDRESS' */  /* `match ipv6 next-hop IP_ADDRESS' */
   
 static route_map_result_t  static route_map_result_t
 route_match_ipv6_next_hop (void *rule, struct prefix *prefix,   route_match_ipv6_next_hop (void *rule, struct prefix *prefix, 
                            route_map_object_t type, void *object)                             route_map_object_t type, void *object)
 {  {
  struct in6_addr *addr;  struct in6_addr *addr = rule;
   struct bgp_info *bgp_info;    struct bgp_info *bgp_info;
   
   if (type == RMAP_BGP)    if (type == RMAP_BGP)
     {      {
       addr = rule;  
       bgp_info = object;        bgp_info = object;
               
       if (!bgp_info->attr->extra)        if (!bgp_info->attr->extra)
         return RMAP_NOMATCH;          return RMAP_NOMATCH;
               
      if (IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_global, rule))      if (IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_global, addr))
         return RMAP_MATCH;          return RMAP_MATCH;
   
       if (bgp_info->attr->extra->mp_nexthop_len == 32 &&        if (bgp_info->attr->extra->mp_nexthop_len == 32 &&
          IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_local, rule))          IPV6_ADDR_SAME (&bgp_info->attr->extra->mp_nexthop_local, addr))
         return RMAP_MATCH;          return RMAP_MATCH;
   
       return RMAP_NOMATCH;        return RMAP_NOMATCH;
Line 1843  struct route_map_rule_cmd route_match_ipv6_next_hop_cm Line 1811  struct route_map_rule_cmd route_match_ipv6_next_hop_cm
   route_match_ipv6_next_hop_compile,    route_match_ipv6_next_hop_compile,
   route_match_ipv6_next_hop_free    route_match_ipv6_next_hop_free
 };  };
 /* `match ipv6 address prefix-list PREFIX_LIST' */  /* `match ipv6 address prefix-list PREFIX_LIST' */
   
 static route_map_result_t  static route_map_result_t
Line 1883  struct route_map_rule_cmd route_match_ipv6_address_pre Line 1851  struct route_map_rule_cmd route_match_ipv6_address_pre
   route_match_ipv6_address_prefix_list_compile,    route_match_ipv6_address_prefix_list_compile,
   route_match_ipv6_address_prefix_list_free    route_match_ipv6_address_prefix_list_free
 };  };
 /* `set ipv6 nexthop global IP_ADDRESS' */  /* `set ipv6 nexthop global IP_ADDRESS' */
   
 /* Set nexthop to object.  ojbect must be pointer to struct attr. */  /* Set nexthop to object.  ojbect must be pointer to struct attr. */
Line 1947  struct route_map_rule_cmd route_set_ipv6_nexthop_globa Line 1915  struct route_map_rule_cmd route_set_ipv6_nexthop_globa
   route_set_ipv6_nexthop_global_compile,    route_set_ipv6_nexthop_global_compile,
   route_set_ipv6_nexthop_global_free    route_set_ipv6_nexthop_global_free
 };  };
 /* `set ipv6 nexthop local IP_ADDRESS' */  /* `set ipv6 nexthop local IP_ADDRESS' */
   
 /* Set nexthop to object.  ojbect must be pointer to struct attr. */  /* Set nexthop to object.  ojbect must be pointer to struct attr. */
Line 2011  struct route_map_rule_cmd route_set_ipv6_nexthop_local Line 1979  struct route_map_rule_cmd route_set_ipv6_nexthop_local
   route_set_ipv6_nexthop_local_compile,    route_set_ipv6_nexthop_local_compile,
   route_set_ipv6_nexthop_local_free    route_set_ipv6_nexthop_local_free
 };  };
#endif /* HAVE_IPV6 */
/* `set ipv6 nexthop peer-address' */
 
 /* Set nexthop to object.  ojbect must be pointer to struct attr. */
 static route_map_result_t
 route_set_ipv6_nexthop_peer (void *rule, struct prefix *prefix,
                              route_map_object_t type, void *object)
 {
   struct in6_addr peer_address;
   struct bgp_info *bgp_info;
   struct peer *peer;
   char peer_addr_buf[INET6_ADDRSTRLEN];
 
   if (type == RMAP_BGP)
     {
       /* Fetch routemap's rule information. */
       bgp_info = object;
       peer = bgp_info->peer;
 
       if ((CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN) ||
            CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
           && peer->su_remote
           && sockunion_family (peer->su_remote) == AF_INET6)
         {
           inet_pton (AF_INET6, sockunion2str (peer->su_remote,
                                               peer_addr_buf,
                                               INET6_ADDRSTRLEN),
                      &peer_address);
         }
       else if (CHECK_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT)
                && peer->su_local
                && sockunion_family (peer->su_local) == AF_INET6)
         {
           inet_pton (AF_INET, sockunion2str (peer->su_local,
                                              peer_addr_buf,
                                              INET6_ADDRSTRLEN),
                      &peer_address);
         }
 
       if (IN6_IS_ADDR_LINKLOCAL(&peer_address))
         {
           /* Set next hop value. */
           (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_local = peer_address;
 
           /* Set nexthop length. */
           if (bgp_info->attr->extra->mp_nexthop_len != 32)
             bgp_info->attr->extra->mp_nexthop_len = 32;
         }
       else
         {
           /* Set next hop value. */
           (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global = peer_address;
 
           /* Set nexthop length. */
           if (bgp_info->attr->extra->mp_nexthop_len == 0)
             bgp_info->attr->extra->mp_nexthop_len = 16;
         }
     }
 
   return RMAP_OKAY;
 }
 
 /* Route map `ip next-hop' compile function.  Given string is converted
    to struct in_addr structure. */
 static void *
 route_set_ipv6_nexthop_peer_compile (const char *arg)
 {
   int *rins = NULL;
 
   rins = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (int));
   *rins = 1;
 
   return rins;
 }
 
 /* Free route map's compiled `ip next-hop' value. */
 static void
 route_set_ipv6_nexthop_peer_free (void *rule)
 {
   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 }
 
 /* Route map commands for ip nexthop set. */
 struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd =
 {
   "ipv6 next-hop peer-address",
   route_set_ipv6_nexthop_peer,
   route_set_ipv6_nexthop_peer_compile,
   route_set_ipv6_nexthop_peer_free
 };
 
 /* `set vpnv4 nexthop A.B.C.D' */  /* `set vpnv4 nexthop A.B.C.D' */
   
 static route_map_result_t  static route_map_result_t
Line 2030  route_set_vpnv4_nexthop (void *rule, struct prefix *pr Line 2087  route_set_vpnv4_nexthop (void *rule, struct prefix *pr
           
       /* Set next hop value. */         /* Set next hop value. */ 
       (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global_in = *address;        (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global_in = *address;
         (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_len = 4;
     }      }
   
   return RMAP_OKAY;    return RMAP_OKAY;
Line 2068  struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd  Line 2126  struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd 
   route_set_vpnv4_nexthop_compile,    route_set_vpnv4_nexthop_compile,
   route_set_vpnv4_nexthop_free    route_set_vpnv4_nexthop_free
 };  };
 /* `set originator-id' */  /* `set originator-id' */
   
 /* For origin set. */  /* For origin set. */
Line 2117  route_set_originator_id_free (void *rule) Line 2175  route_set_originator_id_free (void *rule)
   XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);    XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
 }  }
   
/* Set metric rule structure. *//* Set originator-id rule structure. */
 struct route_map_rule_cmd route_set_originator_id_cmd =   struct route_map_rule_cmd route_set_originator_id_cmd = 
 {  {
   "originator-id",    "originator-id",
Line 2125  struct route_map_rule_cmd route_set_originator_id_cmd  Line 2183  struct route_map_rule_cmd route_set_originator_id_cmd 
   route_set_originator_id_compile,    route_set_originator_id_compile,
   route_set_originator_id_free,    route_set_originator_id_free,
 };  };
 /* Add bgp route map rule. */  /* Add bgp route map rule. */
 static int  static int
 bgp_route_match_add (struct vty *vty, struct route_map_index *index,  bgp_route_match_add (struct vty *vty, struct route_map_index *index,
Line 2235  bgp_route_map_update (const char *unused) Line 2293  bgp_route_map_update (const char *unused)
   struct bgp_node *bn;    struct bgp_node *bn;
   struct bgp_static *bgp_static;    struct bgp_static *bgp_static;
   
     if (bm->bgp == NULL)          /* may be called during cleanup */
       return;
   
   /* For neighbor route-map updates. */    /* For neighbor route-map updates. */
   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))    for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
     {      {
Line 2323  bgp_route_map_update (const char *unused) Line 2384  bgp_route_map_update (const char *unused)
     {      {
       for (i = 0; i < ZEBRA_ROUTE_MAX; i++)        for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
         {          {
          if (bgp->rmap[ZEBRA_FAMILY_IPV4][i].name)          if (bgp->rmap[AFI_IP][i].name)
            bgp->rmap[ZEBRA_FAMILY_IPV4][i].map =             bgp->rmap[AFI_IP][i].map =
              route_map_lookup_by_name (bgp->rmap[ZEBRA_FAMILY_IPV4][i].name);              route_map_lookup_by_name (bgp->rmap[AFI_IP][i].name);
#ifdef HAVE_IPV6          if (bgp->rmap[AFI_IP6][i].name)
          if (bgp->rmap[ZEBRA_FAMILY_IPV6][i].name)            bgp->rmap[AFI_IP6][i].map =
            bgp->rmap[ZEBRA_FAMILY_IPV6][i].map =              route_map_lookup_by_name (bgp->rmap[AFI_IP][i].name);
              route_map_lookup_by_name (bgp->rmap[ZEBRA_FAMILY_IPV6][i].name); 
#endif /* HAVE_IPV6 */ 
         }          }
     }      }
 }  }
 DEFUN (match_peer,  DEFUN (match_peer,
        match_peer_cmd,         match_peer_cmd,
        "match peer (A.B.C.D|X:X::X:X)",         "match peer (A.B.C.D|X:X::X:X)",
Line 2353  DEFUN (match_peer_local, Line 2412  DEFUN (match_peer_local,
         "Match peer address\n"          "Match peer address\n"
         "Static or Redistributed routes\n")          "Static or Redistributed routes\n")
 {  {
  return bgp_route_match_add (vty, vty->index, "peer", NULL);  return bgp_route_match_add (vty, vty->index, "peer", "local");
 }  }
   
 DEFUN (no_match_peer,  DEFUN (no_match_peer,
Line 2462  ALIAS (no_match_ip_next_hop, Line 2521  ALIAS (no_match_ip_next_hop,
        "IP access-list number (expanded range)\n"         "IP access-list number (expanded range)\n"
        "IP Access-list name\n")         "IP Access-list name\n")
   
   /* match probability { */
   
   DEFUN (match_probability,
          match_probability_cmd,
          "match probability <0-100>",
          MATCH_STR
          "Match portion of routes defined by percentage value\n"
          "Percentage of routes\n")
   {
     return bgp_route_match_add (vty, vty->index, "probability", argv[0]);
   }
   
   DEFUN (no_match_probability,
          no_match_probability_cmd,
          "no match probability",
          NO_STR
          MATCH_STR
          "Match portion of routes defined by percentage value\n")
   {
     return bgp_route_match_delete (vty, vty->index, "probability", argc ? argv[0] : NULL);
   }
   
   ALIAS (no_match_probability,
          no_match_probability_val_cmd,
          "no match probability <1-99>",
          NO_STR
          MATCH_STR
          "Match portion of routes defined by percentage value\n"
          "Percentage of routes\n")
   
   /* } */
   
 DEFUN (match_ip_route_source,   DEFUN (match_ip_route_source, 
        match_ip_route_source_cmd,         match_ip_route_source_cmd,
        "match ip route-source (<1-199>|<1300-2699>|WORD)",         "match ip route-source (<1-199>|<1300-2699>|WORD)",
Line 2893  ALIAS (set_metric, Line 2984  ALIAS (set_metric,
        "Metric value for destination routing protocol\n"         "Metric value for destination routing protocol\n"
        "Add or subtract metric\n")         "Add or subtract metric\n")
   
   ALIAS (set_metric,
          set_metric_rtt_cmd,
          "set metric (rtt|+rtt|-rtt)",
          SET_STR
          "Metric value for destination routing protocol\n"
          "Assign round trip time\n"
          "Add round trip time\n"
          "Subtract round trip time\n")
   
 DEFUN (no_set_metric,  DEFUN (no_set_metric,
        no_set_metric_cmd,         no_set_metric_cmd,
        "no set metric",         "no set metric",
Line 2994  DEFUN (set_aspath_prepend, Line 3094  DEFUN (set_aspath_prepend,
   return ret;    return ret;
 }  }
   
   ALIAS (set_aspath_prepend,
          set_aspath_prepend_lastas_cmd,
          "set as-path prepend (last-as) <1-10>",
          SET_STR
          "Transform BGP AS_PATH attribute\n"
          "Prepend to the as-path\n"
          "Use the peer's AS-number\n"
          "Number of times to insert")
   
 DEFUN (no_set_aspath_prepend,  DEFUN (no_set_aspath_prepend,
        no_set_aspath_prepend_cmd,         no_set_aspath_prepend_cmd,
        "no set as-path prepend",         "no set as-path prepend",
Line 3384  DEFUN (set_aggregator_as, Line 3493  DEFUN (set_aggregator_as,
        "IP address of aggregator\n")         "IP address of aggregator\n")
 {  {
   int ret;    int ret;
  as_t as;  as_t as __attribute__((unused)); /* dummy for VTY_GET_INTEGER_RANGE */
   struct in_addr address;    struct in_addr address;
   char *argstr;    char *argstr;
   
Line 3418  DEFUN (no_set_aggregator_as, Line 3527  DEFUN (no_set_aggregator_as,
        "AS number of aggregator\n")         "AS number of aggregator\n")
 {  {
   int ret;    int ret;
  as_t as;  as_t as __attribute__((unused)); /* dummy for VTY_GET_INTEGER_RANGE */
   struct in_addr address;    struct in_addr address;
   char *argstr;    char *argstr;
   
Line 3456  ALIAS (no_set_aggregator_as, Line 3565  ALIAS (no_set_aggregator_as,
        "AS number\n"         "AS number\n"
        "IP address of aggregator\n")         "IP address of aggregator\n")
   
   
 #ifdef HAVE_IPV6  
 DEFUN (match_ipv6_address,   DEFUN (match_ipv6_address, 
        match_ipv6_address_cmd,         match_ipv6_address_cmd,
        "match ipv6 address WORD",         "match ipv6 address WORD",
Line 3529  DEFUN (no_match_ipv6_address_prefix_list, Line 3636  DEFUN (no_match_ipv6_address_prefix_list,
   return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]);    return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]);
 }  }
   
   DEFUN (set_ipv6_nexthop_peer,
          set_ipv6_nexthop_peer_cmd,
          "set ipv6 next-hop peer-address",
          SET_STR
          IPV6_STR
          "Next hop address\n"
          "Use peer address (for BGP only)\n")
   {
     return bgp_route_set_add (vty, vty->index, "ipv6 next-hop peer-address", NULL);
   }
   
   DEFUN (no_set_ipv6_nexthop_peer,
          no_set_ipv6_nexthop_peer_cmd,
          "no set ipv6 next-hop peer-address",
          NO_STR
          SET_STR
          IPV6_STR
          "IPv6 next-hop address\n"
          )
   {
     return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop", argv[0]);
   }
   
 DEFUN (set_ipv6_nexthop_global,  DEFUN (set_ipv6_nexthop_global,
        set_ipv6_nexthop_global_cmd,         set_ipv6_nexthop_global_cmd,
        "set ipv6 next-hop global X:X::X:X",         "set ipv6 next-hop global X:X::X:X",
Line 3602  ALIAS (no_set_ipv6_nexthop_local, Line 3732  ALIAS (no_set_ipv6_nexthop_local,
        "IPv6 next-hop address\n"         "IPv6 next-hop address\n"
        "IPv6 local address\n"         "IPv6 local address\n"
        "IPv6 address of next hop\n")         "IPv6 address of next hop\n")
 #endif /* HAVE_IPV6 */  
   
 DEFUN (set_vpnv4_nexthop,  DEFUN (set_vpnv4_nexthop,
        set_vpnv4_nexthop_cmd,         set_vpnv4_nexthop_cmd,
Line 3727  ALIAS (no_match_pathlimit_as, Line 3856  ALIAS (no_match_pathlimit_as,
        "BGP AS-Pathlimit attribute\n"         "BGP AS-Pathlimit attribute\n"
        "Match Pathlimit ASN\n")         "Match Pathlimit ASN\n")
   
 /* Initialization of route map. */  /* Initialization of route map. */
 void  void
 bgp_route_map_init (void)  bgp_route_map_init (void)
Line 3749  bgp_route_map_init (void) Line 3878  bgp_route_map_init (void)
   route_map_install_match (&route_match_ecommunity_cmd);    route_map_install_match (&route_match_ecommunity_cmd);
   route_map_install_match (&route_match_metric_cmd);    route_map_install_match (&route_match_metric_cmd);
   route_map_install_match (&route_match_origin_cmd);    route_map_install_match (&route_match_origin_cmd);
     route_map_install_match (&route_match_probability_cmd);
   
   route_map_install_set (&route_set_ip_nexthop_cmd);    route_map_install_set (&route_set_ip_nexthop_cmd);
   route_map_install_set (&route_set_local_pref_cmd);    route_map_install_set (&route_set_local_pref_cmd);
Line 3780  bgp_route_map_init (void) Line 3910  bgp_route_map_init (void)
   install_element (RMAP_NODE, &match_ip_route_source_cmd);    install_element (RMAP_NODE, &match_ip_route_source_cmd);
   install_element (RMAP_NODE, &no_match_ip_route_source_cmd);    install_element (RMAP_NODE, &no_match_ip_route_source_cmd);
   install_element (RMAP_NODE, &no_match_ip_route_source_val_cmd);    install_element (RMAP_NODE, &no_match_ip_route_source_val_cmd);
   
   install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);    install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
   install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);    install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
   install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);    install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
Line 3808  bgp_route_map_init (void) Line 3937  bgp_route_map_init (void)
   install_element (RMAP_NODE, &match_origin_cmd);    install_element (RMAP_NODE, &match_origin_cmd);
   install_element (RMAP_NODE, &no_match_origin_cmd);    install_element (RMAP_NODE, &no_match_origin_cmd);
   install_element (RMAP_NODE, &no_match_origin_val_cmd);    install_element (RMAP_NODE, &no_match_origin_val_cmd);
     install_element (RMAP_NODE, &match_probability_cmd);
     install_element (RMAP_NODE, &no_match_probability_cmd);
     install_element (RMAP_NODE, &no_match_probability_val_cmd);
   
   install_element (RMAP_NODE, &set_ip_nexthop_cmd);    install_element (RMAP_NODE, &set_ip_nexthop_cmd);
   install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);    install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd);
Line 3821  bgp_route_map_init (void) Line 3953  bgp_route_map_init (void)
   install_element (RMAP_NODE, &no_set_weight_val_cmd);    install_element (RMAP_NODE, &no_set_weight_val_cmd);
   install_element (RMAP_NODE, &set_metric_cmd);    install_element (RMAP_NODE, &set_metric_cmd);
   install_element (RMAP_NODE, &set_metric_addsub_cmd);    install_element (RMAP_NODE, &set_metric_addsub_cmd);
     install_element (RMAP_NODE, &set_metric_rtt_cmd);
   install_element (RMAP_NODE, &no_set_metric_cmd);    install_element (RMAP_NODE, &no_set_metric_cmd);
   install_element (RMAP_NODE, &no_set_metric_val_cmd);    install_element (RMAP_NODE, &no_set_metric_val_cmd);
   install_element (RMAP_NODE, &set_aspath_prepend_cmd);    install_element (RMAP_NODE, &set_aspath_prepend_cmd);
     install_element (RMAP_NODE, &set_aspath_prepend_lastas_cmd);
   install_element (RMAP_NODE, &set_aspath_exclude_cmd);    install_element (RMAP_NODE, &set_aspath_exclude_cmd);
   install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);    install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
   install_element (RMAP_NODE, &no_set_aspath_prepend_val_cmd);    install_element (RMAP_NODE, &no_set_aspath_prepend_val_cmd);
Line 3858  bgp_route_map_init (void) Line 3992  bgp_route_map_init (void)
   install_element (RMAP_NODE, &no_set_originator_id_cmd);    install_element (RMAP_NODE, &no_set_originator_id_cmd);
   install_element (RMAP_NODE, &no_set_originator_id_val_cmd);    install_element (RMAP_NODE, &no_set_originator_id_val_cmd);
   
 #ifdef HAVE_IPV6  
   route_map_install_match (&route_match_ipv6_address_cmd);    route_map_install_match (&route_match_ipv6_address_cmd);
   route_map_install_match (&route_match_ipv6_next_hop_cmd);    route_map_install_match (&route_match_ipv6_next_hop_cmd);
   route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);    route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);
   route_map_install_set (&route_set_ipv6_nexthop_global_cmd);    route_map_install_set (&route_set_ipv6_nexthop_global_cmd);
   route_map_install_set (&route_set_ipv6_nexthop_local_cmd);    route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
    route_map_install_set (&route_set_ipv6_nexthop_peer_cmd);
 
   install_element (RMAP_NODE, &match_ipv6_address_cmd);    install_element (RMAP_NODE, &match_ipv6_address_cmd);
   install_element (RMAP_NODE, &no_match_ipv6_address_cmd);    install_element (RMAP_NODE, &no_match_ipv6_address_cmd);
   install_element (RMAP_NODE, &match_ipv6_next_hop_cmd);    install_element (RMAP_NODE, &match_ipv6_next_hop_cmd);
Line 3877  bgp_route_map_init (void) Line 4011  bgp_route_map_init (void)
   install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);    install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
   install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);    install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
   install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);    install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);
#endif /* HAVE_IPV6 */  install_element (RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
   install_element (RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
   
   /* AS-Pathlimit: functionality removed, commands kept for    /* AS-Pathlimit: functionality removed, commands kept for
    * compatibility.     * compatibility.

Removed from v.1.1  
changed lines
  Added in v.1.1.1.4


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