[zebra] Make BSD link-state deal more gracefully with GIFMEDIA ioctl error
2008-07-01 Paul Jakma <paul.jakma@sun.com>
* ioctl.c: (if_get_flags) Deal more gracefully with failure
of the BSD link-state SIOCGIFMEDIA ioctl, as some interfaces
apparently don't implement it (e.g. tun).
Also, make BSD link-state checking be conditional on the
'link-detect' interface configuration flag, as it should be.
Fixes bug #465.
diff --git a/zebra/ChangeLog b/zebra/ChangeLog
index 6483f2c..341c42a 100644
--- a/zebra/ChangeLog
+++ b/zebra/ChangeLog
@@ -1,3 +1,12 @@
+2008-07-01 Paul Jakma <paul.jakma@sun.com>
+
+ * ioctl.c: (if_get_flags) Deal more gracefully with failure
+ of the BSD link-state SIOCGIFMEDIA ioctl, as some interfaces
+ apparently don't implement it (e.g. tun).
+ Also, make BSD link-state checking be conditional on the
+ 'link-detect' interface configuration flag, as it should be.
+ Fixes bug #465.
+
2008-06-02 Denis Ovsienko
* connected.c: (connected_up_ipv4, connected_down_ipv4,
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index d536771..5cf9e7b 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -362,22 +362,29 @@
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)
+
+ /* Per-default, IFF_RUNNING is held high, unless link-detect says
+ * otherwise - we abuse IFF_RUNNING inside zebra as a link-state flag,
+ * following practice on Linux and Solaris kernels
+ */
+ SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+
+ if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
{
- 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);
- else
- UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
- }
- else /* Force always up */
- SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ (void) memset(&ifmr, 0, sizeof(ifmr));
+ strncpy (&ifmr.ifm_name, ifp->name, IFNAMSIZ);
+
+ /* Seems not all interfaces implement this ioctl */
+ if (if_ioctl(SIOCGIFMEDIA, (caddr_t) &ifmr) < 0)
+ zlog_err("if_ioctl(SIOCGIFMEDIA) failed: %s", safe_strerror(errno));
+ else if (ifmr.ifm_status & IFM_AVALID) /* Link state is valid */
+ {
+ if (ifmr.ifm_status & IFM_ACTIVE)
+ SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ else
+ UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ }
+ }
#endif /* HAVE_BSD_LINK_DETECT */
if_flags_update (ifp, (ifreq.ifr_flags & 0x0000ffff));