[link-detect] Try to get BSD link-detect to work properly.

2008-01-10 Ingo Flaschberger <if@xip.at>

	* configure.ac: Define HAVE_BSD_LINK_DETECT if <net/if_media.h> is
	  present.
	* lib/zebra.h: If HAVE_BSD_LINK_DETECT is defined,
	  include <net/if_media.h>.
	* zebra/ioctl.c: (if_get_flags) If HAVE_BSD_LINK_DETECT, use the
	  SIOCGIFMEDIA ioctl to ascertain link state.
	* zebra/kernel_socket.c: (bsd_linkdetect_translate) New function to
	  map the ifm_data.ifi_link_state value into the IFF_RUNNING flag.
	  (ifm_read) Call bsd_linkdetect_translate to fix the IFF_RUNNING
	  flag before calling if_flags_update.
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index c9ec8d5..4f99a6c 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -344,6 +344,9 @@
 {
   int ret;
   struct ifreq ifreq;
+#ifdef HAVE_BSD_LINK_DETECT
+  struct ifmediareq ifmr;
+#endif /* HAVE_BSD_LINK_DETECT */
 
   ifreq_set_name (&ifreq, ifp);
 
@@ -353,6 +356,36 @@
       zlog_err("if_ioctl(SIOCGIFFLAGS) failed: %s", safe_strerror(errno));
       return;
     }
+#ifdef HAVE_BSD_LINK_DETECT /* Detect BSD link-state at start-up */
+  (void) memset(&ifmr, 0, sizeof(ifmr));
+  strncpy (&ifmr.ifm_name, ifp->name, IFNAMSIZ);
+  if (if_ioctl(SIOCGIFMEDIA, (caddr_t) &ifmr) < 0)
+    {
+      zlog_err("if_ioctl(SIOCGIFMEDIA) failed: %s", safe_strerror(errno));
+      return;
+    }
+  if (ifmr.ifm_status & IFM_AVALID) /* Link state is valid */
+    {
+      if (ifmr.ifm_status & IFM_ACTIVE)
+        {
+	  SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+	  zlog_debug("%s: BSD link state to up at interface %s, ifindex %d",
+		     __func__, ifp->name, ifp->ifindex);
+        }
+      else
+        {
+	  UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+	  zlog_debug("%s: BSD link state to down at interface %s, ifindex %d",
+		     __func__, ifp->name, ifp->ifindex);
+        }
+    }
+  else /* Force always up */
+    {
+      SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+      zlog_debug("%s: BSD link state invalid, forced up at interface %s, ifindex %d",
+		 __func__, ifp->name, ifp->ifindex);
+    }
+#endif /* HAVE_BSD_LINK_DETECT */
 
   if_flags_update (ifp, (ifreq.ifr_flags & 0x0000ffff));
 }