diff options
Diffstat (limited to 'ripd')
| -rw-r--r-- | ripd/ChangeLog | 4 | ||||
| -rw-r--r-- | ripd/Makefile.am | 2 | ||||
| -rw-r--r-- | ripd/rip_interface.c | 237 | ||||
| -rw-r--r-- | ripd/rip_routemap.c | 273 | ||||
| -rw-r--r-- | ripd/rip_zebra.c | 42 | ||||
| -rw-r--r-- | ripd/ripd.c | 280 | ||||
| -rw-r--r-- | ripd/ripd.h | 15 | 
7 files changed, 742 insertions, 111 deletions
diff --git a/ripd/ChangeLog b/ripd/ChangeLog index 49501693..c80338dd 100644 --- a/ripd/ChangeLog +++ b/ripd/ChangeLog @@ -1,3 +1,7 @@ +2003-05-25 Vincent Jardin <vjardin@wanadoo.fr> + +  * 6Wind patch merge. +  2003-04-19 Hasso Tepper <hasso@estpak.ee>  	* rip_routemap.c: sync daemon's route-map commands to have same diff --git a/ripd/Makefile.am b/ripd/Makefile.am index fd254851..df9a0af5 100644 --- a/ripd/Makefile.am +++ b/ripd/Makefile.am @@ -17,7 +17,7 @@ noinst_HEADERS = \  ripd_SOURCES = \  	rip_main.c $(librip_a_SOURCES) -ripd_LDADD = ../lib/libzebra.a +ripd_LDADD = -L../lib -lzebra  sysconf_DATA = ripd.conf.sample diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 23c9cb0b..8ec96ae1 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -43,6 +43,10 @@  void rip_enable_apply (struct interface *);  void rip_passive_interface_apply (struct interface *);  int rip_if_down(struct interface *ifp); +int rip_enable_if_lookup (char *ifname); +int rip_enable_network_lookup2 (struct connected *connected); +void rip_enable_apply_all (); +  struct message ri_version_msg[] =   { @@ -122,7 +126,7 @@ rip_interface_new ()       Relay or SMDS is enabled, the default value for split-horizon is       off.  But currently Zebra does detect Frame Relay or SMDS       interface.  So all interface is set to split horizon.  */ -  ri->split_horizon_default = 1; +  ri->split_horizon_default = RIP_SPLIT_HORIZON;    ri->split_horizon = ri->split_horizon_default;    return ri; @@ -226,10 +230,8 @@ rip_request_interface_send (struct interface *ifp, u_char version)  	      to.sin_port = htons (RIP_PORT_DEFAULT);  	      to.sin_addr = p->prefix; -#if 0  	      if (IS_RIP_DEBUG_EVENT)  		zlog_info ("SEND request to %s", inet_ntoa (to.sin_addr)); -#endif /* 0 */  	      rip_request_send (&to, ifp, version);  	    } @@ -466,6 +468,9 @@ rip_interface_add (int command, struct zclient *zclient, zebra_size_t length)    /* rip_request_neighbor_all (); */ +  /* Check interface routemap. */ +  rip_if_rmap_update_interface (ifp); +    return 0;  } @@ -554,8 +559,8 @@ rip_interface_reset ()  	  ri->key_chain = NULL;  	} -      ri->split_horizon = 0; -      ri->split_horizon_default = 0; +      ri->split_horizon = RIP_NO_SPLIT_HORIZON; +      ri->split_horizon_default = RIP_NO_SPLIT_HORIZON;        ri->list[RIP_FILTER_IN] = NULL;        ri->list[RIP_FILTER_OUT] = NULL; @@ -644,6 +649,34 @@ rip_if_down_all ()      }  } +static void +rip_apply_address_add (struct connected *ifc) { +  struct prefix_ipv4 address; +  struct prefix *p; + +  if (!rip) +    return; + +  if (! if_is_up(ifc->ifp)) +    return; + +  p = ifc->address; + +  memset (&address, 0, sizeof (address)); +  address.family = p->family; +  address.prefix = p->u.prefix4; +  address.prefixlen = p->prefixlen; +  apply_mask_ipv4(&address); + +  /* Check if this interface is RIP enabled or not +     or  Check if this address's prefix is RIP enabled */ +  if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) || +      (rip_enable_network_lookup2(ifc) >= 0)) +    rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, +                         &address, ifc->ifp->ifindex, NULL); + +} +  int  rip_interface_address_add (int command, struct zclient *zclient,  			   zebra_size_t length) @@ -663,9 +696,9 @@ rip_interface_address_add (int command, struct zclient *zclient,        if (IS_RIP_DEBUG_ZEBRA)  	zlog_info ("connected address %s/%d is added",   		   inet_ntoa (p->u.prefix4), p->prefixlen); -       -      /* Check is this interface is RIP enabled or not.*/ -      rip_enable_apply (ifc->ifp); + +      /* Check if this prefix needs to be redistributed */ +      rip_apply_address_add(ifc);  #ifdef HAVE_SNMP        rip_ifaddr_add (ifc->ifp, ifc); @@ -675,6 +708,29 @@ rip_interface_address_add (int command, struct zclient *zclient,    return 0;  } +static void +rip_apply_address_del (struct connected *ifc) { +  struct prefix_ipv4 address; +  struct prefix *p; + +  if (!rip) +    return; + +  if (! if_is_up(ifc->ifp)) +    return; + +  p = ifc->address; + +  memset (&address, 0, sizeof (address)); +  address.family = p->family; +  address.prefix = p->u.prefix4; +  address.prefixlen = p->prefixlen; +  apply_mask_ipv4(&address); + +  rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, +                          &address, ifc->ifp->ifindex); +} +  int  rip_interface_address_delete (int command, struct zclient *zclient,  			      zebra_size_t length) @@ -698,8 +754,9 @@ rip_interface_address_delete (int command, struct zclient *zclient,  	  rip_ifaddr_delete (ifc->ifp, ifc);  #endif /* HAVE_SNMP */ -	  /* Check if this interface is RIP enabled or not.*/ -	  rip_enable_apply (ifc->ifp); +	  /* Chech wether this prefix needs to be removed */ +          rip_apply_address_del(ifc); +  	}        connected_free (ifc); @@ -710,8 +767,10 @@ rip_interface_address_delete (int command, struct zclient *zclient,  }  /* Check interface is enabled by network statement. */ +/* Check wether the interface has at least a connected prefix that + * is within the ripng_enable_network table. */  int -rip_enable_network_lookup (struct interface *ifp) +rip_enable_network_lookup_if (struct interface *ifp)  {    struct listnode *nn;    struct connected *connected; @@ -743,6 +802,34 @@ rip_enable_network_lookup (struct interface *ifp)    return -1;  } +/* Check wether connected is within the ripng_enable_network table. */ +int +rip_enable_network_lookup2 (struct connected *connected) +{ +  struct prefix_ipv4 address; +  struct prefix *p; + +  p = connected->address; + +  if (p->family == AF_INET) { +    struct route_node *node; + +    address.family = p->family; +    address.prefix = p->u.prefix4; +    address.prefixlen = IPV4_MAX_BITLEN; + +    /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within rip_enable_network */ +    node = route_node_match (rip_enable_network, +                             (struct prefix *)&address); + +    if (node) { +      route_unlock_node (node); +      return 1; +    } +  } + +  return -1; +}  /* Add RIP enable network. */  int  rip_enable_network_add (struct prefix *p) @@ -759,6 +846,9 @@ rip_enable_network_add (struct prefix *p)    else      node->info = "enabled"; +  /* XXX: One should find a better solution than a generic one */ +  rip_enable_apply_all(); +    return 1;  } @@ -779,6 +869,9 @@ rip_enable_network_delete (struct prefix *p)        /* Unlock lookup lock. */        route_unlock_node (node); +      /* XXX: One should find a better solution than a generic one */ +      rip_enable_apply_all (); +        return 1;      }    return -1; @@ -810,6 +903,8 @@ rip_enable_if_add (char *ifname)    vector_set (rip_enable_interface, strdup (ifname)); +  rip_enable_apply_all(); /* TODOVJ */ +    return 1;  } @@ -828,6 +923,8 @@ rip_enable_if_delete (char *ifname)    free (str);    vector_unset (rip_enable_interface, index); +  rip_enable_apply_all(); /* TODOVJ */ +    return 1;  } @@ -883,10 +980,13 @@ rip_connect_set (struct interface *ifp, int set)  	address.prefixlen = p->prefixlen;  	apply_mask_ipv4 (&address); -	if (set) -	  rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, -				&address, connected->ifp->ifindex, NULL); -	else +	if (set) { +          /* Check once more wether this prefix is within a "network IF_OR_PREF" one */ +          if ((rip_enable_if_lookup(connected->ifp->name) >= 0) || +              (rip_enable_network_lookup2(connected) >= 0)) +	    rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, +				  &address, connected->ifp->ifindex, NULL); +	} else  	  {  	    rip_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,  				     &address, connected->ifp->ifindex); @@ -905,16 +1005,13 @@ rip_enable_apply (struct interface *ifp)    struct rip_interface *ri = NULL;    /* Check interface. */ -  if (if_is_loopback (ifp)) -    return; -    if (! if_is_operative (ifp))      return;    ri = ifp->info;    /* Check network configuration. */ -  ret = rip_enable_network_lookup (ifp); +  ret = rip_enable_network_lookup_if (ifp);    /* If the interface is matched. */    if (ret > 0) @@ -939,7 +1036,6 @@ rip_enable_apply (struct interface *ifp)    /* Update running status of the interface. */    if (ri->enable_network || ri->enable_interface)      { -      if (! ri->running)  	{  	  if (IS_RIP_DEBUG_EVENT)  	    zlog_info ("turn on %s", ifp->name); @@ -955,13 +1051,11 @@ rip_enable_apply (struct interface *ifp)      {        if (ri->running)  	{ -	  if (IS_RIP_DEBUG_EVENT) -	    zlog_info ("turn off %s", ifp->name); - -	  /* Might as well clean up the route table as well */  +	  /* Might as well clean up the route table as well +	   * rip_if_down sets to 0 ri->running, and displays "turn off %s" +	   **/   	  rip_if_down(ifp); -	  ri->running = 0;            rip_connect_set (ifp, 0);  	}      } @@ -1181,8 +1275,6 @@ DEFUN (rip_network,        return CMD_WARNING;      } -  rip_enable_apply_all (); -    return CMD_SUCCESS;  } @@ -1212,8 +1304,6 @@ DEFUN (no_rip_network,        return CMD_WARNING;      } -  rip_enable_apply_all (); -    return CMD_SUCCESS;  } @@ -1661,10 +1751,15 @@ ALIAS (no_ip_rip_authentication_key_chain,         "Authentication key-chain\n"         "name of key-chain\n") -DEFUN (rip_split_horizon, -       rip_split_horizon_cmd, -       "ip split-horizon", +/* CHANGED: ip rip split-horizon +   Cisco and Zebra's command is +   ip split-horizon + */ +DEFUN (ip_rip_split_horizon, +       ip_rip_split_horizon_cmd, +       "ip rip split-horizon",         IP_STR +       "Routing Information Protocol\n"         "Perform split horizon\n")  {    struct interface *ifp; @@ -1673,15 +1768,38 @@ DEFUN (rip_split_horizon,    ifp = vty->index;    ri = ifp->info; -  ri->split_horizon = 1; +  ri->split_horizon = RIP_SPLIT_HORIZON;    return CMD_SUCCESS;  } -DEFUN (no_rip_split_horizon, -       no_rip_split_horizon_cmd, -       "no ip split-horizon", +DEFUN (ip_rip_split_horizon_poisoned_reverse, +       ip_rip_split_horizon_poisoned_reverse_cmd, +       "ip rip split-horizon poisoned-reverse", +       IP_STR +       "Routing Information Protocol\n" +       "Perform split horizon\n" +       "With poisoned-reverse\n") +{ +  struct interface *ifp; +  struct rip_interface *ri; + +  ifp = vty->index; +  ri = ifp->info; + +  ri->split_horizon = RIP_SPLIT_HORIZON_POISONED_REVERSE; +  return CMD_SUCCESS; +} + +/* CHANGED: no ip rip split-horizon +   Cisco and Zebra's command is +   no ip split-horizon + */ +DEFUN (no_ip_rip_split_horizon, +       no_ip_rip_split_horizon_cmd, +       "no ip rip split-horizon",         NO_STR         IP_STR +       "Routing Information Protocol\n"         "Perform split horizon\n")  {    struct interface *ifp; @@ -1690,10 +1808,19 @@ DEFUN (no_rip_split_horizon,    ifp = vty->index;    ri = ifp->info; -  ri->split_horizon = 0; +  ri->split_horizon = RIP_NO_SPLIT_HORIZON;    return CMD_SUCCESS;  } +ALIAS (no_ip_rip_split_horizon, +       no_ip_rip_split_horizon_poisoned_reverse_cmd, +       "no ip rip split-horizon poisoned-reverse", +       NO_STR +       IP_STR +       "Routing Information Protocol\n" +       "Perform split horizon\n" +       "With poisoned-reverse\n") +  DEFUN (rip_passive_interface,         rip_passive_interface_cmd,         "passive-interface IFNAME", @@ -1727,6 +1854,18 @@ rip_interface_config_write (struct vty *vty)        ifp = getdata (node);        ri = ifp->info; +      /* Do not display the interface if there is no +       * configuration about it. +       **/ +      if ((!ifp->desc)                                     && +          (ri->split_horizon == ri->split_horizon_default) && +          (ri->ri_send == RI_RIP_UNSPEC)                   && +          (ri->ri_receive == RI_RIP_UNSPEC)                && +          (ri->auth_type != RIP_AUTH_MD5)                  && +          (!ri->auth_str)                                  && +          (!ri->key_chain)                                 ) +        continue; +        vty_out (vty, "interface %s%s", ifp->name,  	       VTY_NEWLINE); @@ -1737,10 +1876,19 @@ rip_interface_config_write (struct vty *vty)        /* Split horizon. */        if (ri->split_horizon != ri->split_horizon_default)  	{ -	  if (ri->split_horizon) -	    vty_out (vty, " ip split-horizon%s", VTY_NEWLINE); -	  else -	    vty_out (vty, " no ip split-horizon%s", VTY_NEWLINE); +          switch (ri->split_horizon) { +          case RIP_SPLIT_HORIZON: +            vty_out (vty, " ip rip split-horizon%s", VTY_NEWLINE); +            break; +          case RIP_SPLIT_HORIZON_POISONED_REVERSE: +            vty_out (vty, " ip rip split-horizon poisoned-reverse%s", +                          VTY_NEWLINE); +            break; +          case RIP_NO_SPLIT_HORIZON: +          default: +            vty_out (vty, " no ip rip split-horizon%s", VTY_NEWLINE); +            break; +          }  	}        /* RIP version setting. */ @@ -1837,6 +1985,7 @@ int  rip_interface_delete_hook (struct interface *ifp)  {    XFREE (MTYPE_RIP_INTERFACE, ifp->info); +  ifp->info = NULL;    return 0;  } @@ -1897,6 +2046,8 @@ rip_if_init ()    install_element (INTERFACE_NODE, &no_ip_rip_authentication_string_cmd);    install_element (INTERFACE_NODE, &no_ip_rip_authentication_string2_cmd); -  install_element (INTERFACE_NODE, &rip_split_horizon_cmd); -  install_element (INTERFACE_NODE, &no_rip_split_horizon_cmd); +  install_element (INTERFACE_NODE, &ip_rip_split_horizon_cmd); +  install_element (INTERFACE_NODE, &ip_rip_split_horizon_poisoned_reverse_cmd); +  install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_cmd); +  install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_poisoned_reverse_cmd);  } diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c index 8262f508..b354a896 100644 --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@ -31,6 +31,18 @@  #include "plist.h"  #include "ripd/ripd.h" + +struct rip_metric_modifier +{ +  enum  +  { +    metric_increment, +    metric_decrement, +    metric_absolute +  } type; + +  u_char metric; +};  /* Add rip route map rule. */  int @@ -439,6 +451,57 @@ struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =    route_match_ip_address_prefix_list_compile,    route_match_ip_address_prefix_list_free  }; + +/* `match tag TAG' */ +/* Match function return 1 if match is success else return zero. */ +route_map_result_t +route_match_tag (void *rule, struct prefix *prefix,  +		    route_map_object_t type, void *object) +{ +  u_short *tag; +  struct rip_info *rinfo; + +  if (type == RMAP_RIP) +    { +      tag = rule; +      rinfo = object; + +      /* The information stored by rinfo is host ordered. */ +      if (rinfo->tag == *tag) +	return RMAP_MATCH; +      else +	return RMAP_NOMATCH; +    } +  return RMAP_NOMATCH; +} + +/* Route map `match tag' match statement. `arg' is TAG value */ +void * +route_match_tag_compile (char *arg) +{ +  u_short *tag; + +  tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); +  *tag = atoi (arg); + +  return tag; +} + +/* Free route map's compiled `match tag' value. */ +void +route_match_tag_free (void *rule) +{ +  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for tag matching. */ +struct route_map_rule_cmd route_match_tag_cmd = +{ +  "tag", +  route_match_tag, +  route_match_tag_compile, +  route_match_tag_free +};  /* `set metric METRIC' */ @@ -447,17 +510,26 @@ route_map_result_t  route_set_metric (void *rule, struct prefix *prefix,   		  route_map_object_t type, void *object)  { -  u_int32_t *metric; -  struct rip_info *rinfo; -    if (type == RMAP_RIP)      { -      /* Fetch routemap's rule information. */ -      metric = rule; +      struct rip_metric_modifier *mod; +      struct rip_info *rinfo; + +      mod = rule;        rinfo = object; -     -      /* Set metric out value. */ -      rinfo->metric_out = *metric; + +      if (mod->type == metric_increment) +	rinfo->metric_out += mod->metric; +      else if (mod->type == metric_decrement) +	rinfo->metric_out -= mod->metric; +      else if (mod->type == metric_absolute) +	rinfo->metric_out = mod->metric; + +      if (rinfo->metric_out < 1) +	rinfo->metric_out = 1; +      if (rinfo->metric_out > RIP_METRIC_INFINITY) +	rinfo->metric_out = RIP_METRIC_INFINITY; +        rinfo->metric_set = 1;      }    return RMAP_OKAY; @@ -467,22 +539,51 @@ route_set_metric (void *rule, struct prefix *prefix,  void *  route_set_metric_compile (char *arg)  { -  u_int32_t *metric; +  int len; +  char *pnt; +  int type; +  long metric; +  char *endptr = NULL; +  struct rip_metric_modifier *mod; -  metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); -  *metric = atoi (arg); +  len = strlen (arg); +  pnt = arg; -  return metric; +  if (len == 0) +    return NULL; -#if 0 -  /* To make it consistent to other daemon, metric check is commented -     out.*/ -  if (*metric >= 0 && *metric <= 16) -    return metric; +  /* Examine first character. */ +  if (arg[0] == '+') +    { +      type = metric_increment; +      pnt++; +    } +  else if (arg[0] == '-') +    { +      type = metric_decrement; +      pnt++; +    } +  else +    type = metric_absolute; -  XFREE (MTYPE_ROUTE_MAP_COMPILED, metric); -  return NULL; -#endif /* 0 */ +  /* Check beginning with digit string. */ +  if (*pnt < '0' || *pnt > '9') +    return NULL; + +  /* Convert string to integer. */ +  metric = strtol (pnt, &endptr, 10); + +  if (metric == LONG_MAX || *endptr != '\0') +    return NULL; +  if (metric < 0 || metric > RIP_METRIC_INFINITY) +    return NULL; + +  mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,  +		 sizeof (struct rip_metric_modifier)); +  mod->type = type; +  mod->metric = metric; + +  return mod;  }  /* Free route map's compiled `set metric' value. */ @@ -560,6 +661,58 @@ struct route_map_rule_cmd route_set_ip_nexthop_cmd =    route_set_ip_nexthop_compile,    route_set_ip_nexthop_free  }; + +/* `set tag TAG' */ + +/* Set tag to object.  ojbect must be pointer to struct attr. */ +route_map_result_t +route_set_tag (void *rule, struct prefix *prefix,  +		      route_map_object_t type, void *object) +{ +  u_short *tag; +  struct rip_info *rinfo; + +  if(type == RMAP_RIP) +    { +      /* Fetch routemap's rule information. */ +      tag = rule; +      rinfo = object; +     +      /* Set next hop value. */  +      rinfo->tag_out = *tag; +    } + +  return RMAP_OKAY; +} + +/* Route map `tag' compile function.  Given string is converted +   to u_short. */ +void * +route_set_tag_compile (char *arg) +{ +  u_short *tag; + +  tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); +  *tag = atoi (arg); + +  return tag; +} + +/* Free route map's compiled `ip nexthop' value. */ +void +route_set_tag_free (void *rule) +{ +  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for tag set. */ +struct route_map_rule_cmd route_set_tag_cmd = +{ +  "tag", +  route_set_tag, +  route_set_tag_compile, +  route_set_tag_free +};  #define MATCH_STR "Match values from routing table\n"  #define SET_STR "Set values in destination routing protocol\n" @@ -777,14 +930,46 @@ ALIAS (no_match_ip_address_prefix_list,         "Match entries of prefix-lists\n"         "IP prefix-list name\n") +DEFUN (match_tag,  +       match_tag_cmd, +       "match tag <0-65535>", +       MATCH_STR +       "Match tag of route\n" +       "Metric value\n") +{ +  return rip_route_match_add (vty, vty->index, "tag", argv[0]); +} + +DEFUN (no_match_tag, +       no_match_tag_cmd, +       "no match tag", +       NO_STR +       MATCH_STR +       "Match tag of route\n") +{ +  if (argc == 0) +    return rip_route_match_delete (vty, vty->index, "tag", NULL); + +  return rip_route_match_delete (vty, vty->index, "tag", argv[0]); +} + +ALIAS (no_match_tag, +       no_match_tag_val_cmd, +       "no match tag <0-65535>", +       NO_STR +       MATCH_STR +       "Match tag of route\n" +       "Metric value\n") +  /* set functions */  DEFUN (set_metric,         set_metric_cmd, -       "set metric <0-4294967295>", +       "set metric (<0-4294967295>|<+/-metric>)",         SET_STR         "Metric value for destination routing protocol\n" -       "Metric value\n") +       "Metric value\n" +       "Add or subtract metric\n")  {    return rip_route_set_add (vty, vty->index, "metric", argv[0]);  } @@ -804,11 +989,12 @@ DEFUN (no_set_metric,  ALIAS (no_set_metric,         no_set_metric_val_cmd, -       "no set metric <0-4294967295>", +       "no set metric (<0-4294967295>|<+/-metric>)",         NO_STR         SET_STR         "Metric value for destination routing protocol\n" -       "Metric value\n") +       "Metric value\n" +       "Add or subtract metric\n")  DEFUN (set_ip_nexthop,         set_ip_nexthop_cmd, @@ -854,6 +1040,37 @@ ALIAS (no_set_ip_nexthop,         "Next hop address\n"         "IP address of next hop\n") +DEFUN (set_tag, +       set_tag_cmd, +       "set tag <0-65535>", +       SET_STR +       "Tag value for routing protocol\n" +       "Tag value\n") +{ +  return rip_route_set_add (vty, vty->index, "tag", argv[0]); +} + +DEFUN (no_set_tag, +       no_set_tag_cmd, +       "no set tag", +       NO_STR +       SET_STR +       "Tag value for routing protocol\n") +{ +  if (argc == 0) +    return rip_route_set_delete (vty, vty->index, "tag", NULL); +   +  return rip_route_set_delete (vty, vty->index, "tag", argv[0]); +} + +ALIAS (no_set_tag, +       no_set_tag_val_cmd, +       "no set tag <0-65535>", +       NO_STR +       SET_STR +       "Tag value for routing protocol\n" +       "Tag value\n") +  void  rip_route_map_reset ()  { @@ -875,9 +1092,11 @@ rip_route_map_init ()    route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);    route_map_install_match (&route_match_ip_address_cmd);    route_map_install_match (&route_match_ip_address_prefix_list_cmd); +  route_map_install_match (&route_match_tag_cmd);    route_map_install_set (&route_set_metric_cmd);    route_map_install_set (&route_set_ip_nexthop_cmd); +  route_map_install_set (&route_set_tag_cmd);    install_element (RMAP_NODE, &match_metric_cmd);    install_element (RMAP_NODE, &no_match_metric_cmd); @@ -897,6 +1116,9 @@ rip_route_map_init ()    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_val_cmd); +  install_element (RMAP_NODE, &match_tag_cmd); +  install_element (RMAP_NODE, &no_match_tag_cmd); +  install_element (RMAP_NODE, &no_match_tag_val_cmd);    install_element (RMAP_NODE, &set_metric_cmd);    install_element (RMAP_NODE, &no_set_metric_cmd); @@ -904,4 +1126,7 @@ rip_route_map_init ()    install_element (RMAP_NODE, &set_ip_nexthop_cmd);    install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);    install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd); +  install_element (RMAP_NODE, &set_tag_cmd); +  install_element (RMAP_NODE, &no_set_tag_cmd); +  install_element (RMAP_NODE, &no_set_tag_val_cmd);  } diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index b6caf3b0..67d7b8bf 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -502,6 +502,43 @@ DEFUN (no_rip_redistribute_type_metric,    return CMD_WARNING;  } +DEFUN (rip_redistribute_type_metric_routemap, +       rip_redistribute_type_metric_routemap_cmd, +       "redistribute (kernel|connected|static|ospf|bgp) metric <0-16> route-map WORD", +       "Redistribute information from another routing protocol\n" +       "Kernel routes\n" +       "Connected\n" +       "Static routes\n" +       "Open Shortest Path First (OSPF)\n" +       "Border Gateway Protocol (BGP)\n" +       "Metric\n" +       "Metric value\n" +       "Route map reference\n" +       "Pointer to route-map entries\n") +{ +  int i; +  int metric; + +  metric = atoi (argv[1]); + +  for (i = 0; redist_type[i].str; i++) { +    if (strncmp(redist_type[i].str, argv[0], +		redist_type[i].str_min_len) == 0)  +      { +	rip_redistribute_metric_set (redist_type[i].type, metric); +	rip_routemap_set (redist_type[i].type, argv[2]); +	zclient_redistribute_set (zclient, redist_type[i].type); +	return CMD_SUCCESS; +      } +  } + +  vty_out(vty, "Invalid type %s%s", argv[0], +	  VTY_NEWLINE); + +  return CMD_WARNING; +} + +  DEFUN (no_rip_redistribute_type_metric_routemap,         no_rip_redistribute_type_metric_routemap_cmd,         "no redistribute (kernel|connected|static|ospf|bgp) metric <0-16> route-map WORD", @@ -559,7 +596,7 @@ DEFUN (rip_default_information_originate,        rip->default_information = 1; -      rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL); +      rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0, NULL);      }    return CMD_SUCCESS; @@ -581,7 +618,7 @@ DEFUN (no_rip_default_information_originate,        rip->default_information = 0; -      rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0); +      rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0);      }    return CMD_SUCCESS; @@ -682,6 +719,7 @@ rip_zclient_init ()    install_element (RIP_NODE, &rip_redistribute_type_cmd);    install_element (RIP_NODE, &rip_redistribute_type_routemap_cmd);    install_element (RIP_NODE, &rip_redistribute_type_metric_cmd); +  install_element (RIP_NODE, &rip_redistribute_type_metric_routemap_cmd);    install_element (RIP_NODE, &no_rip_redistribute_type_cmd);    install_element (RIP_NODE, &no_rip_redistribute_type_routemap_cmd);    install_element (RIP_NODE, &no_rip_redistribute_type_metric_cmd); diff --git a/ripd/ripd.c b/ripd/ripd.c index 62ebd47c..c5d45536 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -32,6 +32,7 @@  #include "filter.h"  #include "sockunion.h"  #include "routemap.h" +#include "if_rmap.h"  #include "plist.h"  #include "distribute.h"  #include "md5-gnu.h" @@ -404,6 +405,40 @@ rip_rte_process (struct rte *rte, struct sockaddr_in *from,    if (ret < 0)      return; +  /* Modify entry according to the interface routemap. */ +  if (ri->routemap[RIP_FILTER_IN]) +    { +      int ret; +      struct rip_info newinfo; + +      memset (&newinfo, 0, sizeof (newinfo)); +      newinfo.type = ZEBRA_ROUTE_RIP; +      newinfo.sub_type = RIP_ROUTE_RTE; +      newinfo.nexthop= rte->nexthop; +      newinfo.from   = from->sin_addr; +      newinfo.ifindex= ifp->ifindex; +      newinfo.metric = rte->metric; +      newinfo.metric_out = rte->metric; /* XXX */ +      newinfo.tag    = ntohs(rte->tag); /* XXX */ + +      /* The object should be of the type of rip_info */ +      ret = route_map_apply (ri->routemap[RIP_FILTER_IN],  +			     (struct prefix *)&p, RMAP_RIP, &newinfo); + +      if (ret == RMAP_DENYMATCH) +	{ +	  if (IS_RIP_DEBUG_PACKET) +	    zlog_info ("RIP %s/%d is filtered by route-map in", +		       inet_ntoa (p.prefix), p.prefixlen); +	  return; +	} + +      /* Get back the object */ +      rte->nexthop    = newinfo.nexthop_out; +      rte->tag        = htons(newinfo.tag_out); /* XXX */ +      rte->metric     = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */ +    } +    /* Once the entry has been validated, update the metric by       adding the cost of the network on wich the message       arrived. If the result is greater than infinity, use infinity @@ -425,11 +460,11 @@ rip_rte_process (struct rte *rte, struct sockaddr_in *from,    else      nexthop = &rte->nexthop; -  /* Check nexthop address. */ +  /* Check if nexthop address is myself, then do nothing. */    if (rip_nexthop_check (nexthop) < 0)      {        if (IS_RIP_DEBUG_PACKET) -	zlog_info ("Nexthop address %s is invalid", inet_ntoa (*nexthop)); +	zlog_info ("Nexthop address %s is myself", inet_ntoa (*nexthop));        return;      } @@ -448,7 +483,8 @@ rip_rte_process (struct rte *rte, struct sockaddr_in *from,        /* Local static route. */        if (rinfo->type == ZEBRA_ROUTE_RIP -	  && rinfo->sub_type == RIP_ROUTE_STATIC +	  && ((rinfo->sub_type == RIP_ROUTE_STATIC) || +	      (rinfo->sub_type == RIP_ROUTE_DEFAULT))  	  && rinfo->metric != RIP_METRIC_INFINITY)  	return;      } @@ -514,7 +550,8 @@ rip_rte_process (struct rte *rte, struct sockaddr_in *from,  	 to the address of the router from which the datagram came.  	 If this datagram is from the same router as the existing  	 route, reinitialize the timeout.  */ -      same = IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr); +      same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr) +      	      && (rinfo->ifindex == ifp->ifindex));        if (same)  	rip_timeout_update (rinfo); @@ -522,9 +559,10 @@ rip_rte_process (struct rte *rte, struct sockaddr_in *from,        /* Next, compare the metrics.  If the datagram is from the same  	 router as the existing route, and the new metric is different  	 than the old one; or, if the new metric is lower than the old -	 one; do the following actions: */ +	 one, or if the tag has been changed; do the following actions: */        if ((same && rinfo->metric != rte->metric) || -	  rte->metric < rinfo->metric) +	  (rte->metric < rinfo->metric) || +	  (same && (rinfo->metric == rte->metric) && ntohs(rte->tag) != rinfo->tag))  	{  	  /* - Adopt the route from the datagram.  That is, put the  	     new metric in, and adjust the next hop address (if @@ -1275,9 +1313,11 @@ rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,        /* Manually configured RIP route check. */        if (rinfo->type == ZEBRA_ROUTE_RIP  -	  && rinfo->sub_type == RIP_ROUTE_STATIC) +	  && ((rinfo->sub_type == RIP_ROUTE_STATIC) || +	      (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )  	{ -	  if (type != ZEBRA_ROUTE_RIP || sub_type != RIP_ROUTE_STATIC) +	  if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) && +	                                  (sub_type != RIP_ROUTE_DEFAULT)))  	    {  	      route_unlock_node (rp);  	      return; @@ -1312,6 +1352,18 @@ rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p,    rinfo->flags |= RIP_RTF_CHANGED; +  if (IS_RIP_DEBUG_EVENT) { +    if (!nexthop) +      zlog_info ("Redistribute new prefix %s/%d on the interface %s", +                 inet_ntoa(p->prefix), p->prefixlen, +                 ifindex2ifname(ifindex)); +    else +      zlog_info ("Redistribute new prefix %s/%d with nexthop %s on the interface %s", +                 inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop), +                 ifindex2ifname(ifindex)); +  } + +    rip_event (RIP_TRIGGERED_UPDATE, 0);  } @@ -1345,6 +1397,11 @@ rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p,  	  RIP_TIMER_OFF (rinfo->t_timeout);  	  rinfo->flags |= RIP_RTF_CHANGED; +          if (IS_RIP_DEBUG_EVENT) +            zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [delete]", +                       inet_ntoa(p->prefix), p->prefixlen, +                       ifindex2ifname(ifindex)); +  	  rip_event (RIP_TRIGGERED_UPDATE, 0);  	}      } @@ -1362,7 +1419,14 @@ rip_request_process (struct rip_packet *packet, int size,    struct rip_info *rinfo;    struct rip_interface *ri; +  /* Does not reponse to the requests on the loopback interfaces */ +  if (if_is_loopback (ifp)) +    return; + +  /* Check RIPng process is enabled on this interface. */    ri = ifp->info; +  if (! ri->running) +    return;    /* When passive interface is specified, suppress responses */    if (ri->passive) @@ -1907,7 +1971,7 @@ rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,        masklen2ip (p->prefixlen, &mask);        stream_putw (s, AF_INET); -      stream_putw (s, rinfo->tag); +      stream_putw (s, rinfo->tag_out);        stream_put_ipv4 (s, p->prefix.s_addr);        stream_put_ipv4 (s, mask.s_addr);        stream_put_ipv4 (s, rinfo->nexthop_out.s_addr); @@ -2054,7 +2118,7 @@ rip_output_process (struct interface *ifp, struct prefix *ifaddr,  	/* Split horizon. */  	/* if (split_horizon == rip_split_horizon) */ -	if (ri->split_horizon) +	if (ri->split_horizon == RIP_SPLIT_HORIZON)  	  {  	    /* We perform split horizon for RIP and connected route. */  	    if ((rinfo->type == ZEBRA_ROUTE_RIP || @@ -2067,23 +2131,36 @@ rip_output_process (struct interface *ifp, struct prefix *ifaddr,  	rinfo->metric_set = 0;  	rinfo->nexthop_out.s_addr = 0;  	rinfo->metric_out = rinfo->metric; +	rinfo->tag_out = rinfo->tag;  	rinfo->ifindex_out = ifp->ifindex; -	/* In order to avoid some local loops, if the RIP route has a -	   nexthop via this interface, keep the nexthop, otherwise set -	   it to 0. The nexthop should not be propagated beyond the -	   local broadcast/multicast area in order to avoid an IGP -	   multi-level recursive look-up.  For RIP and connected -	   route, we don't set next hop value automatically.  For -	   settting next hop to those routes, please use -	   route-map.  */ - -	if (rinfo->type != ZEBRA_ROUTE_RIP -	    && rinfo->type != ZEBRA_ROUTE_CONNECT -	    && rinfo->ifindex == ifp->ifindex) +	/* In order to avoid some local loops, +	 * if the RIP route has a nexthop via this interface, keep the nexthop, +	 * otherwise set it to 0. The nexthop should not be propagated +	 * beyond the local broadcast/multicast area in order +	 * to avoid an IGP multi-level recursive look-up. +	 * see (4.4) +	 */ +	if (rinfo->ifindex == ifp->ifindex)  	  rinfo->nexthop_out = rinfo->nexthop; + +	/* Interface route-map */ +	if (ri->routemap[RIP_FILTER_OUT]) +	  { +	    ret = route_map_apply (ri->routemap[RIP_FILTER_OUT],  +				     (struct prefix *) p, RMAP_RIP,  +				     rinfo); + +	    if (ret == RMAP_DENYMATCH) +	      { +	        if (IS_RIP_DEBUG_PACKET) +	          zlog_info ("RIP %s/%d is filtered by route-map out", +			     inet_ntoa (p->prefix), p->prefixlen); +		  continue; +	      } +	  } -	/* Apply route map - continue, if deny */ +	/* Apply redistribute route map - continue, if deny */  	if (rip->route_map[rinfo->type].name  	    && rinfo->sub_type != RIP_ROUTE_INTERFACE)  	  { @@ -2125,7 +2202,17 @@ rip_output_process (struct interface *ifp, struct prefix *ifaddr,  	if (rinfo->metric_out > RIP_METRIC_INFINITY)  	  rinfo->metric_out = RIP_METRIC_INFINITY; -	   + +	/* Perform split-horizon with poisoned reverse  +	 * for RIP and connected routes. +	 **/ +	if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) { +	  if ((rinfo->type == ZEBRA_ROUTE_RIP || +	       rinfo->type == ZEBRA_ROUTE_CONNECT) && +	       rinfo->ifindex == ifp->ifindex) +	       rinfo->metric_out = RIP_METRIC_INFINITY; +	} +   	/* Write RTE to the stream. */  	num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifp);  	if (num == rtemax) @@ -2419,6 +2506,14 @@ rip_redistribute_withdraw (int type)  	    RIP_TIMER_OFF (rinfo->t_timeout);  	    rinfo->flags |= RIP_RTF_CHANGED; +	    if (IS_RIP_DEBUG_EVENT) { +              struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p; + +              zlog_info ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]", +                         inet_ntoa(p->prefix), p->prefixlen, +                         ifindex2ifname(rinfo->ifindex)); +	    } +  	    rip_event (RIP_TRIGGERED_UPDATE, 0);  	  }        } @@ -2775,6 +2870,17 @@ DEFUN (no_rip_timers,    return CMD_SUCCESS;  } + +ALIAS (no_rip_timers, +       no_rip_timers_val_cmd, +       "no timers basic <0-65535> <0-65535> <0-65535>", +       NO_STR +       "Adjust routing timers\n" +       "Basic routing protocol update timers\n" +       "Routing table update timer value in second. Default is 30.\n" +       "Routing information timeout timer. Default is 180.\n" +       "Garbage collection timer. Default is 120.\n") +  struct route_table *rip_distance_table; @@ -3109,11 +3215,12 @@ DEFUN (show_ip_rip,    if (! rip)      return CMD_SUCCESS; -  vty_out (vty, "Codes: R - RIP, C - connected, O - OSPF, B - BGP%s" -	   "      (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s" +  vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s" +	   "Sub-codes:%s" +           "      (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"  	   "      (i) - interface%s%s" -	   "     Network            Next Hop         Metric From            Time%s", -	   VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); +	   "     Network         Next Hop         Metric From            Tag Time%s", +	   VTY_NEWLINE, VTY_NEWLINE,  VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);    for (np = route_top (rip->table); np; np = route_next (np))      if ((rinfo = np->info) != NULL) @@ -3126,7 +3233,7 @@ DEFUN (show_ip_rip,  		       rip_route_type_print (rinfo->sub_type),  		       inet_ntoa (np->p.u.prefix4), np->p.prefixlen); -	len = 24 - len; +	len = 21 - len;  	if (len > 0)  	  vty_out (vty, "%*s", len, " "); @@ -3142,15 +3249,20 @@ DEFUN (show_ip_rip,  	    (rinfo->sub_type == RIP_ROUTE_RTE))  	  {  	    vty_out (vty, "%-15s ", inet_ntoa (rinfo->from)); +	    vty_out (vty, "%3d ", rinfo->tag);  	    rip_vty_out_uptime (vty, rinfo);  	  }  	else if (rinfo->metric == RIP_METRIC_INFINITY)  	  {  	    vty_out (vty, "self            "); +	    vty_out (vty, "%3d ", rinfo->tag);  	    rip_vty_out_uptime (vty, rinfo);  	  }  	else -	  vty_out (vty, "self"); +	  { +	    vty_out (vty, "self            "); +	    vty_out (vty, "%3d", rinfo->tag); +	  }  	vty_out (vty, "%s", VTY_NEWLINE);        } @@ -3168,11 +3280,13 @@ rip_next_thread_timer (struct thread *thread)    return thread->u.sands.tv_sec - timer_now.tv_sec;  } -DEFUN (show_ip_protocols_rip, -       show_ip_protocols_rip_cmd, -       "show ip protocols", +/* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */ +DEFUN (show_ip_rip_status, +       show_ip_rip_status_cmd, +       "show ip rip status",         SHOW_STR         IP_STR +       "Show RIP routes\n"         "IP routing protocol process parameters and statistics\n")  {    listnode node; @@ -3307,6 +3421,9 @@ config_write_rip (struct vty *vty)        /* Distribute configuration. */        write += config_write_distribute (vty); +      /* Interface routemap configuration */ +      write += config_write_if_rmap (vty); +        /* Distance configuration. */        if (rip->distance)  	vty_out (vty, " distance %d%s", rip->distance, VTY_NEWLINE); @@ -3538,6 +3655,83 @@ rip_reset ()    rip_zclient_reset ();  } +void +rip_if_rmap_update (struct if_rmap *if_rmap) +{ +  struct interface *ifp; +  struct rip_interface *ri; +  struct route_map *rmap; + +  ifp = if_lookup_by_name (if_rmap->ifname); +  if (ifp == NULL) +    return; + +  ri = ifp->info; + +  if (if_rmap->routemap[IF_RMAP_IN]) +    { +      rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]); +      if (rmap) +	ri->routemap[IF_RMAP_IN] = rmap; +      else +	ri->routemap[IF_RMAP_IN] = NULL; +    } +  else +    ri->routemap[RIP_FILTER_IN] = NULL; + +  if (if_rmap->routemap[IF_RMAP_OUT]) +    { +      rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]); +      if (rmap) +	ri->routemap[IF_RMAP_OUT] = rmap; +      else +	ri->routemap[IF_RMAP_OUT] = NULL; +    } +  else +    ri->routemap[RIP_FILTER_OUT] = NULL; +} + +void +rip_if_rmap_update_interface (struct interface *ifp) +{ +  struct if_rmap *if_rmap; + +  if_rmap = if_rmap_lookup (ifp->name); +  if (if_rmap) +    rip_if_rmap_update (if_rmap); +} + +void +rip_routemap_update_redistribute (void) +{ +  int i; + +  if (rip) +    { +      for (i = 0; i < ZEBRA_ROUTE_MAX; i++)  +	{ +	  if (rip->route_map[i].name) +	    rip->route_map[i].map =  +	      route_map_lookup_by_name (rip->route_map[i].name); +	} +    } +} + +void +rip_routemap_update () +{ +  struct interface *ifp; +  listnode node; + +  for (node = listhead (iflist); node; nextnode (node)) +    { +      ifp = getdata (node); +      rip_if_rmap_update_interface (ifp); +    } + +  rip_routemap_update_redistribute (); +} +  /* Allocate new rip structure and set default value. */  void  rip_init () @@ -3550,9 +3744,9 @@ rip_init ()    /* Install rip commands. */    install_element (VIEW_NODE, &show_ip_rip_cmd); -  install_element (VIEW_NODE, &show_ip_protocols_rip_cmd); +  install_element (VIEW_NODE, &show_ip_rip_status_cmd);    install_element (ENABLE_NODE, &show_ip_rip_cmd); -  install_element (ENABLE_NODE, &show_ip_protocols_rip_cmd); +  install_element (ENABLE_NODE, &show_ip_rip_status_cmd);    install_element (CONFIG_NODE, &router_rip_cmd);    install_element (CONFIG_NODE, &no_router_rip_cmd); @@ -3565,6 +3759,7 @@ rip_init ()    install_element (RIP_NODE, &no_rip_default_metric_val_cmd);    install_element (RIP_NODE, &rip_timers_cmd);    install_element (RIP_NODE, &no_rip_timers_cmd); +  install_element (RIP_NODE, &no_rip_timers_val_cmd);    install_element (RIP_NODE, &rip_route_cmd);    install_element (RIP_NODE, &no_rip_route_cmd);    install_element (RIP_NODE, &rip_distance_cmd); @@ -3577,10 +3772,6 @@ rip_init ()    /* Debug related init. */    rip_debug_init (); -  /* Filter related init. */ -  rip_route_map_init (); -  rip_offset_init (); -    /* SNMP init. */  #ifdef HAVE_SNMP    rip_snmp_init (); @@ -3601,6 +3792,17 @@ rip_init ()    distribute_list_add_hook (rip_distribute_update);    distribute_list_delete_hook (rip_distribute_update); +  /* Route-map */ +  rip_route_map_init (); +  rip_offset_init (); + +  route_map_add_hook (rip_routemap_update); +  route_map_delete_hook (rip_routemap_update); + +  if_rmap_init (RIP_NODE); +  if_rmap_hook_add (rip_if_rmap_update); +  if_rmap_hook_delete (rip_if_rmap_update); +    /* Distance control. */    rip_distance_table = route_table_init ();  } diff --git a/ripd/ripd.h b/ripd/ripd.h index 112e1cbf..260ea469 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -199,6 +199,7 @@ struct rip_info    struct in_addr nexthop_out;    u_char metric_set;    u_int32_t metric_out; +  u_short tag_out;    unsigned int ifindex_out;    struct route_node *rp; @@ -211,6 +212,12 @@ struct rip_info  #endif /* NEW_RIP_TABLE */  }; +typedef enum { +  RIP_NO_SPLIT_HORIZON = 0, +  RIP_SPLIT_HORIZON, +  RIP_SPLIT_HORIZON_POISONED_REVERSE +} split_horizon_policy_t; +  /* RIP specific interface configuration. */  struct rip_interface  { @@ -239,8 +246,8 @@ struct rip_interface    char *key_chain;    /* Split horizon flag. */ -  int split_horizon; -  int split_horizon_default; +  split_horizon_policy_t split_horizon; +  split_horizon_policy_t split_horizon_default;    /* For filter type slot. */  #define RIP_FILTER_IN  0 @@ -253,6 +260,9 @@ struct rip_interface    /* Prefix-list. */    struct prefix_list *prefix[RIP_FILTER_MAX]; +  /* Route-map. */ +  struct route_map *routemap[RIP_FILTER_MAX]; +    /* Wake up thread. */    struct thread *t_wakeup; @@ -369,6 +379,7 @@ void rip_zebra_ipv4_add (struct prefix_ipv4 *, struct in_addr *, u_int32_t, u_ch  void rip_zebra_ipv4_delete (struct prefix_ipv4 *, struct in_addr *, u_int32_t);  void rip_interface_multicast_set (int, struct interface *);  void rip_distribute_update_interface (struct interface *); +void rip_if_rmap_update_interface (struct interface *);  int config_write_rip_network (struct vty *, int);  int config_write_rip_offset_list (struct vty *);  | 
