[quagga-dev 8364] Quagga doesn't handle interface routes

Daniel Fahlgren fahlgren at tutus.se
Mon Nov 22 13:12:18 GMT 2010


this is my first post to this list, so please be gentle ;)

I'm having problems with Quagga on FreeBSD 8.1. If I create a tun device
and assign a route to it using the following commands:

ifconfig tun0 create
route add x.x.x.x/y -interface tun0

will that route not be picked up by Quagga. This behavior isn't related
to tun devices only, it is the same if I assign the route to a physical
network card like em0. Yes I know the interface doesn't have an ip and
that the route doesn't have a nexthop.

I have tracked it down to be line 795 in zebra/kernel_socket.c that is
"dropping" the route:

  /* This is connected route. */
  if (! (flags & RTF_GATEWAY))

The only flags that this route has are up and static. If I force it to
continue beyond that point will I end up with a kernel route that is
inactive according to vtysh. But since it is inactive will it not
propagate to the other routes in my test setup. Any pointers to how I
can fix it?

However, if I manually set a connected route does it work. See attached
patch. The first block of the patch is needed since new routes that are
added while Quagga is running is missing the interface name. I know the
patch is probably "wrong", but is fixes my problem and is attached so
you can see what I'm trying to solve. What is the correct way to fix
this issue? If it should be supported at all..

A related note is that if I run the command

ip route x.x.x.x/y tun0

in vtysh is it added to Quagga, but not to the kernel's routing table
(netstat -rn). I'm guessing that if I add a route both in the OS and
through vtysh will it work, but that is a bit cumbersome.

Daniel Fahlgren
-------------- next part --------------
diff -Naur quagga.orig/zebra/kernel_socket.c quagga/zebra/kernel_socket.c
--- quagga.orig/zebra/kernel_socket.c	2010-11-22 09:34:06.539303508 +0100
+++ quagga/zebra/kernel_socket.c	2010-11-22 13:37:14.161322709 +0100
@@ -743,6 +743,19 @@
   RTA_ATTR_GET (mask, RTA_NETMASK, rtm->rtm_addrs, pnt);
   RTA_ADDR_GET (NULL, RTA_GENMASK, rtm->rtm_addrs, pnt);
   RTA_NAME_GET (ifname, RTA_IFP, rtm->rtm_addrs, pnt, *ifnlen);
+  if (!*ifnlen)
+    {
+      struct interface *ifp;
+      if ((ifp = if_lookup_by_index(rtm->rtm_index)) != NULL)
+        {
+          if (ifp->name != NULL && strlen(ifp->name) < INTERFACE_NAMSIZ)
+            {
+              *ifnlen = strlen(ifp->name);
+              strncpy(ifname, ifp->name, *ifnlen);
+              ifname[*ifnlen] = '\0';
+            }
+        }
+    }
   RTA_ADDR_GET (NULL, RTA_IFA, rtm->rtm_addrs, pnt);
   RTA_ADDR_GET (NULL, RTA_AUTHOR, rtm->rtm_addrs, pnt);
   RTA_ADDR_GET (NULL, RTA_BRD, rtm->rtm_addrs, pnt);
@@ -792,8 +805,25 @@
   /* This is connected route. */
-  if (! (flags & RTF_GATEWAY))
+  if (! (flags & RTF_GATEWAY)) {
+    {
+      struct interface *ifp;
+      if (!ifnlen)
+        return;
+      if (((rtm->rtm_type == RTM_ADD) || (rtm->rtm_type == RTM_GET)) &&
+          (flags == (RTF_UP | RTF_DONE | RTF_STATIC)))
+        if ((ifp = if_lookup_by_name (ifname)) != NULL)
+          connected_add_ipv4 (ifp, flags, &dest.sin.sin_addr, 
+              ip_masklen (mask.sin.sin_addr),
+              &dest.sin.sin_addr, ifname);
+      if ((rtm->rtm_type == RTM_DELETE) &&
+          (flags == (RTF_DONE | RTF_STATIC)))
+        if ((ifp = if_lookup_by_name (ifname)) != NULL)
+          connected_delete_ipv4 (ifp, flags, &dest.sin.sin_addr, 
+              ip_masklen (mask.sin.sin_addr),
+              &dest.sin.sin_addr);
+    }
   if (flags & RTF_PROTO1)
     SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE);

More information about the Quagga-dev mailing list