diff options
| author | Avneesh Sachdev <avneesh@opensourcerouting.org> | 2012-04-09 00:25:15 -0700 | 
|---|---|---|
| committer | Avneesh Sachdev <avneesh@opensourcerouting.org> | 2012-04-09 00:25:15 -0700 | 
| commit | 3cf6c2b4e43f44a977d218c96c26250654ae333e (patch) | |
| tree | e017cde2015fbf3ef6c250327428d7c6152aa8f7 /zebra | |
| parent | 01d7ff0a2166a422c56bd26f04fc22832a9e690b (diff) | |
| parent | e96b312150d8e376c1ef463793d1929eca3618d5 (diff) | |
Merge branch 'quagga' into google-bgp-multipath
Conflicts:
	bgpd/bgp_route.c
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/.cvsignore | 13 | ||||
| -rw-r--r-- | zebra/client_main.c | 1 | ||||
| -rw-r--r-- | zebra/connected.c | 8 | ||||
| -rw-r--r-- | zebra/if_netlink.c | 2 | ||||
| -rw-r--r-- | zebra/interface.c | 24 | ||||
| -rw-r--r-- | zebra/interface.h | 17 | ||||
| -rw-r--r-- | zebra/ipforward_proc.c | 9 | ||||
| -rw-r--r-- | zebra/irdp_interface.c | 3 | ||||
| -rw-r--r-- | zebra/kernel_socket.c | 28 | ||||
| -rw-r--r-- | zebra/main.c | 12 | ||||
| -rw-r--r-- | zebra/redistribute.c | 46 | ||||
| -rw-r--r-- | zebra/rib.h | 11 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 24 | ||||
| -rw-r--r-- | zebra/rtadv.c | 338 | ||||
| -rw-r--r-- | zebra/rtadv.h | 6 | ||||
| -rw-r--r-- | zebra/rtread_getmsg.c | 2 | ||||
| -rw-r--r-- | zebra/rtread_netlink.c | 3 | ||||
| -rw-r--r-- | zebra/rtread_proc.c | 2 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 102 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 163 | ||||
| -rw-r--r-- | zebra/zserv.c | 81 | ||||
| -rw-r--r-- | zebra/zserv.h | 2 | 
22 files changed, 588 insertions, 309 deletions
| diff --git a/zebra/.cvsignore b/zebra/.cvsignore deleted file mode 100644 index 59c5889e..00000000 --- a/zebra/.cvsignore +++ /dev/null @@ -1,13 +0,0 @@ -Makefile -Makefile.in -*.o -zebra -zebra.conf -client -tags -TAGS -.deps -.nfs* -.libs -.arch-inventory -.arch-ids diff --git a/zebra/client_main.c b/zebra/client_main.c index ce01231f..8b95907b 100644 --- a/zebra/client_main.c +++ b/zebra/client_main.c @@ -115,6 +115,7 @@ struct zebra_info    { "static", ZEBRA_ROUTE_STATIC },    { "rip",    ZEBRA_ROUTE_RIP },    { "ripng",  ZEBRA_ROUTE_RIPNG }, +  { "babel",  ZEBRA_ROUTE_BABEL },    { "ospf",   ZEBRA_ROUTE_OSPF },    { "ospf6",  ZEBRA_ROUTE_OSPF6 },    { "bgp",    ZEBRA_ROUTE_BGP }, diff --git a/zebra/connected.c b/zebra/connected.c index 95399fa1..f699b147 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -189,7 +189,7 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc)      return;    rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex, -	RT_TABLE_MAIN, ifp->metric, 0); +	RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);    rib_update ();  } @@ -295,7 +295,7 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc)      return;    /* Same logic as for connected_up_ipv4(): push the changes into the head. */ -  rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); +  rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST);    rib_update ();  } @@ -343,7 +343,7 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc)  #endif    rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN, -                ifp->metric, 0); +                ifp->metric, 0, SAFI_UNICAST);    rib_update ();  } @@ -417,7 +417,7 @@ connected_down_ipv6 (struct interface *ifp, struct connected *ifc)    if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))      return; -  rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); +  rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST);    rib_update ();  } diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 701c81b6..86bd8ffe 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -22,6 +22,8 @@  #include <zebra.h> +#include "zebra/zserv.h" +  extern int interface_lookup_netlink (void);  /* Interface information read by netlink. */ diff --git a/zebra/interface.c b/zebra/interface.c index 03e7ff71..22422594 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -76,9 +76,9 @@ if_zebra_new_hook (struct interface *ifp)      rtadv->AdvReachableTime = 0;      rtadv->AdvRetransTimer = 0;      rtadv->AdvCurHopLimit = 0; -    rtadv->AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME; +    rtadv->AdvDefaultLifetime = -1; /* derive from MaxRtrAdvInterval */      rtadv->HomeAgentPreference = 0; -    rtadv->HomeAgentLifetime = RTADV_ADV_DEFAULT_LIFETIME; +    rtadv->HomeAgentLifetime = -1; /* derive from AdvDefaultLifetime */      rtadv->AdvIntervalOption = 0;      rtadv->DefaultPreference = RTADV_PREF_MEDIUM; @@ -216,7 +216,7 @@ if_subnet_delete (struct interface *ifp, struct connected *ifc)   * interface will affect only the primary interface/address on Solaris.   ************************End Solaris flags hacks ***********************   */ -static inline void +static void  if_flags_mangle (struct interface *ifp, uint64_t *newflags)  {  #ifdef SUNOS_5 @@ -630,8 +630,12 @@ nd_dump_vty (struct vty *vty, struct interface *ifp)          vty_out (vty, "  ND router advertisements are sent every "  			"%d seconds%s", interval / 1000,  		 VTY_NEWLINE); -      vty_out (vty, "  ND router advertisements live for %d seconds%s", -	       rtadv->AdvDefaultLifetime, VTY_NEWLINE); +      if (rtadv->AdvDefaultLifetime != -1) +	vty_out (vty, "  ND router advertisements live for %d seconds%s", +		 rtadv->AdvDefaultLifetime, VTY_NEWLINE); +      else +	vty_out (vty, "  ND router advertisements lifetime tracks ra-interval%s", +		 VTY_NEWLINE);        vty_out (vty, "  ND router advertisement default router preference is "  			"%s%s", rtadv_pref_strs[rtadv->DefaultPreference],  		 VTY_NEWLINE); @@ -642,9 +646,19 @@ nd_dump_vty (struct vty *vty, struct interface *ifp)  	vty_out (vty, "  Hosts use stateless autoconfig for addresses.%s",  		 VTY_NEWLINE);        if (rtadv->AdvHomeAgentFlag) +      {        	vty_out (vty, "  ND router advertisements with "  				"Home Agent flag bit set.%s",  		 VTY_NEWLINE); +	if (rtadv->HomeAgentLifetime != -1) +	  vty_out (vty, "  Home Agent lifetime is %u seconds%s", +	           rtadv->HomeAgentLifetime, VTY_NEWLINE); +	else +	  vty_out (vty, "  Home Agent lifetime tracks ra-lifetime%s", +	           VTY_NEWLINE); +	vty_out (vty, "  Home Agent preference is %u%s", +	         rtadv->HomeAgentPreference, VTY_NEWLINE); +      }        if (rtadv->AdvIntervalOption)        	vty_out (vty, "  ND router advertisements with Adv. Interval option.%s",  		 VTY_NEWLINE); diff --git a/zebra/interface.h b/zebra/interface.h index 0cf66403..0777a2fa 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -46,7 +46,7 @@  #endif  #ifdef RTADV -/* Router advertisement parameter.  From RFC2461, RFC3775 and RFC4191. */ +/* Router advertisement parameter.  From RFC4861, RFC6275 and RFC4191. */  struct rtadvconf  {    /* A flag indicating whether or not the router sends periodic Router @@ -56,8 +56,8 @@ struct rtadvconf    /* The maximum time allowed between sending unsolicited multicast       Router Advertisements from the interface, in milliseconds. -     MUST be no less than 70 ms (RFC3775, section 7.4) and no greater  -     than 1800000 ms (See RFC2461). +     MUST be no less than 70 ms [RFC6275 7.5] and no greater +     than 1800000 ms [RFC4861 6.2.1].       Default: 600000 milliseconds */    int MaxRtrAdvInterval; @@ -65,11 +65,11 @@ struct rtadvconf    /* The minimum time allowed between sending unsolicited multicast       Router Advertisements from the interface, in milliseconds. -     MUST be no less than 30 ms (See RFC3775, section 7.4).  +     MUST be no less than 30 ms [RFC6275 7.5].       MUST be no greater than .75 * MaxRtrAdvInterval.       Default: 0.33 * MaxRtrAdvInterval */ -  int MinRtrAdvInterval; +  int MinRtrAdvInterval; /* This field is currently unused. */  #define RTADV_MIN_RTR_ADV_INTERVAL (0.33 * RTADV_MAX_RTR_ADV_INTERVAL)    /* Unsolicited Router Advertisements' interval timer. */ @@ -131,8 +131,7 @@ struct rtadvconf       Default: 3 * MaxRtrAdvInterval */    int AdvDefaultLifetime; -#define RTADV_ADV_DEFAULT_LIFETIME (3 * RTADV_MAX_RTR_ADV_INTERVAL) - +#define RTADV_MAX_RTRLIFETIME 9000 /* 2.5 hours */    /* A list of prefixes to be placed in Prefix Information options in       Router Advertisement messages sent from the interface. @@ -144,7 +143,7 @@ struct rtadvconf    struct list *AdvPrefixList;    /* The TRUE/FALSE value to be placed in the "Home agent" -     flag field in the Router Advertisement.  See [RFC3775 7.1]. +     flag field in the Router Advertisement.  See [RFC6275 7.1].       Default: FALSE */    int AdvHomeAgentFlag; @@ -167,7 +166,7 @@ struct rtadvconf  #define RTADV_MAX_HALIFETIME 65520 /* 18.2 hours */    /* The TRUE/FALSE value to insert or not an Advertisement Interval -     option. See [RFC 3775 7.3] +     option. See [RFC 6275 7.3]       Default: FALSE */    int AdvIntervalOption; diff --git a/zebra/ipforward_proc.c b/zebra/ipforward_proc.c index 73846137..2876eded 100644 --- a/zebra/ipforward_proc.c +++ b/zebra/ipforward_proc.c @@ -45,7 +45,6 @@ ipforward (void)  {    FILE *fp;    int ipforwarding = 0; -  char *pnt;    char buf[10];    fp = fopen (proc_net_snmp, "r"); @@ -59,8 +58,8 @@ ipforward (void)    /* Get ip_statistics.IpForwarding :        1 => ip forwarding enabled        2 => ip forwarding off. */ -  pnt = fgets (buf, 6, fp); -  sscanf (buf, "Ip: %d", &ipforwarding); +  if (fgets (buf, 6, fp)) +    sscanf (buf, "Ip: %d", &ipforwarding);    fclose(fp); @@ -140,8 +139,8 @@ ipforward_ipv6 (void)    if (fp == NULL)      return -1; -  fgets (buf, 2, fp); -  sscanf (buf, "%d", &ipforwarding); +  if (fgets (buf, 2, fp)) +    sscanf (buf, "%d", &ipforwarding);    fclose (fp);    return ipforwarding; diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c index 8742b62b..6403830b 100644 --- a/zebra/irdp_interface.c +++ b/zebra/irdp_interface.c @@ -99,14 +99,11 @@ if_group (struct interface *ifp,  	  u_int32_t group,   	  int add_leave)  { -  struct zebra_if *zi;    struct ip_mreq m;    struct prefix *p;    int ret;    char b1[INET_ADDRSTRLEN]; -  zi = ifp->info; -    memset (&m, 0, sizeof (m));    m.imr_multiaddr.s_addr = htonl (group);    p = irdp_get_prefix(ifp); diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index feeaf5d0..b7061e76 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -319,6 +319,7 @@ int  ifm_read (struct if_msghdr *ifm)  {    struct interface *ifp = NULL; +  struct sockaddr_dl *sdl;    char ifname[IFNAMSIZ];    short ifnlen = 0;    caddr_t *cp; @@ -356,6 +357,7 @@ ifm_read (struct if_msghdr *ifm)    RTA_ADDR_GET (NULL, RTA_GATEWAY, ifm->ifm_addrs, cp);    RTA_ATTR_GET (NULL, RTA_NETMASK, ifm->ifm_addrs, cp);    RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifm_addrs, cp); +  sdl = (struct sockaddr_dl *)cp;    RTA_NAME_GET (ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen);    RTA_ADDR_GET (NULL, RTA_IFA, ifm->ifm_addrs, cp);    RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifm_addrs, cp); @@ -454,6 +456,16 @@ ifm_read (struct if_msghdr *ifm)  #endif /* __bsdi__ */        if_get_metric (ifp); +      /* +       * XXX sockaddr_dl contents can be larger than the structure +       * definition, so the user of the stored structure must be +       * careful not to read off the end. +       * +       * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid +       */ +      if (ifnlen) +	memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl)); +        if_add_update (ifp);      }    else @@ -606,7 +618,7 @@ ifam_read_mesg (struct ifa_msghdr *ifm,    /* Assert read up end point matches to end point */    if (pnt != end) -    zlog_warn ("ifam_read() does't read all socket data"); +    zlog_warn ("ifam_read() doesn't read all socket data");  }  /* Interface's address information get. */ @@ -754,7 +766,7 @@ rtm_read_mesg (struct rt_msghdr *rtm,    /* Assert read up to the end of pointer. */    if (pnt != end)  -      zlog (NULL, LOG_WARNING, "rtm_read() does't read all socket data."); +      zlog (NULL, LOG_WARNING, "rtm_read() doesn't read all socket data.");    return rtm->rtm_flags;  } @@ -894,16 +906,16 @@ rtm_read (struct rt_msghdr *rtm)         */        if (rtm->rtm_type == RTM_CHANGE)          rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, -                         NULL, 0, 0); +                         NULL, 0, 0, SAFI_UNICAST);        if (rtm->rtm_type == RTM_GET             || rtm->rtm_type == RTM_ADD            || rtm->rtm_type == RTM_CHANGE)  	rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags,  -		      &p, &gate.sin.sin_addr, NULL, 0, 0, 0, 0); +		      &p, &gate.sin.sin_addr, NULL, 0, 0, 0, 0, SAFI_UNICAST);        else  	rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags,  -		      &p, &gate.sin.sin_addr, 0, 0); +		      &p, &gate.sin.sin_addr, 0, 0, SAFI_UNICAST);      }  #ifdef HAVE_IPV6    if (dest.sa.sa_family == AF_INET6) @@ -936,16 +948,16 @@ rtm_read (struct rt_msghdr *rtm)         */        if (rtm->rtm_type == RTM_CHANGE)          rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, -                         NULL, 0, 0); +                         NULL, 0, 0, SAFI_UNICAST);        if (rtm->rtm_type == RTM_GET             || rtm->rtm_type == RTM_ADD            || rtm->rtm_type == RTM_CHANGE)  	rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, -		      &p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0); +		      &p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0, SAFI_UNICAST);        else  	rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, -			 &p, &gate.sin6.sin6_addr, ifindex, 0); +			 &p, &gate.sin6.sin6_addr, ifindex, 0, SAFI_UNICAST);      }  #endif /* HAVE_IPV6 */  } diff --git a/zebra/main.c b/zebra/main.c index d829c046..5f26ce24 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -71,6 +71,7 @@ struct option longopts[] =    { "keep_kernel", no_argument,       NULL, 'k'},    { "config_file", required_argument, NULL, 'f'},    { "pid_file",    required_argument, NULL, 'i'}, +  { "socket",      required_argument, NULL, 'z'},    { "help",        no_argument,       NULL, 'h'},    { "vty_addr",    required_argument, NULL, 'A'},    { "vty_port",    required_argument, NULL, 'P'}, @@ -128,6 +129,7 @@ usage (char *progname, int status)  	      "-d, --daemon       Runs in daemon mode\n"\  	      "-f, --config_file  Set configuration file name\n"\  	      "-i, --pid_file     Set process identifier file name\n"\ +	      "-z, --socket       Set path of zebra socket\n"\  	      "-k, --keep_kernel  Don't delete old routes which installed by "\  				  "zebra.\n"\  	      "-C, --dryrun       Check configuration for validity and exit\n"\ @@ -214,6 +216,7 @@ main (int argc, char **argv)    char *config_file = NULL;    char *progname;    struct thread thread; +  char *zserv_path = NULL;    /* Set umask before anything for security */    umask (0027); @@ -229,9 +232,9 @@ main (int argc, char **argv)        int opt;  #ifdef HAVE_NETLINK   -      opt = getopt_long (argc, argv, "bdkf:i:hA:P:ru:g:vs:C", longopts, 0); +      opt = getopt_long (argc, argv, "bdkf:i:z:hA:P:ru:g:vs:C", longopts, 0);  #else -      opt = getopt_long (argc, argv, "bdkf:i:hA:P:ru:g:vC", longopts, 0); +      opt = getopt_long (argc, argv, "bdkf:i:z:hA:P:ru:g:vC", longopts, 0);  #endif /* HAVE_NETLINK */        if (opt == EOF) @@ -261,6 +264,9 @@ main (int argc, char **argv)          case 'i':            pid_file = optarg;            break; +	case 'z': +	  zserv_path = optarg; +	  break;  	case 'P':  	  /* Deal with atoi() returning 0 on failure, and zebra not  	     listening on zebra port... */ @@ -386,7 +392,7 @@ main (int argc, char **argv)    pid = getpid ();    /* This must be done only after locking pidfile (bug #403). */ -  zebra_zserv_socket_init (); +  zebra_zserv_socket_init (zserv_path);    /* Make vty server socket. */    vty_serv_sock (vty_addr, vty_port, ZEBRA_VTYSH_PATH); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index a8107aeb..4276f1d0 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -245,26 +245,15 @@ zebra_redistribute_add (int command, struct zserv *client, int length)    type = stream_getc (client->ibuf); -  switch (type) +  if (type == 0 || type >= ZEBRA_ROUTE_MAX) +    return; + +  if (! client->redist[type])      { -    case ZEBRA_ROUTE_KERNEL: -    case ZEBRA_ROUTE_CONNECT: -    case ZEBRA_ROUTE_STATIC: -    case ZEBRA_ROUTE_RIP: -    case ZEBRA_ROUTE_RIPNG: -    case ZEBRA_ROUTE_OSPF: -    case ZEBRA_ROUTE_OSPF6: -    case ZEBRA_ROUTE_BGP: -      if (! client->redist[type]) -	{ -	  client->redist[type] = 1; -	  zebra_redistribute (client, type); -	} -      break; -    default: -      break; +      client->redist[type] = 1; +      zebra_redistribute (client, type);      } -}      +}  void  zebra_redistribute_delete (int command, struct zserv *client, int length) @@ -273,22 +262,11 @@ zebra_redistribute_delete (int command, struct zserv *client, int length)    type = stream_getc (client->ibuf); -  switch (type) -    { -    case ZEBRA_ROUTE_KERNEL: -    case ZEBRA_ROUTE_CONNECT: -    case ZEBRA_ROUTE_STATIC: -    case ZEBRA_ROUTE_RIP: -    case ZEBRA_ROUTE_RIPNG: -    case ZEBRA_ROUTE_OSPF: -    case ZEBRA_ROUTE_OSPF6: -    case ZEBRA_ROUTE_BGP: -      client->redist[type] = 0; -      break; -    default: -      break; -    } -}      +  if (type == 0 || type >= ZEBRA_ROUTE_MAX) +    return; + +  client->redist[type] = 0; +}  void  zebra_redistribute_default_add (int command, struct zserv *client, int length) diff --git a/zebra/rib.h b/zebra/rib.h index 887ed3c2..2872fc03 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -249,13 +249,13 @@ extern struct route_table *vrf_static_table (afi_t afi, safi_t safi, u_int32_t i  extern int rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,   			 struct in_addr *gate, struct in_addr *src,  			 unsigned int ifindex, u_int32_t vrf_id, -			 u_int32_t, u_char); +			 u_int32_t, u_char, safi_t); -extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *); +extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t);  extern int rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,  		            struct in_addr *gate, unsigned int ifindex,  -		            u_int32_t); +		            u_int32_t, safi_t safi);  extern struct rib *rib_match_ipv4 (struct in_addr); @@ -266,6 +266,7 @@ extern void rib_weed_tables (void);  extern void rib_sweep_route (void);  extern void rib_close (void);  extern void rib_init (void); +extern unsigned long rib_score_proto (u_char proto);  extern int  static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, @@ -279,11 +280,11 @@ static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,  extern int  rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,  	      struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, -	      u_int32_t metric, u_char distance); +	      u_int32_t metric, u_char distance, safi_t safi);  extern int  rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p, -		 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id); +		 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi);  extern struct rib *rib_lookup_ipv6 (struct in6_addr *); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 7652f80a..f48df2bf 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -723,7 +723,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)        memcpy (&p.prefix, dest, 4);        p.prefixlen = rtm->rtm_dst_len; -      rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0); +      rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0, SAFI_UNICAST);      }  #ifdef HAVE_IPV6    if (rtm->rtm_family == AF_INET6) @@ -734,7 +734,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)        p.prefixlen = rtm->rtm_dst_len;        rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, -		    metric, 0); +		    metric, 0, SAFI_UNICAST);      }  #endif /* HAVE_IPV6 */ @@ -768,6 +768,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)    int index;    int table; +  int metric; +    void *dest;    void *gate;    void *src; @@ -825,6 +827,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)      }    index = 0; +  metric = 0;    dest = NULL;    gate = NULL;    src = NULL; @@ -843,6 +846,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)    if (tb[RTA_PREFSRC])      src = RTA_DATA (tb[RTA_PREFSRC]); +  if (h->nlmsg_type == RTM_NEWROUTE && tb[RTA_PRIORITY]) +    metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); +    if (rtm->rtm_family == AF_INET)      {        struct prefix_ipv4 p; @@ -861,9 +867,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)          }        if (h->nlmsg_type == RTM_NEWROUTE) -        rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, 0, 0); +        rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, metric, 0, SAFI_UNICAST);        else -        rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table); +        rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, SAFI_UNICAST);      }  #ifdef HAVE_IPV6 @@ -889,9 +895,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)          }        if (h->nlmsg_type == RTM_NEWROUTE) -        rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0); +        rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, metric, 0, SAFI_UNICAST);        else -        rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table); +        rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, SAFI_UNICAST);      }  #endif /* HAVE_IPV6 */ @@ -1821,11 +1827,7 @@ extern struct thread_master *master;  static int  kernel_read (struct thread *thread)  { -  int ret; -  int sock; - -  sock = THREAD_FD (thread); -  ret = netlink_parse_info (netlink_information_fetch, &netlink); +  netlink_parse_info (netlink_information_fetch, &netlink);    thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);    return 0; diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 8cc3c4cb..ae5c5a1c 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -163,6 +163,7 @@ rtadv_send_packet (int sock, struct interface *ifp)    struct rtadv_prefix *rprefix;    u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};    struct listnode *node; +  u_int16_t pkt_RouterLifetime;    /*     * Allocate control message bufffer.  This is dynamic because @@ -190,7 +191,7 @@ rtadv_send_packet (int sock, struct interface *ifp)    addr.sin6_len = sizeof (struct sockaddr_in6);  #endif /* SIN6_LEN */    addr.sin6_port = htons (IPPROTO_ICMPV6); -  memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_addr)); +  IPV6_ADDR_COPY (&addr.sin6_addr, all_nodes_addr);    /* Fetch interface information. */    zif = ifp->info; @@ -215,13 +216,32 @@ rtadv_send_packet (int sock, struct interface *ifp)      rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;    if (zif->rtadv.AdvHomeAgentFlag)      rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT; -  rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime); +  /* Note that according to Neighbor Discovery (RFC 4861 [18]), +   * AdvDefaultLifetime is by default based on the value of +   * MaxRtrAdvInterval.  AdvDefaultLifetime is used in the Router Lifetime +   * field of Router Advertisements.  Given that this field is expressed +   * in seconds, a small MaxRtrAdvInterval value can result in a zero +   * value for this field.  To prevent this, routers SHOULD keep +   * AdvDefaultLifetime in at least one second, even if the use of +   * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */ +  pkt_RouterLifetime = zif->rtadv.AdvDefaultLifetime != -1 ? +    zif->rtadv.AdvDefaultLifetime : +    MAX (1, 0.003 * zif->rtadv.MaxRtrAdvInterval); +  rtadv->nd_ra_router_lifetime = htons (pkt_RouterLifetime);    rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);    rtadv->nd_ra_retransmit = htonl (0);    len = sizeof (struct nd_router_advert); -  if (zif->rtadv.AdvHomeAgentFlag) +  /* If both the Home Agent Preference and Home Agent Lifetime are set to +   * their default values specified above, this option SHOULD NOT be +   * included in the Router Advertisement messages sent by this home +   * agent. -- RFC6275, 7.4 */ +  if +  ( +    zif->rtadv.AdvHomeAgentFlag && +    (zif->rtadv.HomeAgentPreference || zif->rtadv.HomeAgentLifetime != -1) +  )      {        struct nd_opt_homeagent_info *ndopt_hai =   	(struct nd_opt_homeagent_info *)(buf + len); @@ -229,7 +249,17 @@ rtadv_send_packet (int sock, struct interface *ifp)        ndopt_hai->nd_opt_hai_len = 1;        ndopt_hai->nd_opt_hai_reserved = 0;        ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference); -      ndopt_hai->nd_opt_hai_lifetime = htons(zif->rtadv.HomeAgentLifetime); +      /* 16-bit unsigned integer.  The lifetime associated with the home +       * agent in units of seconds.  The default value is the same as the +       * Router Lifetime, as specified in the main body of the Router +       * Advertisement.  The maximum value corresponds to 18.2 hours.  A +       * value of 0 MUST NOT be used. -- RFC6275, 7.5 */ +      ndopt_hai->nd_opt_hai_lifetime = htons +      ( +        zif->rtadv.HomeAgentLifetime != -1 ? +        zif->rtadv.HomeAgentLifetime : +        MAX (1, pkt_RouterLifetime) /* 0 is OK for RL, but not for HAL*/ +      );        len += sizeof(struct nd_opt_homeagent_info);      } @@ -267,8 +297,7 @@ rtadv_send_packet (int sock, struct interface *ifp)        pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);        pinfo->nd_opt_pi_reserved2 = 0; -      memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6, -	      sizeof (struct in6_addr)); +      IPV6_ADDR_COPY (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.prefix);  #ifdef DEBUG        { @@ -319,6 +348,17 @@ rtadv_send_packet (int sock, struct interface *ifp)      }  #endif /* HAVE_STRUCT_SOCKADDR_DL */ +  /* MTU */ +  if (zif->rtadv.AdvLinkMTU) +    { +      struct nd_opt_mtu * opt = (struct nd_opt_mtu *) (buf + len); +      opt->nd_opt_mtu_type = ND_OPT_MTU; +      opt->nd_opt_mtu_len = 1; +      opt->nd_opt_mtu_reserved = 0; +      opt->nd_opt_mtu_mtu = htonl (zif->rtadv.AdvLinkMTU); +      len += sizeof (struct nd_opt_mtu); +    } +    msg.msg_name = (void *) &addr;    msg.msg_namelen = sizeof (struct sockaddr_in6);    msg.msg_iov = &iov; @@ -368,7 +408,7 @@ rtadv_timer (struct thread *thread)    for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))      { -      if (if_is_loopback (ifp)) +      if (if_is_loopback (ifp) || ! if_is_operative (ifp))  	continue;        zif = ifp->info; @@ -378,6 +418,8 @@ rtadv_timer (struct thread *thread)  	  zif->rtadv.AdvIntervalTimer -= period;  	  if (zif->rtadv.AdvIntervalTimer <= 0)  	    { +	      /* FIXME: using MaxRtrAdvInterval each time isn't what section +	         6.2.4 of RFC4861 tells to do. */  	      zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;  	      rtadv_send_packet (rtadv->sock, ifp);  	    } @@ -552,19 +594,19 @@ rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)  }  static struct rtadv_prefix * -rtadv_prefix_lookup (struct list *rplist, struct prefix *p) +rtadv_prefix_lookup (struct list *rplist, struct prefix_ipv6 *p)  {    struct listnode *node;    struct rtadv_prefix *rprefix;    for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix)) -    if (prefix_same (&rprefix->prefix, p)) +    if (prefix_same ((struct prefix *) &rprefix->prefix, (struct prefix *) p))        return rprefix;    return NULL;  }  static struct rtadv_prefix * -rtadv_prefix_get (struct list *rplist, struct prefix *p) +rtadv_prefix_get (struct list *rplist, struct prefix_ipv6 *p)  {    struct rtadv_prefix *rprefix; @@ -573,7 +615,7 @@ rtadv_prefix_get (struct list *rplist, struct prefix *p)      return rprefix;    rprefix = rtadv_prefix_new (); -  memcpy (&rprefix->prefix, p, sizeof (struct prefix)); +  memcpy (&rprefix->prefix, p, sizeof (struct prefix_ipv6));    listnode_add (rplist, rprefix);    return rprefix; @@ -681,26 +723,22 @@ DEFUN (no_ipv6_nd_suppress_ra,  DEFUN (ipv6_nd_ra_interval_msec,         ipv6_nd_ra_interval_msec_cmd, -       "ipv6 nd ra-interval msec MILLISECONDS", +       "ipv6 nd ra-interval msec <70-1800000>",         "Interface IPv6 config commands\n"         "Neighbor discovery\n"         "Router Advertisement interval\n"         "Router Advertisement interval in milliseconds\n")  { -  int interval; -  struct interface *ifp; -  struct zebra_if *zif; - -  ifp = (struct interface *) vty->index; -  zif = ifp->info; +  unsigned interval; +  struct interface *ifp = (struct interface *) vty->index; +  struct zebra_if *zif = ifp->info; -  interval = atoi (argv[0]); - -  if (interval <= 0) -    { -      vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +  VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 70, 1800000); +  if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) +  { +    vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE); +    return CMD_WARNING; +  }    if (zif->rtadv.MaxRtrAdvInterval % 1000)      rtadv->adv_msec_if_count--; @@ -717,26 +755,22 @@ DEFUN (ipv6_nd_ra_interval_msec,  DEFUN (ipv6_nd_ra_interval,         ipv6_nd_ra_interval_cmd, -       "ipv6 nd ra-interval SECONDS", +       "ipv6 nd ra-interval <1-1800>",         "Interface IPv6 config commands\n"         "Neighbor discovery\n"         "Router Advertisement interval\n"         "Router Advertisement interval in seconds\n")  { -  int interval; -  struct interface *ifp; -  struct zebra_if *zif; - -  ifp = (struct interface *) vty->index; -  zif = ifp->info; +  unsigned interval; +  struct interface *ifp = (struct interface *) vty->index; +  struct zebra_if *zif = ifp->info; -  interval = atoi (argv[0]); - -  if (interval <= 0) -    { -      vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE); -      return CMD_WARNING; -    } +  VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 1, 1800); +  if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) +  { +    vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE); +    return CMD_WARNING; +  }    if (zif->rtadv.MaxRtrAdvInterval % 1000)      rtadv->adv_msec_if_count--; @@ -775,13 +809,30 @@ DEFUN (no_ipv6_nd_ra_interval,    return CMD_SUCCESS;  } +ALIAS (no_ipv6_nd_ra_interval, +       no_ipv6_nd_ra_interval_val_cmd, +       "no ipv6 nd ra-interval <1-1800>", +       NO_STR +       "Interface IPv6 config commands\n" +       "Neighbor discovery\n" +       "Router Advertisement interval\n") + +ALIAS (no_ipv6_nd_ra_interval, +       no_ipv6_nd_ra_interval_msec_val_cmd, +       "no ipv6 nd ra-interval msec <1-1800000>", +       NO_STR +       "Interface IPv6 config commands\n" +       "Neighbor discovery\n" +       "Router Advertisement interval\n" +       "Router Advertisement interval in milliseconds\n") +  DEFUN (ipv6_nd_ra_lifetime,         ipv6_nd_ra_lifetime_cmd, -       "ipv6 nd ra-lifetime SECONDS", +       "ipv6 nd ra-lifetime <0-9000>",         "Interface IPv6 config commands\n"         "Neighbor discovery\n"         "Router lifetime\n" -       "Router lifetime in seconds\n") +       "Router lifetime in seconds (0 stands for a non-default gw)\n")  {    int lifetime;    struct interface *ifp; @@ -790,11 +841,15 @@ DEFUN (ipv6_nd_ra_lifetime,    ifp = (struct interface *) vty->index;    zif = ifp->info; -  lifetime = atoi (argv[0]); +  VTY_GET_INTEGER_RANGE ("router lifetime", lifetime, argv[0], 0, 9000); -  if (lifetime < 0 || lifetime > 0xffff) +  /* The value to be placed in the Router Lifetime field +   * of Router Advertisements sent from the interface, +   * in seconds.  MUST be either zero or between +   * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */ +  if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval))      { -      vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE); +      vty_out (vty, "This ra-lifetime would conflict with configured ra-interval%s", VTY_NEWLINE);        return CMD_WARNING;      } @@ -817,36 +872,31 @@ DEFUN (no_ipv6_nd_ra_lifetime,    ifp = (struct interface *) vty->index;    zif = ifp->info; -  zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME; +  zif->rtadv.AdvDefaultLifetime = -1;    return CMD_SUCCESS;  } +ALIAS (no_ipv6_nd_ra_lifetime, +       no_ipv6_nd_ra_lifetime_val_cmd, +       "no ipv6 nd ra-lifetime <0-9000>", +       NO_STR +       "Interface IPv6 config commands\n" +       "Neighbor discovery\n" +       "Router lifetime\n" +       "Router lifetime in seconds (0 stands for a non-default gw)\n") +  DEFUN (ipv6_nd_reachable_time,         ipv6_nd_reachable_time_cmd, -       "ipv6 nd reachable-time MILLISECONDS", +       "ipv6 nd reachable-time <1-3600000>",         "Interface IPv6 config commands\n"         "Neighbor discovery\n"         "Reachable time\n"         "Reachable time in milliseconds\n")  { -  u_int32_t rtime; -  struct interface *ifp; -  struct zebra_if *zif; - -  ifp = (struct interface *) vty->index; -  zif = ifp->info; - -  rtime = (u_int32_t) atol (argv[0]); - -  if (rtime > RTADV_MAX_REACHABLE_TIME) -    { -      vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE); -      return CMD_WARNING; -    } - -  zif->rtadv.AdvReachableTime = rtime; - +  struct interface *ifp = (struct interface *) vty->index; +  struct zebra_if *zif = ifp->info; +  VTY_GET_INTEGER_RANGE ("reachable time", zif->rtadv.AdvReachableTime, argv[0], 1, RTADV_MAX_REACHABLE_TIME);    return CMD_SUCCESS;  } @@ -869,31 +919,26 @@ DEFUN (no_ipv6_nd_reachable_time,    return CMD_SUCCESS;  } +ALIAS (no_ipv6_nd_reachable_time, +       no_ipv6_nd_reachable_time_val_cmd, +       "no ipv6 nd reachable-time <1-3600000>", +       NO_STR +       "Interface IPv6 config commands\n" +       "Neighbor discovery\n" +       "Reachable time\n" +       "Reachable time in milliseconds\n") +  DEFUN (ipv6_nd_homeagent_preference,         ipv6_nd_homeagent_preference_cmd, -       "ipv6 nd home-agent-preference PREFERENCE", +       "ipv6 nd home-agent-preference <0-65535>",         "Interface IPv6 config commands\n"         "Neighbor discovery\n"         "Home Agent preference\n" -       "Home Agent preference value 0..65535\n") +       "preference value (default is 0, least preferred)\n")  { -  u_int32_t hapref; -  struct interface *ifp; -  struct zebra_if *zif; - -  ifp = (struct interface *) vty->index; -  zif = ifp->info; - -  hapref = (u_int32_t) atol (argv[0]); - -  if (hapref > 65535) -    { -      vty_out (vty, "Invalid Home Agent preference%s", VTY_NEWLINE); -      return CMD_WARNING; -    } - -  zif->rtadv.HomeAgentPreference = hapref; - +  struct interface *ifp = (struct interface *) vty->index; +  struct zebra_if *zif = ifp->info; +  VTY_GET_INTEGER_RANGE ("home agent preference", zif->rtadv.HomeAgentPreference, argv[0], 0, 65535);    return CMD_SUCCESS;  } @@ -916,31 +961,26 @@ DEFUN (no_ipv6_nd_homeagent_preference,    return CMD_SUCCESS;  } +ALIAS (no_ipv6_nd_homeagent_preference, +       no_ipv6_nd_homeagent_preference_val_cmd, +       "no ipv6 nd home-agent-preference <0-65535>", +       NO_STR +       "Interface IPv6 config commands\n" +       "Neighbor discovery\n" +       "Home Agent preference\n" +       "preference value (default is 0, least preferred)\n") +  DEFUN (ipv6_nd_homeagent_lifetime,         ipv6_nd_homeagent_lifetime_cmd, -       "ipv6 nd home-agent-lifetime SECONDS", +       "ipv6 nd home-agent-lifetime <0-65520>",         "Interface IPv6 config commands\n"         "Neighbor discovery\n"         "Home Agent lifetime\n" -       "Home Agent lifetime in seconds\n") +       "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")  { -  u_int32_t ha_ltime; -  struct interface *ifp; -  struct zebra_if *zif; - -  ifp = (struct interface *) vty->index; -  zif = ifp->info; - -  ha_ltime = (u_int32_t) atol (argv[0]); - -  if (ha_ltime > RTADV_MAX_HALIFETIME) -    { -      vty_out (vty, "Invalid Home Agent Lifetime time%s", VTY_NEWLINE); -      return CMD_WARNING; -    } - -  zif->rtadv.HomeAgentLifetime = ha_ltime; - +  struct interface *ifp = (struct interface *) vty->index; +  struct zebra_if *zif = ifp->info; +  VTY_GET_INTEGER_RANGE ("home agent lifetime", zif->rtadv.HomeAgentLifetime, argv[0], 0, RTADV_MAX_HALIFETIME);    return CMD_SUCCESS;  } @@ -958,11 +998,20 @@ DEFUN (no_ipv6_nd_homeagent_lifetime,    ifp = (struct interface *) vty->index;    zif = ifp->info; -  zif->rtadv.HomeAgentLifetime = 0; +  zif->rtadv.HomeAgentLifetime = -1;    return CMD_SUCCESS;  } +ALIAS (no_ipv6_nd_homeagent_lifetime, +       no_ipv6_nd_homeagent_lifetime_val_cmd, +       "no ipv6 nd home-agent-lifetime <0-65520>", +       NO_STR +       "Interface IPv6 config commands\n" +       "Neighbor discovery\n" +       "Home Agent lifetime\n" +       "Home Agent lifetime in seconds (0 to track ra-lifetime)\n") +  DEFUN (ipv6_nd_managed_config_flag,         ipv6_nd_managed_config_flag_cmd,         "ipv6 nd managed-config-flag", @@ -1137,12 +1186,13 @@ DEFUN (ipv6_nd_prefix,    ifp = (struct interface *) vty->index;    zebra_if = ifp->info; -  ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix); +  ret = str2prefix_ipv6 (argv[0], &rp.prefix);    if (!ret)      {        vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);        return CMD_WARNING;      } +  apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */    rp.AdvOnLinkFlag = 1;    rp.AdvAutonomousFlag = 1;    rp.AdvRouterAddressFlag = 0; @@ -1364,12 +1414,13 @@ DEFUN (no_ipv6_nd_prefix,    ifp = (struct interface *) vty->index;    zebra_if = ifp->info; -  ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix); +  ret = str2prefix_ipv6 (argv[0], &rp.prefix);    if (!ret)      {        vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);        return CMD_WARNING;      } +  apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */    ret = rtadv_prefix_reset (zebra_if, &rp);    if (!ret) @@ -1430,6 +1481,54 @@ DEFUN (no_ipv6_nd_router_preference,    return CMD_SUCCESS;  } +ALIAS (no_ipv6_nd_router_preference, +       no_ipv6_nd_router_preference_val_cmd, +       "no ipv6 nd router-preference (high|medium|low", +       NO_STR +       "Interface IPv6 config commands\n" +       "Neighbor discovery\n" +       "Default router preference\n" +       "High default router preference\n" +       "Low default router preference\n" +       "Medium default router preference (default)\n") + +DEFUN (ipv6_nd_mtu, +       ipv6_nd_mtu_cmd, +       "ipv6 nd mtu <1-65535>", +       "Interface IPv6 config commands\n" +       "Neighbor discovery\n" +       "Advertised MTU\n" +       "MTU in bytes\n") +{ +  struct interface *ifp = (struct interface *) vty->index; +  struct zebra_if *zif = ifp->info; +  VTY_GET_INTEGER_RANGE ("MTU", zif->rtadv.AdvLinkMTU, argv[0], 1, 65535); +  return CMD_SUCCESS; +} + +DEFUN (no_ipv6_nd_mtu, +       no_ipv6_nd_mtu_cmd, +       "no ipv6 nd mtu", +       NO_STR +       "Interface IPv6 config commands\n" +       "Neighbor discovery\n" +       "Advertised MTU\n") +{ +  struct interface *ifp = (struct interface *) vty->index; +  struct zebra_if *zif = ifp->info; +  zif->rtadv.AdvLinkMTU = 0; +  return CMD_SUCCESS; +} + +ALIAS (no_ipv6_nd_mtu, +       no_ipv6_nd_mtu_val_cmd, +       "no ipv6 nd mtu <1-65535>", +       NO_STR +       "Interface IPv6 config commands\n" +       "Neighbor discovery\n" +       "Advertised MTU\n" +       "MTU in bytes\n") +  /* Write configuration about router advertisement. */  void  rtadv_config_write (struct vty *vty, struct interface *ifp) @@ -1463,10 +1562,24 @@ rtadv_config_write (struct vty *vty, struct interface *ifp)        vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,  	     VTY_NEWLINE); -  if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME) +  if (zif->rtadv.AdvIntervalOption) +    vty_out (vty, " ipv6 nd adv-interval-option%s", VTY_NEWLINE); + +  if (zif->rtadv.AdvDefaultLifetime != -1)      vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,  	     VTY_NEWLINE); +  if (zif->rtadv.HomeAgentPreference) +    vty_out (vty, " ipv6 nd home-agent-preference %u%s", +	     zif->rtadv.HomeAgentPreference, VTY_NEWLINE); + +  if (zif->rtadv.HomeAgentLifetime != -1) +    vty_out (vty, " ipv6 nd home-agent-lifetime %u%s", +	     zif->rtadv.HomeAgentLifetime, VTY_NEWLINE); + +  if (zif->rtadv.AdvHomeAgentFlag) +    vty_out (vty, " ipv6 nd home-agent-config-flag%s", VTY_NEWLINE); +    if (zif->rtadv.AdvReachableTime)      vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,  	     VTY_NEWLINE); @@ -1482,10 +1595,13 @@ rtadv_config_write (struct vty *vty, struct interface *ifp)  	     rtadv_pref_strs[zif->rtadv.DefaultPreference],  	     VTY_NEWLINE); +  if (zif->rtadv.AdvLinkMTU) +    vty_out (vty, " ipv6 nd mtu %d%s", zif->rtadv.AdvLinkMTU, VTY_NEWLINE); +    for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))      {        vty_out (vty, " ipv6 nd prefix %s/%d", -	       inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,  +	       inet_ntop (AF_INET6, &rprefix->prefix.prefix,  			  (char *) buf, INET6_ADDRSTRLEN),  	       rprefix->prefix.prefixlen);        if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||  @@ -1572,10 +1688,14 @@ rtadv_init (void)    install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd); +  install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_val_cmd); +  install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_msec_val_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd); +  install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_val_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd); +  install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_val_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd); @@ -1584,8 +1704,10 @@ rtadv_init (void)    install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd); +  install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_val_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd); +  install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_val_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd); @@ -1605,6 +1727,10 @@ rtadv_init (void)    install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);    install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);    install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd); +  install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_val_cmd); +  install_element (INTERFACE_NODE, &ipv6_nd_mtu_cmd); +  install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_cmd); +  install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_val_cmd);  }  static int diff --git a/zebra/rtadv.h b/zebra/rtadv.h index d8d263d0..564a4c66 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -30,7 +30,7 @@  struct rtadv_prefix  {    /* Prefix to be advertised. */ -  struct prefix prefix; +  struct prefix_ipv6 prefix;    /* The value to be placed in the Valid Lifetime in the Prefix */    u_int32_t AdvValidLifetime; @@ -47,7 +47,7 @@ struct rtadv_prefix    /* The value to be placed in the Autonomous Flag. */    int AdvAutonomousFlag; -  /* The value to be placed in the Router Address Flag (RFC3775 7.2). */ +  /* The value to be placed in the Router Address Flag [RFC6275 7.2]. */    int AdvRouterAddressFlag;  #ifndef ND_OPT_PI_FLAG_RADDR  #define ND_OPT_PI_FLAG_RADDR         0x20 @@ -58,7 +58,7 @@ struct rtadv_prefix  extern void rtadv_config_write (struct vty *, struct interface *);  extern void rtadv_init (void); -/* draft-ietf-mip6-mipext-advapi-03 */ +/* RFC4584 Extension to Sockets API for Mobile IPv6 */  #ifndef ND_OPT_ADV_INTERVAL  #define ND_OPT_ADV_INTERVAL	7   /* Adv Interval Option */ diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index 3e065c6f..81bf0de6 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -90,7 +90,7 @@ handle_route_entry (mib2_ipRouteEntry_t *routeEntry)  	gateway.s_addr = routeEntry->ipRouteNextHop;  	rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &prefix, -		      &gateway, NULL, 0, 0, 0, 0); +		      &gateway, NULL, 0, 0, 0, 0, SAFI_UNICAST);  }  void diff --git a/zebra/rtread_netlink.c b/zebra/rtread_netlink.c index 44715d94..066e8443 100644 --- a/zebra/rtread_netlink.c +++ b/zebra/rtread_netlink.c @@ -21,6 +21,9 @@   */  #include <zebra.h> + +#include "zebra/zserv.h" +  extern void netlink_route_read (void);  void route_read (void) diff --git a/zebra/rtread_proc.c b/zebra/rtread_proc.c index 1de435a4..07e8491a 100644 --- a/zebra/rtread_proc.c +++ b/zebra/rtread_proc.c @@ -96,7 +96,7 @@ proc_route_read (void)        p.prefixlen = ip_masklen (tmpmask);        sscanf (gate, "%lX", (unsigned long *)&gateway); -      rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gateway, NULL, 0, 0, 0, 0); +      rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gateway, NULL, 0, 0, 0, 0, SAFI_UNICAST);      }    fclose (fp); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 12f3fa5a..f7f4d0a2 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -55,18 +55,20 @@ static const struct  {      int key;    int distance; -} route_info[] = -{ -  {ZEBRA_ROUTE_SYSTEM,    0}, -  {ZEBRA_ROUTE_KERNEL,    0}, -  {ZEBRA_ROUTE_CONNECT,   0}, -  {ZEBRA_ROUTE_STATIC,    1}, -  {ZEBRA_ROUTE_RIP,     120}, -  {ZEBRA_ROUTE_RIPNG,   120}, -  {ZEBRA_ROUTE_OSPF,    110}, -  {ZEBRA_ROUTE_OSPF6,   110}, -  {ZEBRA_ROUTE_ISIS,    115}, -  {ZEBRA_ROUTE_BGP,      20  /* IBGP is 200. */} +} route_info[ZEBRA_ROUTE_MAX] = +{ +  [ZEBRA_ROUTE_SYSTEM]  = {ZEBRA_ROUTE_SYSTEM,    0}, +  [ZEBRA_ROUTE_KERNEL]  = {ZEBRA_ROUTE_KERNEL,    0}, +  [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT,   0}, +  [ZEBRA_ROUTE_STATIC]  = {ZEBRA_ROUTE_STATIC,    1}, +  [ZEBRA_ROUTE_RIP]     = {ZEBRA_ROUTE_RIP,     120}, +  [ZEBRA_ROUTE_RIPNG]   = {ZEBRA_ROUTE_RIPNG,   120}, +  [ZEBRA_ROUTE_OSPF]    = {ZEBRA_ROUTE_OSPF,    110}, +  [ZEBRA_ROUTE_OSPF6]   = {ZEBRA_ROUTE_OSPF6,   110}, +  [ZEBRA_ROUTE_ISIS]    = {ZEBRA_ROUTE_ISIS,    115}, +  [ZEBRA_ROUTE_BGP]     = {ZEBRA_ROUTE_BGP,      20  /* IBGP is 200. */}, +  [ZEBRA_ROUTE_BABEL]   = {ZEBRA_ROUTE_BABEL,    95}, +  /* no entry/default: 150 */  };  /* Vector for routing table.  */ @@ -89,6 +91,11 @@ vrf_alloc (const char *name)    vrf->table[AFI_IP6][SAFI_UNICAST] = route_table_init ();    vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init ();    vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init (); +  vrf->table[AFI_IP][SAFI_MULTICAST] = route_table_init (); +  vrf->table[AFI_IP6][SAFI_MULTICAST] = route_table_init (); +  vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init (); +  vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init (); +    return vrf;  } @@ -1229,6 +1236,7 @@ static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = {    [ZEBRA_ROUTE_ISIS]    = 2,    [ZEBRA_ROUTE_BGP]     = 3,    [ZEBRA_ROUTE_HSLS]    = 4, +  [ZEBRA_ROUTE_BABEL]   = 2,  };  /* Look into the RN and queue it into one or more priority queues, @@ -1492,7 +1500,7 @@ int  rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,   	      struct in_addr *gate, struct in_addr *src,  	      unsigned int ifindex, u_int32_t vrf_id, -	      u_int32_t metric, u_char distance) +	      u_int32_t metric, u_char distance, safi_t safi)  {    struct rib *rib;    struct rib *same = NULL; @@ -1501,7 +1509,7 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,    struct nexthop *nexthop;    /* Lookup table.  */ -  table = vrf_table (AFI_IP, SAFI_UNICAST, 0); +  table = vrf_table (AFI_IP, safi, 0);    if (! table)      return 0; @@ -1511,7 +1519,10 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,    /* Set default distance by route type. */    if (distance == 0)      { -      distance = route_info[type].distance; +      if ((unsigned)type >= sizeof(route_info) / sizeof(route_info[0])) +	distance = 150; +      else +        distance = route_info[type].distance;        /* iBGP distance is 200. */        if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP)) @@ -1747,7 +1758,7 @@ void rib_lookup_and_pushup (struct prefix_ipv4 * p)  }  int -rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib) +rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi)  {    struct route_table *table;    struct route_node *rn; @@ -1755,9 +1766,10 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)    struct nexthop *nexthop;    /* Lookup table.  */ -  table = vrf_table (AFI_IP, SAFI_UNICAST, 0); +  table = vrf_table (AFI_IP, safi, 0);    if (! table)      return 0; +    /* Make it sure prefixlen is applied to the prefix. */    apply_mask_ipv4 (p); @@ -1820,7 +1832,7 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib)  /* XXX factor with rib_delete_ipv6 */  int  rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, -		 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id) +		 struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)  {    struct route_table *table;    struct route_node *rn; @@ -1832,7 +1844,7 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,    char buf2[INET_ADDRSTRLEN];    /* Lookup table.  */ -  table = vrf_table (AFI_IP, SAFI_UNICAST, 0); +  table = vrf_table (AFI_IP, safi, 0);    if (! table)      return 0; @@ -1879,8 +1891,10 @@ rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p,        if (rib->type != type)  	continue;        if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) && -	  nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex) +	  nexthop->type == NEXTHOP_TYPE_IFINDEX)  	{ +	  if (nexthop->ifindex != ifindex) +	    continue;  	  if (rib->refcnt)  	    {  	      rib->refcnt--; @@ -2281,7 +2295,7 @@ rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,  int  rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,  	      struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, -	      u_int32_t metric, u_char distance) +	      u_int32_t metric, u_char distance, safi_t safi)  {    struct rib *rib;    struct rib *same = NULL; @@ -2290,7 +2304,7 @@ rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,    struct nexthop *nexthop;    /* Lookup table.  */ -  table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); +  table = vrf_table (AFI_IP6, safi, 0);    if (! table)      return 0; @@ -2375,7 +2389,7 @@ rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,  /* XXX factor with rib_delete_ipv6 */  int  rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p, -		 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id) +		 struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi)  {    struct route_table *table;    struct route_node *rn; @@ -2390,7 +2404,7 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,    apply_mask_ipv6 (p);    /* Lookup table.  */ -  table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); +  table = vrf_table (AFI_IP6, safi, 0);    if (! table)      return 0; @@ -2427,8 +2441,10 @@ rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,        if (rib->type != type)          continue;        if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) && -	  nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex) +	  nexthop->type == NEXTHOP_TYPE_IFINDEX)  	{ +	  if (nexthop->ifindex != ifindex) +	    continue;  	  if (rib->refcnt)  	    {  	      rib->refcnt--; @@ -2877,7 +2893,41 @@ rib_sweep_route (void)    rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));    rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));  } - + +/* Remove specific by protocol routes from 'table'. */ +static unsigned long +rib_score_proto_table (u_char proto, struct route_table *table) +{ +  struct route_node *rn; +  struct rib *rib; +  struct rib *next; +  unsigned long n = 0; + +  if (table) +    for (rn = route_top (table); rn; rn = route_next (rn)) +      for (rib = rn->info; rib; rib = next) +        { +          next = rib->next; +          if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) +            continue; +          if (rib->type == proto) +            { +              rib_delnode (rn, rib); +              n++; +            } +        } + +  return n; +} + +/* Remove specific by protocol routes. */ +unsigned long +rib_score_proto (u_char proto) +{ +  return  rib_score_proto_table (proto, vrf_table (AFI_IP,  SAFI_UNICAST, 0)) +         +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0)); +} +  /* Close RIB and clean up kernel routes. */  static void  rib_close_table (struct route_table *table) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index ecb5d10a..dafcf75a 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -556,6 +556,7 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn)  #define ONE_WEEK_SECOND 60*60*24*7        if (rib->type == ZEBRA_ROUTE_RIP  	  || rib->type == ZEBRA_ROUTE_OSPF +	  || rib->type == ZEBRA_ROUTE_BABEL  	  || rib->type == ZEBRA_ROUTE_ISIS  	  || rib->type == ZEBRA_ROUTE_BGP)  	{ @@ -774,6 +775,7 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)        if (rib->type == ZEBRA_ROUTE_RIP  	  || rib->type == ZEBRA_ROUTE_OSPF +	  || rib->type == ZEBRA_ROUTE_BABEL  	  || rib->type == ZEBRA_ROUTE_ISIS  	  || rib->type == ZEBRA_ROUTE_BGP)  	{ @@ -802,10 +804,6 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib)      }  } -#define SHOW_ROUTE_V4_HEADER "Codes: K - kernel route, C - connected, " \ -  "S - static, R - RIP, O - OSPF,%s       I - ISIS, B - BGP, " \ -  "> - selected route, * - FIB route%s%s" -  DEFUN (show_ip_route,         show_ip_route_cmd,         "show ip route", @@ -828,8 +826,7 @@ DEFUN (show_ip_route,        {  	if (first)  	  { -	    vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE, -		     VTY_NEWLINE); +	    vty_out (vty, SHOW_ROUTE_V4_HEADER);  	    first = 0;  	  }  	vty_show_ip_route (vty, rn, rib); @@ -871,8 +868,7 @@ DEFUN (show_ip_route_prefix_longer,  	{  	  if (first)  	    { -	      vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, -		       VTY_NEWLINE, VTY_NEWLINE); +	      vty_out (vty, SHOW_ROUTE_V4_HEADER);  	      first = 0;  	    }  	  vty_show_ip_route (vty, rn, rib); @@ -910,8 +906,7 @@ DEFUN (show_ip_route_supernets,  	  {  	    if (first)  	      { -		vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, -			 VTY_NEWLINE, VTY_NEWLINE); +		vty_out (vty, SHOW_ROUTE_V4_HEADER);  		first = 0;  	      }  	    vty_show_ip_route (vty, rn, rib); @@ -922,17 +917,11 @@ DEFUN (show_ip_route_supernets,  DEFUN (show_ip_route_protocol,         show_ip_route_protocol_cmd, -       "show ip route (bgp|connected|isis|kernel|ospf|rip|static)", +       "show ip route " QUAGGA_IP_REDIST_STR_ZEBRA,         SHOW_STR         IP_STR         "IP routing table\n" -       "Border Gateway Protocol (BGP)\n" -       "Connected\n" -       "ISO IS-IS (ISIS)\n" -       "Kernel\n" -       "Open Shortest Path First (OSPF)\n" -       "Routing Information Protocol (RIP)\n" -       "Static routes\n") +       QUAGGA_IP_REDIST_HELP_STR_ZEBRA)  {    int type;    struct route_table *table; @@ -940,21 +929,8 @@ DEFUN (show_ip_route_protocol,    struct rib *rib;    int first = 1; -  if (strncmp (argv[0], "b", 1) == 0) -    type = ZEBRA_ROUTE_BGP; -  else if (strncmp (argv[0], "c", 1) == 0) -    type = ZEBRA_ROUTE_CONNECT; -  else if (strncmp (argv[0], "k", 1) ==0) -    type = ZEBRA_ROUTE_KERNEL; -  else if (strncmp (argv[0], "o", 1) == 0) -    type = ZEBRA_ROUTE_OSPF; -  else if (strncmp (argv[0], "i", 1) == 0) -    type = ZEBRA_ROUTE_ISIS; -  else if (strncmp (argv[0], "r", 1) == 0) -    type = ZEBRA_ROUTE_RIP; -  else if (strncmp (argv[0], "s", 1) == 0) -    type = ZEBRA_ROUTE_STATIC; -  else  +  type = proto_redistnum (AFI_IP, argv[0]); +  if (type < 0)      {        vty_out (vty, "Unknown route type%s", VTY_NEWLINE);        return CMD_WARNING; @@ -971,8 +947,7 @@ DEFUN (show_ip_route_protocol,  	{  	  if (first)  	    { -	      vty_out (vty, SHOW_ROUTE_V4_HEADER, -		       VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); +	      vty_out (vty, SHOW_ROUTE_V4_HEADER);  	      first = 0;  	    }  	  vty_show_ip_route (vty, rn, rib); @@ -1559,6 +1534,7 @@ vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn)  #define ONE_WEEK_SECOND 60*60*24*7        if (rib->type == ZEBRA_ROUTE_RIPNG  	  || rib->type == ZEBRA_ROUTE_OSPF6 +	  || rib->type == ZEBRA_ROUTE_BABEL  	  || rib->type == ZEBRA_ROUTE_ISIS  	  || rib->type == ZEBRA_ROUTE_BGP)  	{ @@ -1738,6 +1714,7 @@ vty_show_ipv6_route (struct vty *vty, struct route_node *rn,        if (rib->type == ZEBRA_ROUTE_RIPNG  	  || rib->type == ZEBRA_ROUTE_OSPF6 +	  || rib->type == ZEBRA_ROUTE_BABEL  	  || rib->type == ZEBRA_ROUTE_ISIS  	  || rib->type == ZEBRA_ROUTE_BGP)  	{ @@ -1766,8 +1743,6 @@ vty_show_ipv6_route (struct vty *vty, struct route_node *rn,      }  } -#define SHOW_ROUTE_V6_HEADER "Codes: K - kernel route, C - connected, S - static, R - RIPng, O - OSPFv3,%s       I - ISIS, B - BGP, * - FIB route.%s%s" -  DEFUN (show_ipv6_route,         show_ipv6_route_cmd,         "show ipv6 route", @@ -1790,7 +1765,7 @@ DEFUN (show_ipv6_route,        {  	if (first)  	  { -	    vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); +	    vty_out (vty, SHOW_ROUTE_V6_HEADER);  	    first = 0;  	  }  	vty_show_ipv6_route (vty, rn, rib); @@ -1832,7 +1807,7 @@ DEFUN (show_ipv6_route_prefix_longer,  	{  	  if (first)  	    { -	      vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); +	      vty_out (vty, SHOW_ROUTE_V6_HEADER);  	      first = 0;  	    }  	  vty_show_ipv6_route (vty, rn, rib); @@ -1842,17 +1817,11 @@ DEFUN (show_ipv6_route_prefix_longer,  DEFUN (show_ipv6_route_protocol,         show_ipv6_route_protocol_cmd, -       "show ipv6 route (bgp|connected|isis|kernel|ospf6|ripng|static)", +       "show ipv6 route " QUAGGA_IP6_REDIST_STR_ZEBRA,         SHOW_STR         IP_STR         "IP routing table\n" -       "Border Gateway Protocol (BGP)\n" -       "Connected\n" -       "ISO IS-IS (ISIS)\n" -       "Kernel\n" -       "Open Shortest Path First (OSPFv3)\n" -       "Routing Information Protocol (RIPng)\n" -       "Static routes\n") +	QUAGGA_IP6_REDIST_HELP_STR_ZEBRA)  {    int type;    struct route_table *table; @@ -1860,21 +1829,8 @@ DEFUN (show_ipv6_route_protocol,    struct rib *rib;    int first = 1; -  if (strncmp (argv[0], "b", 1) == 0) -    type = ZEBRA_ROUTE_BGP; -  else if (strncmp (argv[0], "c", 1) == 0) -    type = ZEBRA_ROUTE_CONNECT; -  else if (strncmp (argv[0], "k", 1) ==0) -    type = ZEBRA_ROUTE_KERNEL; -  else if (strncmp (argv[0], "o", 1) == 0) -    type = ZEBRA_ROUTE_OSPF6; -  else if (strncmp (argv[0], "i", 1) == 0) -    type = ZEBRA_ROUTE_ISIS; -  else if (strncmp (argv[0], "r", 1) == 0) -    type = ZEBRA_ROUTE_RIPNG; -  else if (strncmp (argv[0], "s", 1) == 0) -    type = ZEBRA_ROUTE_STATIC; -  else  +  type = proto_redistnum (AFI_IP6, argv[0]); +  if (type < 0)      {        vty_out (vty, "Unknown route type%s", VTY_NEWLINE);        return CMD_WARNING; @@ -1891,7 +1847,7 @@ DEFUN (show_ipv6_route_protocol,  	{  	  if (first)  	    { -	      vty_out (vty, SHOW_ROUTE_V6_HEADER, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); +	      vty_out (vty, SHOW_ROUTE_V6_HEADER);  	      first = 0;  	    }  	  vty_show_ipv6_route (vty, rn, rib); @@ -1995,6 +1951,80 @@ DEFUN (show_ipv6_route_summary,    return CMD_SUCCESS;  } +/* + * Show IP mroute command to dump the BGP Multicast  + * routing table + */ +DEFUN (show_ip_mroute, +       show_ip_mroute_cmd, +       "show ip mroute", +       SHOW_STR +       IP_STR +       "IP Multicast routing table\n") +{ +  struct route_table *table; +  struct route_node *rn; +  struct rib *rib; +  int first = 1; + +  table = vrf_table (AFI_IP, SAFI_MULTICAST, 0); +  if (! table) +    return CMD_SUCCESS; + +  /* Show all IPv4 routes. */ +  for (rn = route_top (table); rn; rn = route_next (rn)) +    for (rib = rn->info; rib; rib = rib->next) +      { +       if (first) +         { +	   vty_out (vty, SHOW_ROUTE_V4_HEADER); +           first = 0; +         } +       vty_show_ip_route (vty, rn, rib); +      } +  return CMD_SUCCESS; +} + +/* + * Show IPv6 mroute command.Used to dump + * the Multicast routing table. + */ + +DEFUN (show_ipv6_mroute, +       show_ipv6_mroute_cmd, +       "show ipv6 mroute", +       SHOW_STR +       IP_STR +       "IPv6 Multicast routing table\n") +{ +  struct route_table *table; +  struct route_node *rn; +  struct rib *rib; +  int first = 1; + +  table = vrf_table (AFI_IP6, SAFI_MULTICAST, 0); +  if (! table) +    return CMD_SUCCESS; + +  /* Show all IPv6 route. */ +  for (rn = route_top (table); rn; rn = route_next (rn)) +    for (rib = rn->info; rib; rib = rib->next) +      { +       if (first) +         { +	   vty_out (vty, SHOW_ROUTE_V6_HEADER); +           first = 0; +         } +       vty_show_ipv6_route (vty, rn, rib); +      } +  return CMD_SUCCESS; +} + + + + + +  /* Write IPv6 static route configuration. */  static int  static_config_ipv6 (struct vty *vty) @@ -2137,6 +2167,10 @@ zebra_vty_init (void)    install_element (ENABLE_NODE, &show_ip_route_supernets_cmd);    install_element (ENABLE_NODE, &show_ip_route_summary_cmd); +  install_element (VIEW_NODE, &show_ip_mroute_cmd); +  install_element (ENABLE_NODE, &show_ip_mroute_cmd); + +  #ifdef HAVE_IPV6    install_element (CONFIG_NODE, &ipv6_route_cmd);    install_element (CONFIG_NODE, &ipv6_route_flags_cmd); @@ -2166,5 +2200,8 @@ zebra_vty_init (void)    install_element (ENABLE_NODE, &show_ipv6_route_prefix_cmd);    install_element (ENABLE_NODE, &show_ipv6_route_prefix_longer_cmd);    install_element (ENABLE_NODE, &show_ipv6_route_summary_cmd); + +  install_element (VIEW_NODE, &show_ipv6_mroute_cmd); +  install_element (ENABLE_NODE, &show_ipv6_mroute_cmd);  #endif /* HAVE_IPV6 */  } diff --git a/zebra/zserv.c b/zebra/zserv.c index dc3d432b..672dee88 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -64,6 +64,15 @@ zserv_delayed_close(struct thread *thread)    return 0;  } +/* When client connects, it sends hello message + * with promise to send zebra routes of specific type. + * Zebra stores a socket fd of the client into + * this array. And use it to clean up routes that + * client didn't remove for some reasons after closing + * connection. + */ +static int route_type_oaths[ZEBRA_ROUTE_MAX]; +  static int  zserv_flush_data(struct thread *thread)  { @@ -741,6 +750,8 @@ zread_ipv4_add (struct zserv *client, u_short length)    struct stream *s;    unsigned int ifindex;    u_char ifname_len; +  safi_t safi;	 +    /* Get input stream.  */    s = client->ibuf; @@ -752,6 +763,7 @@ zread_ipv4_add (struct zserv *client, u_short length)    rib->type = stream_getc (s);    rib->flags = stream_getc (s);    message = stream_getc (s);  +  safi = stream_getw (s);    rib->uptime = time (NULL);    /* IPv4 prefix. */ @@ -803,7 +815,7 @@ zread_ipv4_add (struct zserv *client, u_short length)    /* Table */    rib->table=zebrad.rtm_table_default; -  rib_add_ipv4_multipath (&p, rib); +  rib_add_ipv4_multipath (&p, rib, safi);    return 0;  } @@ -829,6 +841,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)    api.type = stream_getc (s);    api.flags = stream_getc (s);    api.message = stream_getc (s); +  api.safi = stream_getw (s);    /* IPv4 prefix. */    memset (&p, 0, sizeof (struct prefix_ipv4)); @@ -877,7 +890,7 @@ zread_ipv4_delete (struct zserv *client, u_short length)      api.metric = 0;    rib_delete_ipv4 (api.type, api.flags, &p, &nexthop, ifindex, -		   client->rtm_table); +		   client->rtm_table, api.safi);    return 0;  } @@ -924,6 +937,7 @@ zread_ipv6_add (struct zserv *client, u_short length)    api.type = stream_getc (s);    api.flags = stream_getc (s);    api.message = stream_getc (s); +  api.safi = stream_getw (s);    /* IPv4 prefix. */    memset (&p, 0, sizeof (struct prefix_ipv6)); @@ -965,10 +979,10 @@ zread_ipv6_add (struct zserv *client, u_short length)    if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))      rib_add_ipv6 (api.type, api.flags, &p, NULL, ifindex, zebrad.rtm_table_default, api.metric, -		  api.distance); +		  api.distance, api.safi);    else      rib_add_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, zebrad.rtm_table_default, api.metric, -		  api.distance); +		  api.distance, api.safi);    return 0;  } @@ -991,6 +1005,7 @@ zread_ipv6_delete (struct zserv *client, u_short length)    api.type = stream_getc (s);    api.flags = stream_getc (s);    api.message = stream_getc (s); +  api.safi = stream_getw (s);    /* IPv4 prefix. */    memset (&p, 0, sizeof (struct prefix_ipv6)); @@ -1030,9 +1045,9 @@ zread_ipv6_delete (struct zserv *client, u_short length)      api.metric = 0;    if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) -    rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, client->rtm_table); +    rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, client->rtm_table, api.safi);    else -    rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table); +    rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, client->rtm_table, api.safi);    return 0;  } @@ -1071,6 +1086,49 @@ zread_router_id_delete (struct zserv *client, u_short length)    return 0;  } +/* Tie up route-type and client->sock */ +static void +zread_hello (struct zserv *client) +{ +  /* type of protocol (lib/zebra.h) */ +  u_char proto; +  proto = stream_getc (client->ibuf); + +  /* accept only dynamic routing protocols */ +  if ((proto < ZEBRA_ROUTE_MAX) +  &&  (proto > ZEBRA_ROUTE_STATIC)) +    { +      zlog_notice ("client %d says hello and bids fair to announce only %s routes", +                    client->sock, zebra_route_string(proto)); + +      /* if route-type was binded by other client */ +      if (route_type_oaths[proto]) +        zlog_warn ("sender of %s routes changed %c->%c", +                    zebra_route_string(proto), route_type_oaths[proto], +                    client->sock); + +      route_type_oaths[proto] = client->sock; +    } +} + +/* If client sent routes of specific type, zebra removes it + * and returns number of deleted routes. + */ +static void +zebra_score_rib (int client_sock) +{ +  int i; + +  for (i = ZEBRA_ROUTE_RIP; i < ZEBRA_ROUTE_MAX; i++) +    if (client_sock == route_type_oaths[i]) +      { +        zlog_notice ("client %d disconnected. %lu %s routes removed from the rib", +                      client_sock, rib_score_proto (i), zebra_route_string (i)); +        route_type_oaths[i] = 0; +        break; +      } +} +  /* Close zebra client. */  static void  zebra_client_close (struct zserv *client) @@ -1079,6 +1137,7 @@ zebra_client_close (struct zserv *client)    if (client->sock)      {        close (client->sock); +      zebra_score_rib (client->sock);        client->sock = -1;      } @@ -1283,6 +1342,9 @@ zebra_client_read (struct thread *thread)      case ZEBRA_IPV4_IMPORT_LOOKUP:        zread_ipv4_import_lookup (client, length);        break; +    case ZEBRA_HELLO: +      zread_hello (client); +      break;      default:        zlog_info ("Zebra received unknown command %d", command);        break; @@ -1352,6 +1414,7 @@ zebra_serv ()        return;      } +  memset (&route_type_oaths, 0, sizeof (route_type_oaths));    memset (&addr, 0, sizeof (struct sockaddr_in));    addr.sin_family = AF_INET;    addr.sin_port = htons (ZEBRA_PORT); @@ -1422,6 +1485,8 @@ zebra_serv_un (const char *path)        return;      } +  memset (&route_type_oaths, 0, sizeof (route_type_oaths)); +    /* Make server socket. */    memset (&serv, 0, sizeof (struct sockaddr_un));    serv.sun_family = AF_UNIX; @@ -1733,11 +1798,11 @@ zebra_init (void)  /* Make zebra server socket, wiping any existing one (see bug #403). */  void -zebra_zserv_socket_init (void) +zebra_zserv_socket_init (char *path)  {  #ifdef HAVE_TCP_ZEBRA    zebra_serv ();  #else -  zebra_serv_un (ZEBRA_SERV_PATH); +  zebra_serv_un (path ? path : ZEBRA_SERV_PATH);  #endif /* HAVE_TCP_ZEBRA */  } diff --git a/zebra/zserv.h b/zebra/zserv.h index a7371830..5e8bccac 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -89,7 +89,7 @@ struct zebra_t  /* Prototypes. */  extern void zebra_init (void);  extern void zebra_if_init (void); -extern void zebra_zserv_socket_init (void); +extern void zebra_zserv_socket_init (char *path);  extern void hostinfo_get (void);  extern void rib_init (void);  extern void interface_list (void); | 
