summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2008-05-22 16:06:06 -0700
committerStephen Hemminger <stephen.hemminger@vyatta.com>2008-05-22 16:06:06 -0700
commit98c5476432c7a5d9b6eb79ef60262f79efa4588f (patch)
treebae10ae44fae81ecae1eea8e570c2894d60075c4
parenta352c7a182f86d926191c31ed9d7e180e9a6287e (diff)
downloadquagga-98c5476432c7a5d9b6eb79ef60262f79efa4588f.tar.bz2
quagga-98c5476432c7a5d9b6eb79ef60262f79efa4588f.tar.xz
Turn on kernel link-detect
If interface has link-detect enabled, try and turn on link-detect in the kernel.
-rwxr-xr-xconfigure.ac6
-rw-r--r--zebra/Makefile.am7
-rw-r--r--zebra/if_linkdetect.c81
-rw-r--r--zebra/interface.c7
-rw-r--r--zebra/interface.h10
-rw-r--r--zebra/linkdetect_null.c16
6 files changed, 124 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac
index 9f18bd39..e679632f 100755
--- a/configure.ac
+++ b/configure.ac
@@ -931,6 +931,12 @@ if test -r /proc/net/if_inet6; then
fi
AC_SUBST(IF_PROC)
+if test -r /proc/sys/net/ipv4/conf; then
+ AC_DEFINE(HAVE_PROC_NET_IPV4_CONF,,/proc/sys/net/ipv4/conf)
+ LINK_DETECT=if_linkdetect.o
+fi
+AC_SUBST(LINK_DETECT)
+
dnl -----------------------------
dnl check ipforward detect method
dnl -----------------------------
diff --git a/zebra/Makefile.am b/zebra/Makefile.am
index 5d8db411..8977c893 100644
--- a/zebra/Makefile.am
+++ b/zebra/Makefile.am
@@ -10,13 +10,14 @@ LIBCAP = @LIBCAP@
ipforward = @IPFORWARD@
if_method = @IF_METHOD@
if_proc = @IF_PROC@
+link_detect = @LINK_DETECT@
rt_method = @RT_METHOD@
rtread_method = @RTREAD_METHOD@
kernel_method = @KERNEL_METHOD@
other_method = @OTHER_METHOD@
ioctl_method = @IOCTL_METHOD@
-otherobj = $(ioctl_method) $(ipforward) $(if_method) $(if_proc) \
+otherobj = $(ioctl_method) $(ipforward) $(if_method) $(if_proc) $(link_detect) \
$(rt_method) $(rtread_method) $(kernel_method) $(other_method)
sbin_PROGRAMS = zebra
@@ -29,7 +30,7 @@ zebra_SOURCES = \
irdp_main.c irdp_interface.c irdp_packet.c router-id.c
testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c debug.c \
- zebra_vty.c \
+ zebra_vty.c linkdetect_null.c \
kernel_null.c redistribute_null.c ioctl_null.c misc_null.c
noinst_HEADERS = \
@@ -42,7 +43,7 @@ testzebra_LDADD = $(LIBCAP) $(LIB_IPV6) ../lib/libzebra.la
zebra_DEPENDENCIES = $(otherobj)
-EXTRA_DIST = if_ioctl.c if_ioctl_solaris.c if_netlink.c if_proc.c \
+EXTRA_DIST = if_ioctl.c if_ioctl_solaris.c if_linkdetect.c if_netlink.c if_proc.c \
if_sysctl.c ipforward_aix.c ipforward_ews.c ipforward_proc.c \
ipforward_solaris.c ipforward_sysctl.c rt_ioctl.c rt_netlink.c \
rt_socket.c rtread_netlink.c rtread_proc.c rtread_sysctl.c \
diff --git a/zebra/if_linkdetect.c b/zebra/if_linkdetect.c
new file mode 100644
index 00000000..9ae7c6a6
--- /dev/null
+++ b/zebra/if_linkdetect.c
@@ -0,0 +1,81 @@
+/* Interface link state tracking
+ * Copyright (C) 2008 Stephen Hemminger
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+#include "log.h"
+#include "privs.h"
+
+#include "log.h"
+#include "privs.h"
+#include "prefix.h"
+
+#include "zebra/interface.h"
+
+extern struct zebra_privs_t zserv_privs;
+
+static int
+linkdetect (const char *name, int onoff)
+{
+ FILE *fp;
+ int save_errno;
+ char proc_name[128];
+
+ snprintf(proc_name, sizeof(proc_name)-1,
+ "/proc/sys/net/ipv4/conf/%s/link_detect", name);
+
+ if ( zserv_privs.change(ZPRIVS_RAISE) )
+ zlog_err ("Can't raise privileges, %s", safe_strerror (errno) );
+
+ fp = fopen (proc_name, "w");
+ save_errno = errno;
+ if (!fp)
+ {
+ if ( zserv_privs.change(ZPRIVS_LOWER) )
+ zlog_err ("Can't lower privileges, %s", safe_strerror (errno));
+
+ zlog_info("Can't %s link-detect, %s:%s",
+ onoff ? "enable" : "disable",
+ proc_name, safe_strerror(save_errno));
+ return -1;
+ }
+ else
+ {
+ fprintf (fp, "%d\n", onoff);
+ fclose (fp);
+
+ if ( zserv_privs.change(ZPRIVS_LOWER) )
+ zlog_err ("Can't lower privileges, %s", safe_strerror (errno));
+
+ return onoff;
+ }
+}
+
+int
+if_linkdetect_on (const char *name)
+{
+ return linkdetect (name, 1);
+}
+
+int
+if_linkdetect_off (const char *name)
+{
+ return linkdetect (name, 1);
+}
diff --git a/zebra/interface.c b/zebra/interface.c
index cfcd5120..f6d2ff9b 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -32,6 +32,7 @@
#include "connected.h"
#include "log.h"
#include "zclient.h"
+#include "ipforward.h"
#include "zebra/interface.h"
#include "zebra/rtadv.h"
@@ -1029,6 +1030,9 @@ DEFUN (linkdetect,
if_was_operative = if_is_operative(ifp);
SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
+ /* Enable FIB to remove kernel routes as well */
+ if_linkdetect_on(ifp->name);
+
/* When linkdetection is enabled, if might come down */
if (!if_is_operative(ifp) && if_was_operative) if_down(ifp);
@@ -1052,6 +1056,9 @@ DEFUN (no_linkdetect,
if_was_operative = if_is_operative(ifp);
UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
+ /* Disable FIB update on link-detect */
+ if_linkdetect_off(ifp->name);
+
/* Interface may come up after disabling link detection */
if (if_is_operative(ifp) && !if_was_operative) if_up(ifp);
diff --git a/zebra/interface.h b/zebra/interface.h
index 0a6b0365..6f356686 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -234,6 +234,16 @@ extern int interface_list_proc (void);
extern int ifaddr_proc_ipv6 (void);
#endif /* HAVE_PROC_NET_IF_INET6 */
+#ifdef HAVE_PROC_NET_IPV4_CONF
+extern int if_linkdetect_on (const char *);
+extern int if_linkdetect_off (const char *);
+#else
+#error config
+#define if_linkdetect_on(name)
+#define if_linkdetect_off(name)
+#endif
+
+
#ifdef BSDI
extern int if_kvm_get_mtu (struct interface *);
#endif /* BSDI */
diff --git a/zebra/linkdetect_null.c b/zebra/linkdetect_null.c
new file mode 100644
index 00000000..c33363e1
--- /dev/null
+++ b/zebra/linkdetect_null.c
@@ -0,0 +1,16 @@
+/* NULL method for testing. */
+
+#include <zebra.h>
+
+
+int
+if_linkdetect_on (const char *name)
+{
+ return 0;
+}
+
+int
+if_linkdetect_off (const char *name)
+{
+ return 0;
+}