* keepalived-0.5.5 released.
* Fixed a gratuitous ARP porting bug.
* VRRP : Review the data structure to be more generic
and clean with the rest of the code.
* VRRP : Remove the interface flags (NIC) ioctl functions
* VRRP : Created an interface (NIC) library giving access
to common interface helpers functions.
* VRRP : Created an interface lookup function creating a global
interface structure during daemon bootstrap. Consist of a netlink
RTM_GETLINK & RTM_GETADDR lookup, so we can work with a userspace
interface representation.
* VRRP : Create a netlink kernel reflection framework updating
dynamically our interface structure according to kernel
netlink broadcast. This design is highly inspired from zebra.
=> Reflection mean : wait for netlink kernel broadcast, if received,
wakeup netlink filter to update our userspace representation.
Prefer this design instead of a delayed netlink poller. That way
we reduce global overhead.
* VRRP : VRRP need to detect failure from many places.
If netlink can notify for many troubles like mainly
IFF_UP|DOWN & IFF_RUNNING, those flags are kernel drivers dependent.
To reduce takeover time and performance we need to have informations like
: Does the media link is present ?. The fact is that most of the new NICs
own embended hardware chip providing such informations. So created a
MII transceiver status register thread poller. Monitoring Basic Mode
Status Register (BMSR) of the MII status words. Waiting for kernel
NIC drivers hackers to support this functionnality through netlink
(=> Like a IFF_RUNNING update broadcast).
* VRRP : Linked the state machine to the global interface structure.
NIC failure/events are handled.
* VRRP : Review the whole state machine code to be more realistic. The
State transition diagram described into the RFC2338 is an obtimist
view. The VRRP state transition diagram implemented here is :
+---------------+
+--------->| |<-------------+
| | Initialize | |
| +------| |----------+ |
| | +---------------+ | |
| V V |
+---------------+ +---------------+
| |---------------------->| |
| Master | | Backup |
| |<----------------------| |
+---------------+ +---------------+
^ | | | ^
| | | +---------------+ | |
| | +------>| Dummy Master | | |
| | +---------------+ | |
| | | | |
| | V | |
| | +---------------+ | |
| +------------>| |<----------+ |
| | Fault | |
+-----------------| |----------------+
+---------------+
* VRRP : Robust multicast handling. Something really strange
is : after a NIC failure (in fallback mode) without closing
the socket, multicast advert can be sent but not received ?
really strange don t know why probably an IGMP resubmit ?.
So multicast group is left during failover (media trouble,
IFF_DOWN or !IFF_RUNNING). In fallback, we register a new
membership and synchronize all the packet dispatcher fds.
* VRRP : Fixed a checksum trouble using password authentication.
* VRRP : Added support to the LVS sync daemon. This permit
LVS sync daemon to be state drived by a specific VRRP instance.
* Review the autoconf/automake to be more generic.
* Some cosmetics patches.
-Jan Holmberg <jan@artech.net>
+Jan Holmberg, <jan@artech.net>
+2002-04-10 Alexandre Cassen <acassen@linux-vs.org>
+ * keepalived-0.5.5 released.
+ * Fixed a gratuitous ARP porting bug.
+ * VRRP : Review the data structure to be more generic
+ and clean with the rest of the code.
+ * VRRP : Remove the interface flags (NIC) ioctl functions
+ * VRRP : Created an interface (NIC) library giving access
+ to common interface helpers functions.
+ * VRRP : Created an interface lookup function creating a global
+ interface structure during daemon bootstrap. Consist of a netlink
+ RTM_GETLINK & RTM_GETADDR lookup, so we can work with a userspace
+ interface representation.
+ * VRRP : Create a netlink kernel reflection framework updating
+ dynamically our interface structure according to kernel
+ netlink broadcast. This design is highly inspired from zebra.
+ => Reflection mean : wait for netlink kernel broadcast, if received,
+ wakeup netlink filter to update our userspace representation.
+ Prefer this design instead of a delayed netlink poller. That way
+ we reduce global overhead.
+ * VRRP : VRRP need to detect failure from many places.
+ If netlink can notify for many troubles like mainly
+ IFF_UP|DOWN & IFF_RUNNING, those flags are kernel drivers dependent.
+ To reduce takeover time and performance we need to have informations like
+ : Does the media link is present ?. The fact is that most of the new NICs
+ own embended hardware chip providing such informations. So created a
+ MII transceiver status register thread poller. Monitoring Basic Mode
+ Status Register (BMSR) of the MII status words. Waiting for kernel
+ NIC drivers hackers to support this functionnality through netlink
+ (=> Like a IFF_RUNNING update broadcast).
+ * VRRP : Linked the state machine to the global interface structure.
+ NIC failure/events are handled.
+ * VRRP : Review the whole state machine code to be more realistic. The
+ State transition diagram described into the RFC2338 is an obtimist
+ view. The VRRP state transition diagram implemented here is :
+
+ +---------------+
+ +--------->| |<-------------+
+ | | Initialize | |
+ | +------| |----------+ |
+ | | +---------------+ | |
+ | V V |
+ +---------------+ +---------------+
+ | |---------------------->| |
+ | Master | | Backup |
+ | |<----------------------| |
+ +---------------+ +---------------+
+ ^ | | | ^
+ | | | +---------------+ | |
+ | | +------>| Dummy Master | | |
+ | | +---------------+ | |
+ | | | | |
+ | | V | |
+ | | +---------------+ | |
+ | +------------>| |<----------+ |
+ | | Fault | |
+ +-----------------| |----------------+
+ +---------------+
+
+ * VRRP : Robust multicast handling. Something really strange
+ is : after a NIC failure (in fallback mode) without closing
+ the socket, multicast advert can be sent but not received ?
+ really strange don t know why probably an IGMP resubmit ?.
+ So multicast group is left during failover (media trouble,
+ IFF_DOWN or !IFF_RUNNING). In fallback, we register a new
+ membership and synchronize all the packet dispatcher fds.
+ * VRRP : Fixed a checksum trouble using password authentication.
+ * VRRP : Added support to the LVS sync daemon. This permit
+ LVS sync daemon to be state drived by a specific VRRP instance.
+ * Review the autoconf/automake to be more generic.
+ * Some cosmetics patches.
+
2002-02-25 Alexandre Cassen <acassen@linux-vs.org>
* keepalived-0.5.3 released.
* Added autoconf / automake generic scripts.
CC = @CC@
CFLAGS = @CFLAGS@ -Wall -Wunused -Wstrict-prototypes -D_DEBUG_ -D$(KERNEL)
-LDFLAGS = @LIBS@ @LDFLAGS@
+LDFLAGS = @LIBS@ @LDFLAGS@ @LIBFW@
OBJS = @LIBOBJS@ \
main.o \
memory.o \
vrrp.o \
vrrp_scheduler.o \
vrrp_netlink.o \
+ vrrp_if.o \
vrrp_ipaddress.o \
vrrp_ipsecah.o
*
* Part: Checkers registration.
*
- * Version: $Id: check_api.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: check_api.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "check_api.h"
#include "parser.h"
#include "memory.h"
+#include "utils.h"
#include "check_misc.h"
#include "check_tcp.h"
#include "check_http.h"
*
* Part: Checkers arguments structures definitions.
*
- * Version: $Id: check_api.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: check_api.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: WEB CHECK. Common HTTP/SSL checker primitives.
*
- * Version: $Id: check_http.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: check_http.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
*
* Part: check_http.c include file.
*
- * Version: $Id: check_http.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: check_http.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
* Part: MISC CHECK. Perform a system call to run an extra
* system prog or script.
*
- * Version: $Id: check_misc.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: check_misc.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
*
* Part: check_misc.c include file.
*
- * Version: $Id: check_misc.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: check_misc.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
* Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
* url, compute a MD5 over this result and match it to the
* expected value.
*
- * Version: $Id: check_ssl.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: check_ssl.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
*
* Part: check_http.c include file.
*
- * Version: $Id: check_http.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: check_http.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
*
* Part: TCP checker.
*
- * Version: $Id: check_tcp.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: check_tcp.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: check_tcp.c include file.
*
- * Version: $Id: check_tcp.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: check_tcp.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
# A filename unique to this package, relative to the directory that
# configure is in, which we can look for to find out if srcdir is correct.
-ac_unique_file=parser.c
+ac_unique_file=scheduler.c
# Find the source files, if location was not specified.
if test -z "$srcdir"; then
KERNEL_VERSION=`uname -r`
-modprobe ip_vs
+
+IPVS_MODULE="/lib/modules/`uname -r`/kernel/net/ipv4/ipvs/ip_vs.o"
+if test -f $IPVS_MODULE; then
+ modprobe ip_vs
+fi
+
if test -f /proc/net/ip_vs; then
IPVS_VERSION=`cat /proc/net/ip_vs | head -1 | awk '{ print $5}'`
+elif test -f /proc/net/ip_masq/vs; then
+ IPVS_VERSION=`cat /proc/net/ip_masq/vs | head -1 | awk '{ print $5}'`
else
echo
echo "!!!WARN!!! Your kernel need to be patched with LVS code !!!WARN!!!"
fi
VERSION=`cat VERSION`
-echo $ac_n "checking for main in -lcrypto""... $ac_c" 1>&6
-echo "configure:845: checking for main in -lcrypto" >&5
-ac_lib_var=`echo crypto'_'main | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for MD5_Init in -lcrypto""... $ac_c" 1>&6
+echo "configure:852: checking for MD5_Init in -lcrypto" >&5
+ac_lib_var=`echo crypto'_'MD5_Init | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_save_LIBS="$LIBS"
LIBS="-lcrypto $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 853 "configure"
+#line 860 "configure"
#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char MD5_Init();
int main() {
-main()
+MD5_Init()
; return 0; }
EOF
-if { (eval echo configure:860: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:871: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
else
echo "$ac_t""no" 1>&6
+{ echo "configure: error: OpenSSL libraries are required" 1>&2; exit 1; }
fi
-echo $ac_n "checking for main in -lpopt""... $ac_c" 1>&6
-echo "configure:888: checking for main in -lpopt" >&5
-ac_lib_var=`echo popt'_'main | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for SSL_CTX_new in -lssl""... $ac_c" 1>&6
+echo "configure:900: checking for SSL_CTX_new in -lssl" >&5
+ac_lib_var=`echo ssl'_'SSL_CTX_new | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_save_LIBS="$LIBS"
-LIBS="-lpopt $LIBS"
+LIBS="-lssl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 896 "configure"
+#line 908 "configure"
#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char SSL_CTX_new();
int main() {
-main()
+SSL_CTX_new()
; return 0; }
EOF
-if { (eval echo configure:903: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:919: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo popt | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ ac_tr_lib=HAVE_LIB`echo ssl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
cat >> confdefs.h <<EOF
#define $ac_tr_lib 1
EOF
- LIBS="-lpopt $LIBS"
+ LIBS="-lssl $LIBS"
else
echo "$ac_t""no" 1>&6
+{ echo "configure: error: OpenSSL libraries are required" 1>&2; exit 1; }
fi
-echo $ac_n "checking for main in -lssl""... $ac_c" 1>&6
-echo "configure:931: checking for main in -lssl" >&5
-ac_lib_var=`echo ssl'_'main | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for poptGetContext in -lpopt""... $ac_c" 1>&6
+echo "configure:948: checking for poptGetContext in -lpopt" >&5
+ac_lib_var=`echo popt'_'poptGetContext | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_save_LIBS="$LIBS"
-LIBS="-lssl $LIBS"
+LIBS="-lpopt $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 939 "configure"
+#line 956 "configure"
#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char poptGetContext();
int main() {
-main()
+poptGetContext()
; return 0; }
EOF
-if { (eval echo configure:946: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:967: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo ssl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ ac_tr_lib=HAVE_LIB`echo popt | sed -e 's/[^a-zA-Z0-9_]/_/g' \
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
cat >> confdefs.h <<EOF
#define $ac_tr_lib 1
EOF
- LIBS="-lssl $LIBS"
+ LIBS="-lpopt $LIBS"
else
echo "$ac_t""no" 1>&6
+{ echo "configure: error: Popt libraries is required" 1>&2; exit 1; }
fi
KERNEL_CODE=`echo $KERNEL_VERSION | cut -d'.' -f2`
if test "${KERNEL_CODE}" = "2"; then
- LDFLAGS = ${LIBS} libipfwc/libipfwc.a
- LIBOBJS = ${LIBOBJS} ipfwwrapper.o
-fi
+ LIBFW="libipfwc/libipfwc.a"
+ LIBOBJS="$LIBOBJS ipfwwrapper.o"
+ fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:981: checking how to run the C preprocessor" >&5
+echo "configure:1003: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
-#line 996 "configure"
+#line 1018 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1002: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1024: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
-#line 1013 "configure"
+#line 1035 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1019: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1041: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
rm -rf conftest*
CPP="${CC-cc} -nologo -E"
cat > conftest.$ac_ext <<EOF
-#line 1030 "configure"
+#line 1052 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1036: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1058: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
echo "$ac_t""$CPP" 1>&6
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:1061: checking for ANSI C header files" >&5
+echo "configure:1083: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1066 "configure"
+#line 1088 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1074: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1096: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1091 "configure"
+#line 1113 "configure"
#include "confdefs.h"
#include <string.h>
EOF
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1109 "configure"
+#line 1131 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
:
else
cat > conftest.$ac_ext <<EOF
-#line 1130 "configure"
+#line 1152 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
exit (0); }
EOF
-if { (eval echo configure:1141: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1163: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
fi
echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
-echo "configure:1165: checking for sys/wait.h that is POSIX.1 compatible" >&5
+echo "configure:1187: checking for sys/wait.h that is POSIX.1 compatible" >&5
if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1170 "configure"
+#line 1192 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/wait.h>
s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
; return 0; }
EOF
-if { (eval echo configure:1186: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1208: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_sys_wait_h=yes
else
fi
+for ac_hdr in openssl/ssl.h openssl/md5.h openssl/err.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1232: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1237 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1242: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+{ echo "configure: error:
+ !!! OpenSSL is not properly installed on your system. !!!
+ !!! Can not include OpenSSL headers files. !!!" 1>&2; exit 1; }
+fi
+done
+
for ac_hdr in fcntl.h sys/ioctl.h sys/time.h syslog.h unistd.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1210: checking for $ac_hdr" >&5
+echo "configure:1275: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1215 "configure"
+#line 1280 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1220: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1285: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:1248: checking for working const" >&5
+echo "configure:1313: checking for working const" >&5
if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1253 "configure"
+#line 1318 "configure"
#include "confdefs.h"
int main() {
; return 0; }
EOF
-if { (eval echo configure:1302: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1367: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_const=yes
else
fi
echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:1323: checking for pid_t" >&5
+echo "configure:1388: checking for pid_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1328 "configure"
+#line 1393 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
fi
echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:1356: checking whether time.h and sys/time.h may both be included" >&5
+echo "configure:1421: checking whether time.h and sys/time.h may both be included" >&5
if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1361 "configure"
+#line 1426 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/time.h>
struct tm *tp;
; return 0; }
EOF
-if { (eval echo configure:1370: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1435: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_time=yes
else
if test $ac_cv_prog_gcc = yes; then
echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
-echo "configure:1393: checking whether ${CC-cc} needs -traditional" >&5
+echo "configure:1458: checking whether ${CC-cc} needs -traditional" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_pattern="Autoconf.*'x'"
cat > conftest.$ac_ext <<EOF
-#line 1399 "configure"
+#line 1464 "configure"
#include "confdefs.h"
#include <sgtty.h>
Autoconf TIOCGETP
if test $ac_cv_prog_gcc_traditional = no; then
cat > conftest.$ac_ext <<EOF
-#line 1417 "configure"
+#line 1482 "configure"
#include "confdefs.h"
#include <termio.h>
Autoconf TCGETA
fi
fi
-echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
-echo "configure:1439: checking for 8-bit clean memcmp" >&5
-if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- ac_cv_func_memcmp_clean=no
-else
- cat > conftest.$ac_ext <<EOF
-#line 1447 "configure"
-#include "confdefs.h"
-
-main()
-{
- char c0 = 0x40, c1 = 0x80, c2 = 0x81;
- exit(memcmp(&c0, &c2, 1) < 0 && memcmp(&c1, &c2, 1) < 0 ? 0 : 1);
-}
-
-EOF
-if { (eval echo configure:1457: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
- ac_cv_func_memcmp_clean=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_func_memcmp_clean=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6
-test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
-
echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:1475: checking return type of signal handlers" >&5
+echo "configure:1504: checking return type of signal handlers" >&5
if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1480 "configure"
+#line 1509 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
int i;
; return 0; }
EOF
-if { (eval echo configure:1497: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1526: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_type_signal=void
else
for ac_func in gettimeofday select socket strerror strtol uname
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1518: checking for $ac_func" >&5
+echo "configure:1547: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1523 "configure"
+#line 1552 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:1546: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1575: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
s%@INSTALL_DATA@%$INSTALL_DATA%g
-s%@CPP@%$CPP%g
+s%@LIBFW@%$LIBFW%g
s%@LIBOBJS@%$LIBOBJS%g
+s%@CPP@%$CPP%g
CEOF
EOF
IPVS version code : ${IPVS_VERSION}
Compiler : ${CC}
Compiler flags : ${CFLAGS}
+Extra Lib : $LIBS
+Lib objects : $LIBOBJS
+Firewall Lib : $LIBFW
EOF
# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
dnl ----[ Process this file with autoconf to produce a configure script ]----
-AC_INIT(cfreader.c)
+AC_INIT(scheduler.c)
dnl ----[ Checks for programs ]----
AC_PROG_CC
dnl ----[ Checks for kernel support ]----
KERNEL_VERSION=`uname -r`
-modprobe ip_vs
+
+IPVS_MODULE="/lib/modules/`uname -r`/kernel/net/ipv4/ipvs/ip_vs.o"
+if test -f $IPVS_MODULE; then
+ modprobe ip_vs
+fi
+
if test -f /proc/net/ip_vs; then
IPVS_VERSION=`cat /proc/net/ip_vs | head -1 | awk '{ print $5}'`
+elif test -f /proc/net/ip_masq/vs; then
+ IPVS_VERSION=`cat /proc/net/ip_masq/vs | head -1 | awk '{ print $5}'`
else
echo
echo "!!!WARN!!! Your kernel need to be patched with LVS code !!!WARN!!!"
VERSION=`cat VERSION`
dnl ----[ Checks for libraries ]----
-dnl Replace `main' with a function in -lcrypto:
-AC_CHECK_LIB(crypto, main)
-dnl Replace `main' with a function in -lpopt:
-AC_CHECK_LIB(popt, main)
-dnl Replace `main' with a function in -lssl:
-AC_CHECK_LIB(ssl, main)
+AC_CHECK_LIB(crypto, MD5_Init,,AC_MSG_ERROR([OpenSSL libraries are required]))
+AC_CHECK_LIB(ssl, SSL_CTX_new,,AC_MSG_ERROR([OpenSSL libraries are required]))
+AC_CHECK_LIB(popt, poptGetContext,,AC_MSG_ERROR([Popt libraries is required]))
dnl ----[ Create object list ]----
KERNEL_CODE=`echo $KERNEL_VERSION | cut -d'.' -f2`
if test "${KERNEL_CODE}" = "2"; then
- LDFLAGS = ${LIBS} libipfwc/libipfwc.a
- LIBOBJS = ${LIBOBJS} ipfwwrapper.o
+ LIBFW="libipfwc/libipfwc.a"
+ LIBOBJS="$LIBOBJS ipfwwrapper.o"
+ AC_SUBST(LIBFW)dnl
+ AC_SUBST(LIBOBJS)dnl
fi
dnl ----[ Checks for header files ]----
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(openssl/ssl.h openssl/md5.h openssl/err.h,,AC_MSG_ERROR([
+ !!! OpenSSL is not properly installed on your system. !!!
+ !!! Can not include OpenSSL headers files. !!!]))
AC_CHECK_HEADERS(fcntl.h sys/ioctl.h sys/time.h syslog.h unistd.h)
dnl ----[ Checks for typedefs, structures, and compiler characteristics ]----
dnl ----[ Checks for library functions ]----
AC_PROG_GCC_TRADITIONAL
-AC_FUNC_MEMCMP
+dnl AC_FUNC_MEMCMP
AC_TYPE_SIGNAL
AC_CHECK_FUNCS(gettimeofday select socket strerror strtol uname)
IPVS version code : ${IPVS_VERSION}
Compiler : ${CC}
Compiler flags : ${CFLAGS}
+Extra Lib : $LIBS
+Lib objects : $LIBOBJS
+Firewall Lib : $LIBFW
EOF
*
* Part: Main program structure.
*
- * Version: $Id: main.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: main.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Daemon process handling.
*
- * Version: $Id: daemon.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: daemon.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Dynamic data structure definition.
*
- * Version: $Id: data.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: data.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "memory.h"
#include "utils.h"
#include "check_api.h"
+#include "vrrp.h"
extern data *conf_data;
/* VRRP facility functions */
static void free_vrrp(void *data)
{
- vrrp_instance *vrrp = data;
- vrrp_rt *ptr = vrrp->vsrv;
+ vrrp_rt *vrrp = data;
FREE(vrrp->iname);
FREE_PTR(vrrp->isync);
- FREE_PTR(ptr->vaddr);
- FREE(ptr->ipsecah_counter);
- FREE(ptr->vif->ifname);
- FREE(ptr->vif);
- FREE(ptr);
+ FREE_PTR(vrrp->lvs_syncd_if);
+ FREE_PTR(vrrp->vaddr);
+ FREE(vrrp->ipsecah_counter);
FREE(vrrp);
}
static void dump_vrrp(void *data)
{
- vrrp_instance *vrrp = data;
- vrrp_rt *ptr = vrrp->vsrv;
+ vrrp_rt *vrrp = data;
int i;
syslog(LOG_INFO, " VRRP Instance = %s", vrrp->iname);
if (vrrp->isync)
syslog(LOG_INFO, " Sync with instance = %s", vrrp->isync);
- if (ptr->init_state == VRRP_STATE_BACK)
+ if (vrrp->init_state == VRRP_STATE_BACK)
syslog(LOG_INFO, " Want State = BACKUP");
else
syslog(LOG_INFO, " Want State = MASTER");
- syslog(LOG_INFO, " Runing on device = %s", ptr->vif->ifname);
- syslog(LOG_INFO, " Virtual Router ID = %d", ptr->vrid);
- syslog(LOG_INFO, " Priority = %d", ptr->priority);
- syslog(LOG_INFO, " Advert interval = %dsec", ptr->adver_int/TIMER_HZ);
- if (ptr->preempt)
+ syslog(LOG_INFO, " Runing on device = %s", IF_NAME(vrrp->ifp));
+ if (vrrp->lvs_syncd_if)
+ syslog(LOG_INFO, " Runing LVS sync daemon on interface = %s"
+ , vrrp->lvs_syncd_if);
+ syslog(LOG_INFO, " Virtual Router ID = %d", vrrp->vrid);
+ syslog(LOG_INFO, " Priority = %d", vrrp->priority);
+ syslog(LOG_INFO, " Advert interval = %dsec", vrrp->adver_int/TIMER_HZ);
+ if (vrrp->preempt)
syslog(LOG_INFO, " Preempt Active");
- if (ptr->vif->auth_type) {
+ if (vrrp->auth_type) {
syslog(LOG_INFO, " Authentication type = %s",
- (ptr->vif->auth_type == VRRP_AUTH_AH)?"IPSEC_AH":"SIMPLE_PASSWORD" );
- syslog(LOG_INFO, " Password = %s", ptr->vif->auth_data);
+ (vrrp->auth_type == VRRP_AUTH_AH)?"IPSEC_AH":"SIMPLE_PASSWORD" );
+ syslog(LOG_INFO, " Password = %s", vrrp->auth_data);
}
- syslog(LOG_INFO, " VIP count = %d", ptr->naddr);
- for (i = 0; i < ptr->naddr; i++)
- syslog(LOG_INFO, " VIP%d = %s", i+1, ip_ntoa(ptr->vaddr[i].addr));
+ syslog(LOG_INFO, " VIP count = %d", vrrp->naddr);
+ for (i = 0; i < vrrp->naddr; i++)
+ syslog(LOG_INFO, " VIP%d = %s", i+1, ip_ntoa(vrrp->vaddr[i].addr));
}
void alloc_vrrp(char *iname)
{
int size = strlen(iname);
- vrrp_instance *new;
- vrrp_rt *rt;
- vrrp_if *vif;
seq_counter *counter;
+ vrrp_rt *new;
/* Allocate new VRRP structure */
- new = (vrrp_instance *)MALLOC(sizeof(vrrp_instance));
- rt = (vrrp_rt *) MALLOC(sizeof(vrrp_rt));
- vif = (vrrp_if *) MALLOC(sizeof(vrrp_if));
+ new = (vrrp_rt *) MALLOC(sizeof(vrrp_rt));
counter = (seq_counter *) MALLOC(sizeof(seq_counter));
/* Build the structure */
- new->vsrv = rt;
- rt->vif = vif;
- rt->ipsecah_counter = counter;
+ new->ipsecah_counter = counter;
/* Set default values */
- rt->wantstate = VRRP_STATE_BACK;
- rt->init_state = VRRP_STATE_BACK;
- rt->adver_int = TIMER_HZ;
- new->iname = (char *)MALLOC(size+1);
+ new->wantstate = VRRP_STATE_BACK;
+ new->init_state = VRRP_STATE_BACK;
+ new->adver_int = TIMER_HZ;
+ new->iname = (char *)MALLOC(size+1);
memcpy(new->iname, iname, size);
list_add(conf_data->vrrp, new);
}
void alloc_vrrp_vip(char *vip)
{
- vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
uint32_t ipaddr = inet_addr(vip);
- vrrp_rt *ptr = vrrp->vsrv;
- ptr->naddr++;
- if (ptr->vaddr)
- ptr->vaddr = REALLOC(ptr->vaddr, ptr->naddr*sizeof(*ptr->vaddr));
+ vrrp->naddr++;
+ if (vrrp->vaddr)
+ vrrp->vaddr = REALLOC(vrrp->vaddr, vrrp->naddr*sizeof(*vrrp->vaddr));
else
- ptr->vaddr = (vip_addr *)MALLOC(sizeof(*ptr->vaddr));
- ptr->vaddr[ptr->naddr-1].addr = ipaddr;
- ptr->vaddr[ptr->naddr-1].deletable = 0;
+ vrrp->vaddr = (vip_addr *)MALLOC(sizeof(*vrrp->vaddr));
+ vrrp->vaddr[vrrp->naddr-1].addr = ipaddr;
+ vrrp->vaddr[vrrp->naddr-1].set = 0;
}
/* Virtual server facility functions */
free_list(conf_data->vrrp);
free_list(conf_data->vs);
- FREE(conf_data->lvs_id);
- FREE(conf_data->email_from);
+// FREE(conf_data->lvs_id);
+// FREE(conf_data->email_from);
FREE(conf_data);
}
void dump_data(void)
{
- syslog(LOG_INFO, "------< Global definitions >------");
- syslog(LOG_INFO, " LVS ID = %s", conf_data->lvs_id);
- syslog(LOG_INFO, " Smtp server = %s", ip_ntoa(conf_data->smtp_server));
- syslog(LOG_INFO, " Smtp server connection timeout = %d", conf_data->smtp_connection_to);
- syslog(LOG_INFO, " Email notification from = %s", conf_data->email_from);
- dump_list(conf_data->email);
+ if (conf_data->lvs_id &&
+ conf_data->smtp_server &&
+ conf_data->smtp_connection_to &&
+ conf_data->email_from) {
+ syslog(LOG_INFO, "------< Global definitions >------");
+ syslog(LOG_INFO, " LVS ID = %s", conf_data->lvs_id);
+ syslog(LOG_INFO, " Smtp server = %s", ip_ntoa(conf_data->smtp_server));
+ syslog(LOG_INFO, " Smtp server connection timeout = %d"
+ , conf_data->smtp_connection_to);
+ syslog(LOG_INFO, " Email notification from = %s"
+ , conf_data->email_from);
+ dump_list(conf_data->email);
+ }
if (conf_data->ssl) {
syslog(LOG_INFO, "------< SSL definitions >------");
*
* Part: Dynamic data structure definition.
*
- * Version: $Id: data.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: data.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* local includes */
#include "list.h"
-#include "vrrp.h"
/* Daemon dynamic data structure definition */
#define MAX_TIMEOUT_LENGTH 5
list rs;
} virtual_server;
-/* VRRP instance definition */
-typedef struct _vrrp_instance {
- char *iname; /* Instance Name */
- char *isync; /* Instance Name to synchronize with */
- vrrp_rt *vsrv; /* VRRP data */
-} vrrp_instance;
-
/* email link list */
typedef struct _email {
char *addr;
lvs_id LVS_DEVEL
}
-;SSL {
- password password
- ca /etc/keepalived/root.pem
- certificate /etc/keepalived/dh1024.pem
- key /etc/keepalived/client.pem
-}
+!SSL {
+! password password
+! ca /etc/keepalived/root.pem
+! certificate /etc/keepalived/dh1024.pem
+! key /etc/keepalived/client.pem
+!}
vrrp_instance VI_1 {
state MASTER
--- /dev/null
+# Generated automatically from Makefile.in by configure.
+# Makefile
+#
+# Keepalived OpenSource project.
+#
+# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
+
+EXEC = genhash
+
+prefix = /usr/local
+exec_prefix = ${prefix}
+bindir = ${exec_prefix}/bin
+
+CC = gcc
+CFLAGS = -g -O2 -Wall -Wunused -Wstrict-prototypes
+LDFLAGS = -lpopt -lssl -lcrypto
+
+OBJS = main.o client.o common.o
+
+all: $(EXEC)
+ strip $(EXEC)
+ @echo ""
+ @echo "Make complete"
+
+$(EXEC): $(OBJS)
+ $(CC) $(OBJS) -o $(EXEC) $(LDFLAGS)
+
+clean:
+ rm -f core *.o $(EXEC)
+
+clean-dist:
+ rm -f $(bindir)/$(EXEC)
+
+install:
+ install -m 755 $(EXEC) $(bindir)/
/* Build version */
#define PROG "genhash"
-#define VERSION "0.4.9 (05/12, 2001)"
+#define VERSION "0.5.3 (03/22, 2002)"
/* HTTP/HTTPS GET command */
#define REQUEST_TEMPLATE "GET %s HTTP/1.0\r\n" \
* library to add/remove server MASQ rules to the kernel
* firewall framework.
*
- * Version: $Id: ipfwwrapper.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: ipfwwrapper.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: ipfwwrapper.c include file.
*
- * Version: $Id: ipfwwrapper.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: ipfwwrapper.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* Part: IPVS Kernel wrapper. Use setsockopt call to add/remove
* server to/from the loadbalanced server pool.
*
- * Version: $Id: ipvswrapper.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: ipvswrapper.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#ifdef _KRNL_2_2_ /* KERNEL 2.2 LVS handling */
+int ipvs_syncd_cmd(int cmd, char *ifname, int state)
+{
+ syslog(LOG_INFO, "IPVS WRAPPER : Sync daemon not supported on kernel v2.2");
+ return IPVS_ERROR;
+}
+
int ipvs_cmd(int cmd, virtual_server *vs, real_server *rs)
{
struct ip_masq_ctl ctl;
#else /* KERNEL 2.4 LVS handling */
+int ipvs_syncd_cmd(int cmd, char *ifname, int state)
+{
+ struct ip_vs_rule_user urule;
+ int result = 0;
+ int sockfd;
+
+ memset(&urule, 0, sizeof(struct ip_vs_rule_user));
+
+ sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+ if (sockfd == -1) {
+ syslog(LOG_INFO, "IPVS WRAPPER : Can not initialize SOCK_RAW descriptor.");
+ return IPVS_ERROR;
+ }
+
+ /* prepare user rule */
+ urule.state = state;
+ if (ifname != NULL)
+ strncpy(urule.mcast_ifn, ifname, IP_VS_IFNAME_MAXLEN);
+
+ result = setsockopt(sockfd, IPPROTO_IP, cmd, (char *)&urule, sizeof(urule));
+
+ if (result) {
+ syslog(LOG_INFO, "IPVS WRAPPER : setsockopt failed !!!");
+
+ switch (cmd) {
+ case IP_VS_SO_SET_STARTDAEMON:
+ if (errno == EEXIST)
+ syslog(LOG_INFO, "IPVS WRAPPER: Sync_daemon is already running");
+ break;
+ case IP_VS_SO_SET_STOPDAEMON:
+ if (errno == ESRCH)
+ syslog(LOG_INFO, "IPVS WRAPPER: Sync_daemon is not running");
+ break;
+ }
+ }
+
+ close(sockfd);
+ return IPVS_SUCCESS;
+}
+
int ipvs_cmd(int cmd, virtual_server *vs, real_server *rs)
{
struct ip_vs_rule_user urule;
#endif
/*
+ * IPVS synchronization daemon state transition
+ */
+int ipvs_syncd_goto_master_thread(thread *thread)
+{
+ char *ifname = THREAD_ARG(thread);
+ ipvs_syncd_cmd(IPVS_STARTDAEMON, ifname, IPVS_MASTER);
+ return 0;
+}
+
+int ipvs_syncd_master_thread(thread *thread)
+{
+ char *ifname = THREAD_ARG(thread);
+ ipvs_syncd_cmd(IPVS_STOPDAEMON, ifname, IPVS_BACKUP);
+ thread_add_timer(master, ipvs_syncd_goto_master_thread
+ , ifname
+ , IPVS_CMD_DELAY);
+ return 0;
+}
+
+int ipvs_syncd_goto_backup_thread(thread *thread)
+{
+ char *ifname = THREAD_ARG(thread);
+ ipvs_syncd_cmd(IPVS_STARTDAEMON, ifname, IPVS_BACKUP);
+ return 0;
+}
+
+int ipvs_syncd_backup_thread(thread *thread)
+{
+ char *ifname = THREAD_ARG(thread);
+ ipvs_syncd_cmd(IPVS_STOPDAEMON, ifname, IPVS_MASTER);
+ thread_add_timer(master, ipvs_syncd_goto_backup_thread
+ , ifname
+ , IPVS_CMD_DELAY);
+ return 0;
+}
+
+/*
* Source code from the ipvsadm.c Wensong code
*/
*
* Part: ipvswrapper.c include file.
*
- * Version: $Id: ipvswrapper.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: ipvswrapper.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include <net/ip_vs.h>
/* locale includes */
+#include "scheduler.h"
#include "data.h"
-#define IPVS_ERROR 0
-#define IPVS_SUCCESS 1
+#define IPVS_ERROR 0
+#define IPVS_SUCCESS 1
+#define IPVS_CMD_DELAY 3
+
+#define IPVS_STARTDAEMON IP_VS_SO_SET_STARTDAEMON
+#define IPVS_STOPDAEMON IP_VS_SO_SET_STOPDAEMON
+#define IPVS_MASTER IP_VS_STATE_MASTER
+#define IPVS_BACKUP IP_VS_STATE_BACKUP
+
+extern thread_master *master;
/* prototypes */
extern int parse_timeout(char *buf, unsigned *timeout);
extern int string_to_number(const char *s, int min, int max);
extern int ipvs_cmd(int cmd, virtual_server *vserver, real_server *rserver);
+extern int ipvs_syncd_cmd(int cmd, char *ifname, int state);
+extern int ipvs_syncd_master_thread(thread *thread);
+extern int ipvs_syncd_backup_thread(thread *thread);
#endif
*
* Part: Manipulation functions for IPVS & IPFW wrappers.
*
- * Version: $id: ipwrapper.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $id: ipwrapper.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#ifdef _KRNL_2_2_
/* IPFW cleaning server entry if granularity = /32 */
- if (vserver->nat_mask == HOST_NETMASK)
+ if (vs->nat_mask == HOST_NETMASK)
if (!ipfw_cmd(IP_FW_CMD_DEL, vs, e->data))
return 0;
#endif
*
* Part: ipwrapper.c include file.
*
- * Version: $Id: ipwrapper.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: ipwrapper.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* Part: Layer4 checkers handling. Register worker threads &
* upper layer checkers.
*
- * Version: $Id: layer4.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: layer4.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "layer4.h"
#include "check_api.h"
+#include "utils.h"
enum connect_result
tcp_connect (int fd, uint32_t addr_ip, uint16_t addr_port)
*
* Part: layer4.c include file.
*
- * Version: $Id: layer4.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: layer4.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
+# Makefile to make libipfwc.
+
+CC = gcc
+COPTS = -g -O
+CFLAGS = -Wall -Wunused $(COPTS)
+
+libipfwc.a: libipfwc.a(libipfwc.o)
+
+libipfwc.o: libipfwc.h ipfwc_kernel_headers.h
+
+clean:
+ rm -f *.a *.o *~
}
/* Get raw socket. */
-int ipfwc_get_raw_socket(void)
+int ipfwc_get_raw_socket()
{
return sockfd;
}
*
* Part: List structure manipulation.
*
- * Version: $Id: list.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: list.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: list.c include file.
*
- * Version: $Id: list.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: list.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Main program structure.
*
- * Version: $Id: main.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: main.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "daemon.h"
#include "memory.h"
#include "parser.h"
+#include "vrrp_if.h"
/* SIGHUP handler */
void sighup(int sig)
signal_set(SIGINT, sighup);
signal_set(SIGTERM, sighup);
signal_set(SIGKILL, sighup);
- signal_set (SIGCHLD, sigchld);
+ signal_set(SIGCHLD, sigchld);
}
/* Usage function */
/* Create the master thread */
master = thread_make_master();
+ /* Init interface queue */
+ init_interface_queue();
+
/* Parse the configuration file */
init_checkers_queue();
init_keywords();
syslog(LOG_INFO, "Stopping "VERSION_STRING);
closelog();
thread_destroy_master(master);
+#ifdef _DEBUG_
keepalived_free_final();
+#endif
exit(0);
}
if (!init_ssl_ctx()) {
closelog();
thread_destroy_master(master);
+#ifdef _DEBUG_
keepalived_free_final();
+#endif
exit(0);
}
thread_destroy_master(master);
clear_services();
shutdown_vrrp_instances();
+ free_interface_queue();
free_data();
pidfile_rm();
*
* Part: Main program include file.
*
- * Version: $Id: main.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: main.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "smtp.h"
#include "vrrp.h"
#include "check_api.h"
-//#include "check_ssl.h"
+#include "vrrp_netlink.h"
/* global var */
thread_master *master;
/* Build version */
#define PROG "Keepalived"
-#define VERSION_CODE 0x000503
-#define DATE_CODE 0x160202
+#define VERSION_CODE 0x000505
+#define DATE_CODE 0x0a0402
#define KEEPALIVED_VERSION(version) \
(version >> 16) & 0xFF, \
(version >> 8) & 0xFF, \
version & 0xFF
-#define VERSION_STRING PROG" v%d.%d.%d (%.2d/%.2d, 20%.2d)", \
+#define VERSION_STRING PROG" v%d.%d.%d (%.2d/%.2d, 20%.2d)\n", \
KEEPALIVED_VERSION(VERSION_CODE), \
KEEPALIVED_VERSION(DATE_CODE)
#endif
* Part: Memory management framework. This framework is used to
* find any memory leak.
*
- * Version: $Id: memory.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: memory.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
*
* Part: memory.c include file.
*
- * Version: $Id: memory.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: memory.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
* data structure representation the conf file representing
* the loadbalanced server pool.
*
- * Version: $Id: parser.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: parser.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
}
static void vrrp_isync_handler(vector strvec)
{
- vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
vrrp->isync = set_value(strvec);
}
static void vrrp_state_handler(vector strvec)
{
char *str = VECTOR_SLOT(strvec, 1);
- vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
- vrrp_rt *rt = vrrp->vsrv;
+ vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
if (!strcmp(str, "MASTER")) {
- rt->wantstate = VRRP_STATE_MAST;
- rt->init_state = VRRP_STATE_MAST;
+ vrrp->wantstate = VRRP_STATE_MAST;
+ vrrp->init_state = VRRP_STATE_MAST;
} else {
- rt->wantstate = VRRP_STATE_BACK;
- rt->init_state = VRRP_STATE_BACK;
+ vrrp->wantstate = VRRP_STATE_BACK;
+ vrrp->init_state = VRRP_STATE_BACK;
}
}
static void vrrp_int_handler(vector strvec)
{
- vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
- vrrp->vsrv->vif->ifname = set_value(strvec);
+ vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ char *name = VECTOR_SLOT(strvec, 1);
+
+ vrrp->ifp = if_get_by_ifname(name);
}
static void vrrp_vrid_handler(vector strvec)
{
- vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
- vrrp->vsrv->vrid = atoi(VECTOR_SLOT(strvec, 1));
+ vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp->vrid = atoi(VECTOR_SLOT(strvec, 1));
- if (VRRP_IS_BAD_VID(vrrp->vsrv->vrid)) {
+ if (VRRP_IS_BAD_VID(vrrp->vrid)) {
syslog(LOG_INFO, "VRRP Error : VRID not valid !\n");
syslog(LOG_INFO, " must be between 1 & 255. reconfigure !\n");
}
}
static void vrrp_prio_handler(vector strvec)
{
- vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
- vrrp->vsrv->priority = atoi(VECTOR_SLOT(strvec, 1));
+ vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp->priority = atoi(VECTOR_SLOT(strvec, 1));
- if (VRRP_IS_BAD_PRIORITY(vrrp->vsrv->priority)) {
+ if (VRRP_IS_BAD_PRIORITY(vrrp->priority)) {
syslog(LOG_INFO, "VRRP Error : Priority not valid !\n");
syslog(LOG_INFO, " must be between 1 & 255. reconfigure !\n");
syslog(LOG_INFO, " Using default value : 100\n");
- vrrp->vsrv->priority = 100;
+ vrrp->priority = 100;
}
}
static void vrrp_adv_handler(vector strvec)
{
- vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
- vrrp->vsrv->adver_int = atoi(VECTOR_SLOT(strvec, 1));
+ vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp->adver_int = atoi(VECTOR_SLOT(strvec, 1));
- if (VRRP_IS_BAD_ADVERT_INT(vrrp->vsrv->adver_int)) {
+ if (VRRP_IS_BAD_ADVERT_INT(vrrp->adver_int)) {
syslog(LOG_INFO, "VRRP Error : Advert intervall not valid !\n");
syslog(LOG_INFO, " must be between less than 1sec.\n");
syslog(LOG_INFO, " Using default value : 1sec\n");
- vrrp->vsrv->adver_int = 1;
+ vrrp->adver_int = 1;
}
- vrrp->vsrv->adver_int *= TIMER_HZ;
+ vrrp->adver_int *= TIMER_HZ;
}
static void vrrp_debug_handler(vector strvec)
{
- vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
- vrrp->vsrv->debug = atoi(VECTOR_SLOT(strvec, 1));
+ vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp->debug = atoi(VECTOR_SLOT(strvec, 1));
- if (VRRP_IS_BAD_DEBUG_INT(vrrp->vsrv->debug)) {
+ if (VRRP_IS_BAD_DEBUG_INT(vrrp->debug)) {
syslog(LOG_INFO, "VRRP Error : Debug intervall not valid !\n");
syslog(LOG_INFO, " must be between 0-4\n");
- vrrp->vsrv->debug = 0;
+ vrrp->debug = 0;
}
}
static void vrrp_preempt_handler(vector strvec)
{
- vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
- vrrp->vsrv->preempt = !vrrp->vsrv->preempt;
+ vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp->preempt = !vrrp->preempt;
}
static void vrrp_notify_handler(vector strvec)
{
- vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
char *str = VECTOR_SLOT(strvec, 1);
- int size = sizeof(vrrp->vsrv->notify_file);
+ int size = sizeof(vrrp->notify_file);
- memcpy(vrrp->vsrv->notify_file, str, size);
- vrrp->vsrv->notify_exec = 1;
+ memcpy(vrrp->notify_file, str, size);
+ vrrp->notify_exec = 1;
+}
+static void vrrp_lvs_syncd_handler(vector strvec)
+{
+ vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp->lvs_syncd_if = set_value(strvec);
}
static void vrrp_auth_type_handler(vector strvec)
{
- vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
char *str = VECTOR_SLOT(strvec, 1);
if (!strcmp(str, "AH"))
- vrrp->vsrv->vif->auth_type = VRRP_AUTH_AH;
+ vrrp->auth_type = VRRP_AUTH_AH;
else
- vrrp->vsrv->vif->auth_type = VRRP_AUTH_PASS;
+ vrrp->auth_type = VRRP_AUTH_PASS;
}
static void vrrp_auth_pass_handler(vector strvec)
{
- vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
char *str = VECTOR_SLOT(strvec, 1);
- int size = sizeof(vrrp->vsrv->vif->auth_data);
+ int size = sizeof(vrrp->auth_data);
- memcpy(vrrp->vsrv->vif->auth_data, str, size);
+ memcpy(vrrp->auth_data, str, size);
}
static void vrrp_vip_handler(vector strvec)
{
install_keyword("preempt", &vrrp_preempt_handler);
install_keyword("debug", &vrrp_debug_handler);
install_keyword("notify", &vrrp_notify_handler);
+ install_keyword("lvs_sync_daemon_interface", &vrrp_lvs_syncd_handler);
install_keyword("authentication", NULL);
install_sublevel();
install_keyword("auth_type", &vrrp_auth_type_handler);
*
* Part: cfreader.c include file.
*
- * Version: $Id: parser.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: parser.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: pidfile utility.
*
- * Version: $Id: pidfile.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: pidfile.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: pidfile.c include file.
*
- * Version: $Id: pidfile.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: pidfile.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
-# Configuration File for keepalived
+! Configuration File for keepalived
global_defs {
notification_email {
lvs_id LVS_DEVEL
}
-;SSL {
- password password
- ca /etc/keepalived/root.pem
- certificate /etc/keepalived/dh1024.pem
- key /etc/keepalived/client.pem
-}
+!SSL {
+! password password
+! ca /etc/keepalived/root.pem
+! certificate /etc/keepalived/dh1024.pem
+! key /etc/keepalived/client.pem
+!}
vrrp_instance VI_1 {
state MASTER
-# Configuration File for keepalived
+! Configuration File for keepalived
global_defs {
notification_email {
-# Configuration File for keepalived
+! Configuration File for keepalived
global_defs {
notification_email {
-# Configuration File for keepalived
+! Configuration File for keepalived
global_defs {
notification_email {
-# Configuration File for keepalived
+! Configuration File for keepalived
global_defs {
notification_email {
--- /dev/null
+! Configuration File for keepalived
+
+vrrp_instance VI_1 {
+ state MASTER
+ interface eth0
+ lvs_sync_daemon_interface eth1
+ virtual_router_id 51
+ priority 150
+ advert_int 1
+ authentication {
+ auth_type PASS
+ auth_pass grr02
+ }
+ virtual_ipaddress {
+ 192.168.200.16
+ 192.168.200.17
+ 192.168.200.18
+ }
+}
+
+vrrp_instance VI_2 {
+ interface eth0
+ virtual_router_id 52
+ priority 100
+ advert_int 1
+ virtual_ipaddress {
+ 192.168.200.19
+ 192.168.200.20
+ 192.168.200.21
+ }
+ sync_instance VI_3
+}
+
+vrrp_instance VI_3 {
+ interface eth1
+ virtual_router_id 53
+ priority 100
+ advert_int 1
+ virtual_ipaddress {
+ 192.168.201.19
+ 192.168.201.20
+ 192.168.201.21
+ }
+ sync_instance VI_2
+}
+
+virtual_server 192.168.200.19 80 {
+ delay_loop 20
+ lb_algo rr
+ lb_kind NAT
+ nat_mask 255.255.255.0
+ persistence_timeout 50
+ protocol TCP
+
+ real_server 192.168.201.100 80 {
+ weight 1
+ TCP_CHECK {
+ connect_timeout 3
+ }
+ }
+}
-# Configuration File for keepalived
+! Configuration File for keepalived
global_defs {
notification_email {
* the thread management routine (thread.c) present in the
* very nice zebra project (http://www.zebra.org).
*
- * Version: $Id: scheduler.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: scheduler.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: scheduler.c include file.
*
- * Version: $Id: scheduler.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: scheduler.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* using the smtp protocol according to the RFC 821. A non blocking
* timeouted connection is used to handle smtp protocol.
*
- * Version: $Id: smtp.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: smtp.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "smtp.h"
#include "memory.h"
#include "list.h"
+#include "utils.h"
extern data *conf_data;
*
* Part: smtp.c include file.
*
- * Version: $Id: smtp.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: smtp.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Timer manipulations.
*
- * Version: $Id: timer.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: timer.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: timer.c include file.
*
- * Version: $Id: timer.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: timer.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: General program utils.
*
- * Version: $Id: utils.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: utils.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: utils.h include file.
*
- * Version: $Id: utils.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: utils.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Vector structure manipulation.
*
- * Version: $Id: vector.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: vector.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vector.c include file.
*
- * Version: $Id: vector.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: vector.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* master fails, a backup server takes over.
* The original implementation has been made by jerome etienne.
*
- * Version: $Id: vrrp.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: vrrp.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* local include */
#include "vrrp_scheduler.h"
+#include "ipvswrapper.h"
#include "vrrp.h"
#include "memory.h"
#include "list.h"
+#include "data.h"
+
+extern data *conf_data;
/* Close all FDs >= a specified value */
void closeall(int fd)
close(fd++);
}
-static char *notify_get_name(vrrp_rt *vsrv)
+static char *notify_get_name(vrrp_rt *vrrp)
{
static char notifyfile[FILENAME_MAX+1];
- if (vsrv->notify_exec) {
- if (vsrv->notify_file != NULL)
- strncpy(notifyfile,vsrv->notify_file, FILENAME_MAX);
+ if (vrrp->notify_exec) {
+ if (vrrp->notify_file != NULL)
+ strncpy(notifyfile, vrrp->notify_file, FILENAME_MAX);
else
- snprintf( notifyfile, sizeof(notifyfile),"%s/" VRRP_NOTIFY_FORMAT
- , VRRP_NOTIFY_DFL
- , vsrv->vif->ifname
- , vsrv->vrid );
+ snprintf(notifyfile, sizeof(notifyfile),"%s/" VRRP_NOTIFY_FORMAT
+ , VRRP_NOTIFY_DFL
+ , IF_NAME(vrrp->ifp)
+ , vrrp->vrid );
}
return notifyfile;
}
/* Execute extern script/program */
-static int notify_exec( vrrp_rt *vsrv , char *cmd)
+static int notify_exec(vrrp_rt *vrrp , char *cmd)
{
- char *name = notify_get_name(vsrv);
+ char *name = notify_get_name(vrrp);
FILE *fOut = fopen(name, "r");
static char mycmd[FILENAME_MAX + 1 + 32];
char tmp[16];
dup(0);
dup(0);
- name = notify_get_name(vsrv);
+ name = notify_get_name(vrrp);
if (strlen(name) + strlen(cmd) + 32 > FILENAME_MAX + 32) {
- syslog(LOG_INFO,"To long exec stmt");
+ syslog(LOG_INFO, "To long exec stmt");
exit (1);
}
- strcpy(mycmd,name);
- strcat(mycmd," ");
- strcat(mycmd,cmd);
- strcat(mycmd," ");
- snprintf(tmp,16,"%d",vsrv->vrid);
+ strcpy(mycmd, name);
+ strcat(mycmd, " ");
+ strcat(mycmd, cmd);
+ strcat(mycmd, " ");
+ snprintf(tmp, 16, "%d", vrrp->vrid);
strcat(mycmd, tmp);
- if (vsrv->debug > 0)
+ if (vrrp->debug > 0)
syslog(LOG_INFO, "Trying to exec %s", mycmd);
err = system(mycmd);
return (answer);
}
-/* retrieve MAC address from interface name */
-static int hwaddr_get(char *ifname, char *addr, int addrlen)
-{
- struct ifreq ifr;
- int fd = socket(AF_INET, SOCK_DGRAM, 0);
- int ret;
-
- if (fd < 0) return (-1);
- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
- ret = ioctl(fd, SIOCGIFHWADDR, (char *)&ifr);
- memcpy(addr, ifr.ifr_hwaddr.sa_data, addrlen);
- close(fd);
- return ret;
-}
-
-/* resolve ipaddress from interface name */
-static uint32_t ifname_to_ip(const char *ifname)
-{
- struct ifreq ifr;
- int fd = socket(AF_INET, SOCK_DGRAM, 0);
- uint32_t addr = 0;
-
- if (fd < 0) return (-1);
- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
- if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) == 0) {
- struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
- addr = ntohl(sin->sin_addr.s_addr);
- }
-
- close(fd);
- return addr;
-}
-
-/* resolve interface index from interface name */
-int ifname_to_idx(const char *ifname)
-{
- struct ifreq ifr;
- int fd = socket(AF_INET, SOCK_DGRAM, 0);
- int ifindex = -1;
-
- if (fd < 0) return (-1);
- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
- if (ioctl(fd, SIOCGIFINDEX, (char *)&ifr) == 0)
- ifindex = ifr.ifr_ifindex;
-
- close(fd);
- return ifindex;
-}
-
-/* resolve ifname from index */
-static void index_to_ifname(const int ifindex, char *ifname)
-{
- struct ifreq ifr;
- int fd = socket(AF_INET, SOCK_DGRAM, 0);
-
- if (fd < 0) return;
-
- /* get interface name */
- ifr.ifr_ifindex = ifindex;
- if (ioctl(fd, SIOCGIFNAME, (char *)&ifr) == 0)
- strncpy(ifname, ifr.ifr_name, sizeof(ifr.ifr_name));
- close(fd);
-}
-
-/* resolve ipaddress from interface index */
-static uint32_t index_to_ip(const int ifindex)
-{
- char ifname[IFNAMSIZ];
-
- memset(&ifname, 0, IFNAMSIZ);
- index_to_ifname(ifindex, ifname);
-
- return(ifname_to_ip(ifname));
-}
-
/*
* add/remove VIP
* retry must clear for each vip address Hoj:-
*/
-static int vrrp_handle_ipaddress(vrrp_rt *vsrv, int cmd)
+static int vrrp_handle_ipaddress(vrrp_rt *vrrp, int cmd)
{
int i, err = 0;
- int retry;
- int ifidx = ifname_to_idx(vsrv->vif->ifname);
+ int retry = 0;
+ int ifindex = IF_INDEX(vrrp->ifp);
- for(i = 0; i < vsrv->naddr; i++ ) {
- vip_addr *vadd = &vsrv->vaddr[i];
- retry ^= retry;
- if(!cmd && !vadd->deletable) continue;
+ for(i = 0; i < vrrp->naddr; i++ ) {
+ vip_addr *vadd = &vrrp->vaddr[i];
+ if(!cmd && !vadd->set) continue;
retry:
- if (netlink_address_ipv4(ifidx , ntohl(vadd->addr), cmd) < 0) {
+ if (netlink_address_ipv4(ifindex , ntohl(vadd->addr), cmd) < 0) {
err = 1;
- vadd->deletable = 0;
+ vadd->set = 0;
syslog(LOG_INFO, "cant %s the address %s to %s\n"
, cmd ? "set" : "remove"
, ip_ntoa(vadd->addr)
- , vsrv->vif->ifname);
+ , IF_NAME(vrrp->ifp));
if (cmd == VRRP_IPADDRESS_ADD) {
syslog(LOG_INFO, "try to delete eventual stalled ip");
- netlink_address_ipv4(ifidx, ntohl(vadd->addr), VRRP_IPADDRESS_DEL);
- if (!retry) {
+ netlink_address_ipv4(ifindex, ntohl(vadd->addr), VRRP_IPADDRESS_DEL);
+ if (retry < 4) {
retry++;
goto retry;
}
}
} else {
- vadd->deletable = 1;
+ vadd->set = 1;
}
}
return err;
}
/* IP header length */
-static int vrrp_iphdr_len(vrrp_rt *vsrv)
+static int vrrp_iphdr_len(vrrp_rt *vrrp)
{
return sizeof(struct iphdr);
}
}
/* VRRP header length */
-static int vrrp_hd_len(vrrp_rt *vsrv)
+static int vrrp_hd_len(vrrp_rt *vrrp)
{
return sizeof(vrrp_pkt)
- + vsrv->naddr*sizeof(uint32_t)
+ + vrrp->naddr * sizeof(uint32_t)
+ VRRP_AUTH_LEN;
}
* IPSEC AH incoming packet check.
* return 0 for a valid pkt, != 0 otherwise.
*/
-static int vrrp_in_chk_ipsecah(vrrp_rt *vsrv, char *buffer)
+static int vrrp_in_chk_ipsecah(vrrp_rt *vrrp, char *buffer)
{
struct iphdr *ip = (struct iphdr*)(buffer);
ipsec_ah *ah = (ipsec_ah *)((char *)ip + (ip->ihl<<2));
* in inbound processing, we increment seq_number counter to audit
* sender counter.
*/
- vsrv->ipsecah_counter->seq_number++;
- if (ah->seq_number >= vsrv->ipsecah_counter->seq_number) {
-#ifdef _DEBUG_
-// syslog(LOG_DEBUG, "IPSEC AH : SEQUENCE NUMBER : %d\n", ah->seq_number);
-#endif
- vsrv->ipsecah_counter->seq_number = ah->seq_number;
+ vrrp->ipsecah_counter->seq_number++;
+ if (ah->seq_number >= vrrp->ipsecah_counter->seq_number) {
+ vrrp->ipsecah_counter->seq_number = ah->seq_number;
} else {
syslog(LOG_INFO, "IPSEC AH : sequence number %d already proceeded."
" Packet droped", ah->seq_number);
memset(ah->auth_data, 0, sizeof(ah->auth_data));
/* Compute the ICV */
- hmac_md5(buffer, vrrp_iphdr_len(vsrv)+vrrp_ipsecah_len()+vrrp_hd_len(vsrv),
- vsrv->vif->auth_data, sizeof(vsrv->vif->auth_data), digest);
+ hmac_md5(buffer, vrrp_iphdr_len(vrrp) + vrrp_ipsecah_len() + vrrp_hd_len(vrrp)
+ , vrrp->auth_data
+ , sizeof(vrrp->auth_data)
+ , digest);
if (memcmp(backup_auth_data, digest, HMAC_MD5_TRUNC) != 0) {
syslog(LOG_INFO, "IPSEC AH : invalid IPSEC HMAC-MD5 value."
}
/* check if ipaddr is present in VIP buffer */
-static int vrrp_in_chk_vips(vrrp_rt *vsrv, uint32_t ipaddr, unsigned char *buffer)
+static int vrrp_in_chk_vips(vrrp_rt *vrrp, uint32_t ipaddr, unsigned char *buffer)
{
int i;
uint32_t ipbuf;
- for (i=0; i < vsrv->naddr; i++) {
+ for (i=0; i < vrrp->naddr; i++) {
bcopy(buffer+i*sizeof(uint32_t), &ipbuf, sizeof(uint32_t));
if (ipaddr == ntohl(ipbuf)) return 1;
}
* VRRP incoming packet check.
* return 0 if the pkt is valid, != 0 otherwise.
*/
-static int vrrp_in_chk(vrrp_rt *vsrv, char *buffer)
+static int vrrp_in_chk(vrrp_rt *vrrp, char *buffer)
{
struct iphdr *ip = (struct iphdr*)(buffer);
int ihl = ip->ihl << 2;
- vrrp_if *vif = vsrv->vif;
ipsec_ah *ah;
vrrp_pkt *hd;
unsigned char *vips;
int i;
- if (vif->auth_type == VRRP_AUTH_AH) {
+ if (vrrp->auth_type == VRRP_AUTH_AH) {
ah = (ipsec_ah *)(buffer + sizeof(struct iphdr));
hd = (vrrp_pkt *)(buffer + ihl + vrrp_ipsecah_len());
} else {
}
/* MUST verify the VRRP checksum */
- if (in_csum( (u_short*)hd, vrrp_hd_len(vsrv), 0)) {
+ if (in_csum( (u_short*)hd, vrrp_hd_len(vrrp), 0)) {
syslog(LOG_INFO, "Invalid vrrp checksum");
return VRRP_PACKET_KO;
}
* MUST perform authentication specified by Auth Type
* check the authentication type
*/
- if (vif->auth_type != hd->auth_type) {
- syslog(LOG_INFO, "receive a %d auth, expecting %d!", vif->auth_type
+ if (vrrp->auth_type != hd->auth_type) {
+ syslog(LOG_INFO, "receive a %d auth, expecting %d!", vrrp->auth_type
, hd->auth_type);
return VRRP_PACKET_KO;
}
/* check the authentication if it is a passwd */
if (hd->auth_type == VRRP_AUTH_PASS) {
char *pw = (char *)ip + ntohs(ip->tot_len)
- - sizeof(vif->auth_data);
- if (memcmp( pw, vif->auth_data, sizeof(vif->auth_data))){
+ - sizeof(vrrp->auth_data);
+ if (memcmp(pw, vrrp->auth_data, sizeof(vrrp->auth_data))) {
syslog(LOG_INFO, "receive an invalid passwd!");
return VRRP_PACKET_KO;
}
}
/* MUST verify that the VRID is valid on the receiving interface */
- if (vsrv->vrid != hd->vrid) {
- syslog(LOG_INFO, "received VRID mismatch. Received %d, Expected %d",
- hd->vrid, vsrv->vrid);
+ if (vrrp->vrid != hd->vrid) {
+ syslog(LOG_INFO, "received VRID mismatch. Received %d, Expected %d"
+ , hd->vrid
+ , vrrp->vrid);
return VRRP_PACKET_DROP;
}
* MAY verify that the IP address(es) associated with the
* VRID are valid
*/
- if (vsrv->naddr != hd->naddr) {
+ if (vrrp->naddr != hd->naddr) {
syslog(LOG_INFO, "receive an invalid ip number count associated with VRID!");
return VRRP_PACKET_KO;
}
- for (i=0; i < vsrv->naddr; i++)
- if (!vrrp_in_chk_vips(vsrv,vsrv->vaddr[i].addr,vips)) {
+ for (i=0; i < vrrp->naddr; i++)
+ if (!vrrp_in_chk_vips(vrrp, vrrp->vaddr[i].addr,vips)) {
syslog(LOG_INFO, "ip address associated with VRID"
" not present in received packet : %d"
- , vsrv->vaddr[i].addr);
+ , vrrp->vaddr[i].addr);
syslog(LOG_INFO, "one or more VIP associated with"
" VRID mismatch actual MASTER advert");
return VRRP_PACKET_KO;
* MUST verify that the Adver Interval in the packet is the same as
* the locally configured for this virtual router
*/
- if (vsrv->adver_int/TIMER_HZ != hd->adver_int) {
+ if (vrrp->adver_int/TIMER_HZ != hd->adver_int) {
syslog(LOG_INFO, "advertissement interval mismatch mine=%d rcved=%d"
- , vsrv->adver_int, hd->adver_int);
+ , vrrp->adver_int
+ , hd->adver_int);
/* to prevent concurent VRID running => multiple master in 1 VRID */
return VRRP_PACKET_DROP;
}
/* check the authenicaion if it is ipsec ah */
if(hd->auth_type == VRRP_AUTH_AH)
- return(vrrp_in_chk_ipsecah(vsrv, buffer));
+ return(vrrp_in_chk_ipsecah(vrrp, buffer));
return VRRP_PACKET_OK;
}
/* build ARP header */
-static void vrrp_build_dlt(vrrp_rt *vsrv, char *buffer, int buflen)
+static void vrrp_build_arp(vrrp_rt *vrrp, char *buffer, int buflen)
{
/* hardcoded for ethernet */
struct ether_header * eth = (struct ether_header *)buffer;
eth->ether_dhost[5] = INADDR_VRRP_GROUP & 0xFF;
/* source address -- rfc2338.7.3 */
- memcpy(eth->ether_shost, vsrv->hwaddr, sizeof(vsrv->hwaddr));
+ memcpy(eth->ether_shost, vrrp->hwaddr, sizeof(vrrp->hwaddr));
/* type */
eth->ether_type = htons(ETHERTYPE_IP);
}
/* build IP header */
-static void vrrp_build_ip(vrrp_rt *vsrv, char *buffer, int buflen)
+static void vrrp_build_ip(vrrp_rt *vrrp, char *buffer, int buflen)
{
struct iphdr *ip = (struct iphdr *)(buffer);
ip->ihl = 5;
ip->version = 4;
ip->tos = 0;
- ip->tot_len = ip->ihl*4 + vrrp_hd_len(vsrv);
+ ip->tot_len = ip->ihl*4 + vrrp_hd_len(vrrp);
ip->tot_len = htons(ip->tot_len);
- ip->id = ++vsrv->vif->ip_id;
+ ip->id = ++vrrp->ip_id;
ip->frag_off = 0;
ip->ttl = VRRP_IP_TTL;
/* fill protocol type --rfc2402.2 */
- ip->protocol = (vsrv->vif->auth_type == VRRP_AUTH_AH)?IPPROTO_IPSEC_AH:IPPROTO_VRRP;
- ip->saddr = htonl(vsrv->vif->ipaddr);
+ ip->protocol = (vrrp->auth_type == VRRP_AUTH_AH)?IPPROTO_IPSEC_AH:IPPROTO_VRRP;
+ ip->saddr = IF_ADDR(vrrp->ifp);
ip->daddr = htonl(INADDR_VRRP_GROUP);
/* checksum must be done last */
}
/* build IPSEC AH header */
-static void vrrp_build_ipsecah(vrrp_rt *vsrv, char *buffer, int buflen)
+static void vrrp_build_ipsecah(vrrp_rt *vrrp, char *buffer, int buflen)
{
ICV_mutable_fields *ip_mutable_fields;
unsigned char *digest;
ah->next_header = IPPROTO_VRRP;
/* update IP header total length value */
- ip->tot_len = ip->ihl*4 + vrrp_ipsecah_len() + vrrp_hd_len(vsrv);
+ ip->tot_len = ip->ihl*4 + vrrp_ipsecah_len() + vrrp_hd_len(vrrp);
ip->tot_len = htons(ip->tot_len);
/* update ip checksum */
In the current implementation if counter has cycled, we stop sending adverts and
become BACKUP. If all the master are down we reset the counter for becoming MASTER.
*/
-// if (vsrv->ipsecah_counter->seq_number > 5) {
- if (vsrv->ipsecah_counter->seq_number > 0xFFFFFFFD) {
- vsrv->ipsecah_counter->cycle = 1;
+// if (vrrp->ipsecah_counter->seq_number > 5) {
+ if (vrrp->ipsecah_counter->seq_number > 0xFFFFFFFD) {
+ vrrp->ipsecah_counter->cycle = 1;
} else {
- vsrv->ipsecah_counter->seq_number++;
+ vrrp->ipsecah_counter->seq_number++;
}
- ah->seq_number = vsrv->ipsecah_counter->seq_number;
+ ah->seq_number = vrrp->ipsecah_counter->seq_number;
/* Compute the ICV & trunc the digest to 96bits
=> No padding needed.
-- rfc2402.3.3.3.1.1.1 & rfc2401.5
*/
digest = (unsigned char *)MALLOC(16*sizeof(unsigned char *));
- hmac_md5(buffer, buflen,vsrv->vif->auth_data, sizeof(vsrv->vif->auth_data), digest);
+ hmac_md5(buffer, buflen
+ , vrrp->auth_data
+ , sizeof(vrrp->auth_data)
+ , digest);
memcpy(ah->auth_data, digest, HMAC_MD5_TRUNC);
/* Restore the ip mutable fields */
}
/* build VRRP header */
-static int vrrp_build_vrrp(vrrp_rt *vsrv, int prio, char *buffer, int buflen)
+static int vrrp_build_vrrp(vrrp_rt *vrrp, int prio, char *buffer, int buflen)
{
int i;
- vrrp_if *vif = vsrv->vif;
vrrp_pkt *hd = (vrrp_pkt *)buffer;
uint32_t *iparr = (uint32_t *)((char *)hd+sizeof(*hd));
hd->vers_type = (VRRP_VERSION<<4) | VRRP_PKT_ADVERT;
- hd->vrid = vsrv->vrid;
- hd->priority = prio;
- hd->naddr = vsrv->naddr;
- hd->auth_type = vsrv->vif->auth_type;
- hd->adver_int = vsrv->adver_int/TIMER_HZ;
+ hd->vrid = vrrp->vrid;
+ hd->priority = prio;
+ hd->naddr = vrrp->naddr;
+ hd->auth_type = vrrp->auth_type;
+ hd->adver_int = vrrp->adver_int/TIMER_HZ;
/* copy the ip addresses */
- for( i = 0; i < vsrv->naddr; i++ ){
- iparr[i] = htonl(vsrv->vaddr[i].addr);
+ for( i = 0; i < vrrp->naddr; i++ ){
+ iparr[i] = htonl(vrrp->vaddr[i].addr);
}
- hd->chksum = in_csum( (u_short*)hd, vrrp_hd_len(vsrv), 0);
/* copy the passwd if the authentication is VRRP_AH_PASS */
- if( vif->auth_type == VRRP_AUTH_PASS ){
- char *pw = (char *)hd + sizeof(*hd) + vsrv->naddr*4;
- memcpy(pw, vif->auth_data, sizeof(vif->auth_data));
+ if (vrrp->auth_type == VRRP_AUTH_PASS) {
+ char *pw = (char *)hd + sizeof(*hd) + vrrp->naddr*4;
+ memcpy(pw, vrrp->auth_data, sizeof(vrrp->auth_data));
}
+ /* finaly compute vrrp checksum */
+ hd->chksum = in_csum( (u_short*)hd, vrrp_hd_len(vrrp), 0);
+
return(0);
}
/* build VRRP packet */
-static void vrrp_build_pkt(vrrp_rt *vsrv, int prio, char *buffer, int buflen)
+static void vrrp_build_pkt(vrrp_rt *vrrp, int prio, char *buffer, int buflen)
{
char *bufptr;
bufptr = buffer;
/* build the ethernet header */
- vrrp_build_dlt(vsrv, buffer, buflen);
+ vrrp_build_arp(vrrp, buffer, buflen);
/* build the ip header */
- buffer += vrrp_dlt_len(vsrv);
- buflen -= vrrp_dlt_len(vsrv);
- vrrp_build_ip(vsrv, buffer, buflen);
+ buffer += vrrp_dlt_len(vrrp);
+ buflen -= vrrp_dlt_len(vrrp);
+ vrrp_build_ip(vrrp, buffer, buflen);
/* build the vrrp header */
- buffer += vrrp_iphdr_len(vsrv);
+ buffer += vrrp_iphdr_len(vrrp);
- if (vsrv->vif->auth_type == VRRP_AUTH_AH)
+ if (vrrp->auth_type == VRRP_AUTH_AH)
buffer += vrrp_ipsecah_len();
- buflen -= vrrp_iphdr_len(vsrv);
+ buflen -= vrrp_iphdr_len(vrrp);
- if (vsrv->vif->auth_type == VRRP_AUTH_AH)
+ if (vrrp->auth_type == VRRP_AUTH_AH)
buflen -= vrrp_ipsecah_len();
- vrrp_build_vrrp(vsrv, prio, buffer, buflen);
+ vrrp_build_vrrp(vrrp, prio, buffer, buflen);
/* build the IPSEC AH header */
- if (vsrv->vif->auth_type == VRRP_AUTH_AH) {
- bufptr += vrrp_dlt_len(vsrv);
- buflen += vrrp_ipsecah_len() + vrrp_iphdr_len(vsrv);;
- vrrp_build_ipsecah(vsrv, bufptr, buflen);
+ if (vrrp->auth_type == VRRP_AUTH_AH) {
+ bufptr += vrrp_dlt_len(vrrp);
+ buflen += vrrp_ipsecah_len() + vrrp_iphdr_len(vrrp);;
+ vrrp_build_ipsecah(vrrp, bufptr, buflen);
}
}
/* send VRRP packet */
-static int vrrp_send_pkt(vrrp_rt *vsrv, char *buffer, int buflen)
+static int vrrp_send_pkt(vrrp_rt *vrrp, char *buffer, int buflen)
{
struct sockaddr from;
int len;
/* build the address */
memset(&from, 0 , sizeof(from));
- strcpy(from.sa_data, vsrv->vif->ifname);
+ strcpy(from.sa_data, IF_NAME(vrrp->ifp));
//print_buffer(buflen, buffer);
}
/* send VRRP advertissement */
-static int vrrp_send_adv(vrrp_rt *vsrv, int prio)
+static int vrrp_send_adv(vrrp_rt *vrrp, int prio)
{
int buflen, ret;
char *buffer;
/* alloc the memory */
- buflen = vrrp_dlt_len(vsrv) + vrrp_iphdr_len(vsrv) + vrrp_hd_len(vsrv);
- if (vsrv->vif->auth_type == VRRP_AUTH_AH)
+ buflen = vrrp_dlt_len(vrrp) + vrrp_iphdr_len(vrrp) + vrrp_hd_len(vrrp);
+ if (vrrp->auth_type == VRRP_AUTH_AH)
buflen += vrrp_ipsecah_len();
buffer = MALLOC(buflen);
/* build the packet */
- vrrp_build_pkt(vsrv, prio, buffer, buflen);
+ vrrp_build_pkt(vrrp, prio, buffer, buflen);
/* send it */
- ret = vrrp_send_pkt(vsrv, buffer, buflen);
+ ret = vrrp_send_pkt(vrrp, buffer, buflen);
/* free the memory */
FREE(buffer);
}
/* Received packet processing */
-int vrrp_check_packet(vrrp_rt *vsrv, char *buf, int buflen)
+int vrrp_check_packet(vrrp_rt *vrrp, char *buf, int buflen)
{
int ret;
if (buflen > 0) {
- ret = vrrp_in_chk(vsrv, buf);
+ ret = vrrp_in_chk(vrrp, buf);
if (ret == VRRP_PACKET_DROP) {
- syslog(LOG_INFO, "Sync instance needed on %s !!!",
- vsrv->vif->ifname);
+ syslog(LOG_INFO, "Sync instance needed on %s !!!"
+ , IF_NAME(vrrp->ifp));
}
if (ret == VRRP_PACKET_KO)
- syslog(LOG_INFO, "bogus VRRP packet received on %s !!!",
- vsrv->vif->ifname);
+ syslog(LOG_INFO, "bogus VRRP packet received on %s !!!"
+ , IF_NAME(vrrp->ifp));
// else
-// syslog(LOG_INFO, "Success receiving VRRP packet on %s.",
-// vsrv->vif->ifname);
+// syslog(LOG_INFO, "Success receiving VRRP packet on %s."
+// , IF_NAME(vrrp->ifp));
return ret;
}
}
/* send a gratuitous ARP packet */
-static int send_gratuitous_arp(vrrp_rt *vsrv, int addr)
+static int send_gratuitous_arp(vrrp_rt *vrrp, int addr)
{
struct m_arphdr {
unsigned short int ar_hrd; /* Format of hardware address. */
char buf[sizeof(struct m_arphdr) + ETHER_HDR_LEN];
char buflen = sizeof(struct m_arphdr) + ETHER_HDR_LEN;
struct ether_header *eth = (struct ether_header *)buf;
- struct m_arphdr *arph = (struct m_arphdr *)(buf + vrrp_dlt_len(vsrv));
- char *hwaddr = vsrv->vif->hwaddr;
+ struct m_arphdr *arph = (struct m_arphdr *)(buf + vrrp_dlt_len(vrrp));
+ char *hwaddr = IF_HWADDR(vrrp->ifp);
int hwlen = ETH_ALEN;
/* hardcoded for ethernet */
addr = htonl(addr);
memcpy(arph->__ar_sip, &addr, sizeof(addr));
memcpy(arph->__ar_tip, &addr, sizeof(addr));
- return vrrp_send_pkt(vsrv, buf, buflen);
+ return vrrp_send_pkt(vrrp, buf, buflen);
}
/* Gratuitous ARP on each VIP */
-void vrrp_send_gratuitous_arp(vrrp_instance *vrrp_instance)
+void vrrp_send_gratuitous_arp(vrrp_rt *vrrp)
{
int i, j;
- vrrp_rt *vsrv = vrrp_instance->vsrv;
/* send gratuitous arp for each virtual ip */
for (j = 0; j < 5; j++)
- for (i = 0; i < vsrv->naddr; i++)
- send_gratuitous_arp(vsrv, vsrv->vaddr[i].addr);
+ for (i = 0; i < vrrp->naddr; i++)
+ send_gratuitous_arp(vrrp, ntohl(vrrp->vaddr[i].addr));
}
/* becoming master */
-void vrrp_state_goto_master(vrrp_instance *vrrp_instance)
+void vrrp_state_goto_master(vrrp_rt *vrrp)
{
- vrrp_rt *vsrv = vrrp_instance->vsrv;
-
/* add the ip addresses */
- vrrp_handle_ipaddress(vsrv, VRRP_IPADDRESS_ADD);
+ vrrp_handle_ipaddress(vrrp, VRRP_IPADDRESS_ADD);
/* send an advertisement */
- vrrp_send_adv(vsrv, vsrv->priority);
+ vrrp_send_adv(vrrp, vrrp->priority);
/* remotes arp tables update */
- vrrp_send_gratuitous_arp(vrrp_instance);
-
- syslog(LOG_INFO, "VRRP_Instance(%s) Entering MASTER STATE"
- , vrrp_instance->iname);
-
- if (vsrv->notify_exec) {
- notify_exec(vsrv, "master");
- if (vsrv->debug > 0)
+ syslog(LOG_INFO, "Sending gratuitous ARP on %s"
+ , IF_NAME(vrrp->ifp));
+ vrrp_send_gratuitous_arp(vrrp);
+
+ /* Check if notify is needed */
+ if (vrrp->notify_exec) {
+ notify_exec(vrrp, "master");
+ if (vrrp->debug > 0)
syslog(LOG_INFO, "notify:%s, flg:%d"
- , vsrv->notify_file
- , vsrv->notify_exec);
+ , vrrp->notify_file
+ , vrrp->notify_exec);
}
- vsrv->state = VRRP_STATE_MAST;
+ /* Check if sync daemon handling is needed */
+ if (vrrp->lvs_syncd_if)
+ thread_add_timer(master, ipvs_syncd_master_thread
+ , vrrp->lvs_syncd_if
+ , IPVS_CMD_DELAY);
+
+ if (vrrp->wantstate == VRRP_STATE_MAST) {
+ vrrp->state = VRRP_STATE_MAST;
+ syslog(LOG_INFO, "VRRP_Instance(%s) Entering MASTER STATE"
+ , vrrp->iname);
+ } else {
+ vrrp->state = VRRP_STATE_DUMMY_MAST;
+ syslog(LOG_INFO, "VRRP_Instance(%s) Entering DUMMY_MASTER STATE"
+ , vrrp->iname);
+ }
}
/* leaving master state */
-static void vrrp_restore_interface(vrrp_rt *vsrv, int advF)
+static void vrrp_restore_interface(vrrp_rt *vrrp, int advF)
{
/* remove the ip addresses */
- vrrp_handle_ipaddress(vsrv, VRRP_IPADDRESS_DEL);
+ vrrp_handle_ipaddress(vrrp, VRRP_IPADDRESS_DEL);
/* if we stop vrrp, warn the other routers to speed up the recovery */
if (advF)
- vrrp_send_adv(vsrv, VRRP_PRIO_STOP);
+ vrrp_send_adv(vrrp, VRRP_PRIO_STOP);
}
-void vrrp_state_leave_master(vrrp_instance *instance)
+void vrrp_state_leave_master(vrrp_rt *vrrp)
{
- vrrp_rt *vsrv = instance->vsrv;
-
/* Remove VIPs */
- vrrp_restore_interface(vsrv, 0);
-
- syslog(LOG_INFO, "VRRP_Instance(%s) Entering BACKUP STATE"
- , instance->iname);
-
- if (vsrv->notify_exec) {
- notify_exec(vsrv, "backup");
- if (vsrv->debug > 0)
+ vrrp_restore_interface(vrrp, 0);
+
+ if (vrrp->wantstate == VRRP_STATE_BACK)
+ syslog(LOG_INFO, "VRRP_Instance(%s) Entering BACKUP STATE"
+ , vrrp->iname);
+ if (vrrp->wantstate == VRRP_STATE_GOTO_FAULT)
+ syslog(LOG_INFO, "VRRP_Instance(%s) Entering FAULT STATE"
+ , vrrp->iname);
+
+ /* Check if notify is needed */
+ if (vrrp->notify_exec) {
+ if (vrrp->wantstate == VRRP_STATE_BACK)
+ notify_exec(vrrp, "backup");
+ if (vrrp->wantstate == VRRP_STATE_GOTO_FAULT)
+ notify_exec(vrrp, "fault");
+ if (vrrp->debug > 0)
syslog(LOG_INFO, "notify:%s, flg:%d"
- , vsrv->notify_file
- , vsrv->notify_exec);
+ , vrrp->notify_file
+ , vrrp->notify_exec);
}
- /* register the vrrp backup handler */
- vsrv->state = VRRP_STATE_BACK;
+ /* Check if sync daemon handling is needed */
+ if (vrrp->lvs_syncd_if)
+ thread_add_timer(master, ipvs_syncd_backup_thread
+ , vrrp->lvs_syncd_if
+ , IPVS_CMD_DELAY);
+
+ /* set the new vrrp state */
+ switch (vrrp->wantstate) {
+ case VRRP_STATE_BACK:
+ vrrp->state = vrrp->wantstate;
+ break;
+ case VRRP_STATE_GOTO_FAULT:
+ vrrp->state = VRRP_STATE_FAULT;
+ break;
+ }
}
/* BACKUP state processing */
-void vrrp_state_backup(vrrp_instance *instance, char *buf, int buflen)
+void vrrp_state_backup(vrrp_rt *vrrp, char *buf, int buflen)
{
int ret = 0;
- vrrp_rt *vsrv = instance->vsrv;
struct iphdr *iph = (struct iphdr *)buf;
vrrp_pkt *hd = NULL;
}
/* Process the incoming packet */
- ret = vrrp_check_packet(vsrv, buf, buflen);
+ ret = vrrp_check_packet(vrrp, buf, buflen);
if (ret == VRRP_PACKET_KO ||
ret == VRRP_PACKET_NULL) {
syslog(LOG_INFO, "VRRP_Instance(%s) ignoring received advertisment..."
- , instance->iname);
- vsrv->ms_down_timer = 3 * vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);
+ , vrrp->iname);
+ vrrp->ms_down_timer = 3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
} else if (hd->priority == 0) {
- vsrv->ms_down_timer = VRRP_TIMER_SKEW(vsrv);
- } else if( !vsrv->preempt || hd->priority >= vsrv->priority ) {
- vsrv->ms_down_timer = 3 * vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);
+ vrrp->ms_down_timer = VRRP_TIMER_SKEW(vrrp);
+ } else if( !vrrp->preempt || hd->priority >= vrrp->priority ) {
+ vrrp->ms_down_timer = 3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
}
}
/* MASTER state processing */
-void vrrp_state_master_tx(vrrp_instance *instance, const int prio)
+void vrrp_state_master_tx(vrrp_rt *vrrp, const int prio)
{
- vrrp_rt *vsrv = instance->vsrv;
-
if (prio == VRRP_PRIO_OWNER)
- vrrp_send_adv(vsrv, VRRP_PRIO_OWNER);
+ vrrp_send_adv(vrrp, VRRP_PRIO_OWNER);
else
- vrrp_send_adv(vsrv, vsrv->priority);
+ vrrp_send_adv(vrrp, vrrp->priority);
}
-int vrrp_state_master_rx(vrrp_instance *instance, char *buf, int buflen)
+int vrrp_state_master_rx(vrrp_rt *vrrp, char *buf, int buflen)
{
int ret = 0;
- vrrp_rt *vsrv = instance->vsrv;
struct iphdr *iph = (struct iphdr *)buf;
vrrp_pkt *hd = NULL;
+ /* return on link failure */
+ if (vrrp->wantstate == VRRP_STATE_GOTO_FAULT) {
+ vrrp->ms_down_timer = 3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
+ vrrp->state = VRRP_STATE_FAULT;
+ return 1;
+ }
+
/* Fill the VRRP header */
switch (iph->protocol) {
case IPPROTO_IPSEC_AH:
}
/* Process the incoming packet */
- ret = vrrp_check_packet(vsrv, buf, buflen);
+ ret = vrrp_check_packet(vrrp, buf, buflen);
if (ret == VRRP_PACKET_KO ||
ret == VRRP_PACKET_NULL ||
ret == VRRP_PACKET_DROP) {
syslog(LOG_INFO, "VRRP_Instance(%s) Dropping received VRRP packet..."
- , instance->iname);
- vrrp_send_adv(vsrv, vsrv->priority);
+ , vrrp->iname);
+ vrrp_send_adv(vrrp, vrrp->priority);
return 0;
} else if (hd->priority == 0) {
- vrrp_send_adv(vsrv, vsrv->priority);
+ vrrp_send_adv(vrrp, vrrp->priority);
return 0;
- } else if( hd->priority > vsrv->priority ||
- (hd->priority == vsrv->priority &&
- ntohl(iph->saddr) > vsrv->vif->ipaddr)) {
- vsrv->ms_down_timer = 3 * vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);
- vsrv->state = VRRP_STATE_BACK;
+ } else if (hd->priority > vrrp->priority ||
+ (hd->priority == vrrp->priority &&
+ ntohl(iph->saddr) > IF_ADDR(vrrp->ifp))) {
+ syslog(LOG_INFO, "VRRP_Instance(%s) Received higher prio advert"
+ , vrrp->iname);
+ syslog(LOG_INFO, "VRRP_Instance(%s) Entering BACKUP state"
+ , vrrp->iname);
+ vrrp->ms_down_timer = 3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
+ vrrp->state = VRRP_STATE_BACK;
return 1;
}
return 0;
}
+int vrrp_state_fault_rx(vrrp_rt *vrrp, char *buf, int buflen)
+{
+ int ret = 0;
+ struct iphdr *iph = (struct iphdr *)buf;
+ vrrp_pkt *hd = NULL;
+
+ /* Fill the VRRP header */
+ switch (iph->protocol) {
+ case IPPROTO_IPSEC_AH:
+ hd = (vrrp_pkt *)((char *)iph + (iph->ihl<<2) + vrrp_ipsecah_len());
+ break;
+ case IPPROTO_VRRP:
+ hd = (vrrp_pkt *)((char *)iph + (iph->ihl<<2));
+ break;
+ }
+
+ /* Process the incoming packet */
+ ret = vrrp_check_packet(vrrp, buf, buflen);
+
+ if (ret == VRRP_PACKET_KO ||
+ ret == VRRP_PACKET_NULL ||
+ ret == VRRP_PACKET_DROP) {
+ syslog(LOG_INFO, "VRRP_Instance(%s) Dropping received VRRP packet..."
+ , vrrp->iname);
+ vrrp_send_adv(vrrp, vrrp->priority);
+ return 0;
+ } else if (vrrp->priority > hd->priority ||
+ hd->priority == VRRP_PRIO_OWNER)
+ return 1;
+
+printf("Local prio: %d, remote prio: %d\n", vrrp->priority, hd->priority);
+
+ return 0;
+}
+
/* check for minimum configuration requirements */
-static int chk_min_cfg(vrrp_rt *vsrv)
+static int chk_min_cfg(vrrp_rt *vrrp)
{
- if( vsrv->naddr == 0 ){
+ if (vrrp->naddr == 0) {
syslog(LOG_INFO, "provide at least one ip for the virtual server");
return 0;
}
- if( vsrv->vrid == 0 ){
+ if (vrrp->vrid == 0) {
syslog(LOG_INFO, "the virtual id must be set!");
return 0;
}
- if( vsrv->vif->ipaddr == 0 ){
+ if (!IF_ADDR(vrrp->ifp)) {
syslog(LOG_INFO, "the interface ipaddr must be set!");
return 0;
}
int open_vrrp_socket(const int proto, const int index)
{
struct ip_mreqn req_add;
- char ifname[IFNAMSIZ];
+ interface *ifp;
int fd;
int ret;
+ int retry_num = 0;
+
+ /* Retreive interface */
+ ifp = if_get_by_ifindex(index);
+
+ if (!IF_ISUP(ifp)) {
+ syslog(LOG_INFO, "Kernel is reporting: Interface %s is DOWN"
+ , IF_NAME(ifp));
+ return -1;
+ }
/* open the socket */
fd = socket(AF_INET, SOCK_RAW, proto);
* Needed for filter multicasted advert per interface.
*
* -- If you read this !!! and know the answer to the question
- * please feal free to answer me ! :)
+ * please feel free to answer me ! :)
*/
- memset(ifname, 0, IFNAMSIZ);
- index_to_ifname(index, ifname);
- ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
- ifname, strlen(ifname)+1);
+ ret = setsockopt(fd, SOL_SOCKET
+ , SO_BINDTODEVICE
+ , IF_NAME(ifp)
+ , strlen(IF_NAME(ifp))+1);
if (ret < 0) {
int err = errno;
- syslog(LOG_INFO, "cant bind to device %s. errno=%d. (try to run it as root)",
- ifname, err);
- close(fd); /* sd leak handle */
+ syslog(LOG_INFO, "cant bind to device %s. errno=%d. (try to run it as root)"
+ , IF_NAME(ifp)
+ , err);
+ close(fd);
return -1;
}
*/
memset(&req_add, 0, sizeof (req_add));
req_add.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);
- req_add.imr_address.s_addr = htonl(index_to_ip(index));
- req_add.imr_ifindex = index;
- ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (char *)&req_add, sizeof(struct ip_mreqn));
+ req_add.imr_address.s_addr = IF_ADDR(ifp);
+ req_add.imr_ifindex = IF_INDEX(ifp);
+
+ /* -> Need to handle multicast convergance after takeover.
+ * We retry until multicast is available on the interface.
+ * After VRRP_MCAST_RETRY we assume interface doesn't support
+ * multicast then exist with error.
+ * -> This can sound a little nasty since it degrade a little
+ * the global scheduling timers.
+ */
+moretry:
+ ret = setsockopt(fd, IPPROTO_IP
+ , IP_ADD_MEMBERSHIP
+ , (char *)&req_add
+ , sizeof(struct ip_mreqn));
if (ret < 0) {
- int err = errno;
- syslog(LOG_INFO, "cant do IP_ADD_MEMBERSHIP errno=%d", err);
+ syslog(LOG_INFO, "cant do IP_ADD_MEMBERSHIP errno=%s (%d)"
+ , strerror(errno)
+ , errno);
+ if (errno == 19) {
+ retry_num++;
+ if (retry_num > VRRP_MCAST_RETRY) {
+ syslog(LOG_INFO, "cant do IP_ADD_MEMBERSHIP after %d retry errno=%s"
+ , VRRP_MCAST_RETRY
+ , strerror(errno));
+ return -1;
+ }
+ sleep(1); /* FIXME: Beurk... Very nasty... !!! */
+ goto moretry;
+ }
return -1;
}
return fd;
}
+void close_vrrp_socket(vrrp_rt *vrrp)
+{
+ struct ip_mreqn req_add;
+ int ret = 0;
-extern data *conf_data;
+ /* Leaving the VRRP multicast group */
+ memset(&req_add, 0, sizeof (req_add));
+ req_add.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);
+ req_add.imr_address.s_addr = IF_ADDR(vrrp->ifp);
+ req_add.imr_ifindex = IF_INDEX(vrrp->ifp);
+ ret = setsockopt(vrrp->fd, IPPROTO_IP
+ , IP_DROP_MEMBERSHIP
+ , (char *)&req_add
+ , sizeof(struct ip_mreqn));
+ if (ret < 0) {
+ syslog(LOG_INFO, "cant do IP_DROP_MEMBERSHIP errno=%s (%d)"
+ , strerror(errno)
+ , errno);
+ return;
+ }
+
+ /* Finally close the desc */
+ close(vrrp->fd);
+}
+
+void new_vrrp_socket(vrrp_rt *vrrp)
+{
+ int old_fd = vrrp->fd;
+ list p = conf_data->vrrp;
+ vrrp_rt *vrrp_ptr;
+ element e;
+
+ /* close the desc & open a new one */
+ close_vrrp_socket(vrrp);
+ if (vrrp->auth_type == VRRP_AUTH_AH)
+ vrrp->fd = open_vrrp_socket(IPPROTO_IPSEC_AH, IF_INDEX(vrrp->ifp));
+ else
+ vrrp->fd = open_vrrp_socket(IPPROTO_VRRP, IF_INDEX(vrrp->ifp));
+
+ /* Sync the other desc */
+ for (e = LIST_HEAD(p); e; ELEMENT_NEXT(e)) {
+ vrrp_ptr = ELEMENT_DATA(e);
+ if (vrrp_ptr->fd == old_fd)
+ vrrp_ptr->fd = vrrp->fd;
+ }
+}
/* handle terminate state */
void shutdown_vrrp_instances(void)
{
list l = conf_data->vrrp;
element e;
- vrrp_instance *vrrp;
+ vrrp_rt *vrrp;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
vrrp = ELEMENT_DATA(e);
/* remove VIPs */
- if (vrrp->vsrv->state == VRRP_STATE_MAST)
- vrrp_restore_interface(vrrp->vsrv, 1);
+ if (vrrp->state == VRRP_STATE_MAST ||
+ vrrp->state == VRRP_STATE_DUMMY_MAST)
+ vrrp_restore_interface(vrrp, 1);
+
+ /* Stop stalled syncd */
+ if (vrrp->lvs_syncd_if)
+ ipvs_syncd_cmd(IPVS_STOPDAEMON, NULL, 0);
}
}
/* complete vrrp structure */
-static int vrrp_complete_instance(vrrp_rt *vsrv)
+static int vrrp_complete_instance(vrrp_rt *vrrp)
{
- vrrp_if *vif = vsrv->vif;
-
/* complete the VMAC address */
- vsrv->hwaddr[0] = 0x00;
- vsrv->hwaddr[1] = 0x00;
- vsrv->hwaddr[2] = 0x5E;
- vsrv->hwaddr[3] = 0x00;
- vsrv->hwaddr[4] = 0x01;
- vsrv->hwaddr[5] = vsrv->vrid;
-
- /* get the ip address */
- vif->ipaddr = ifname_to_ip(vif->ifname);
- if (!vif->ipaddr) {
- syslog(LOG_INFO, "VRRP Error : no interface found : %s !\n", vif->ifname);
- return 0;
- }
- /* get the hwaddr */
- if (hwaddr_get(vif->ifname, vif->hwaddr, sizeof(vif->hwaddr))) {
- syslog(LOG_INFO, "VRRP Error : Unreadable MAC"
- "address for interface : %s !\n", vif->ifname);
- return 0;
- }
-
- vsrv->state = VRRP_STATE_INIT;
- if (!vsrv->adver_int) vsrv->adver_int = VRRP_ADVER_DFL * TIMER_HZ;
- if (!vsrv->priority) vsrv->priority = VRRP_PRIO_DFL;
- if (!vsrv->preempt) vsrv->preempt = VRRP_PREEMPT_DFL;
-
- return(chk_min_cfg(vsrv));
+ vrrp->hwaddr[0] = 0x00;
+ vrrp->hwaddr[1] = 0x00;
+ vrrp->hwaddr[2] = 0x5E;
+ vrrp->hwaddr[3] = 0x00;
+ vrrp->hwaddr[4] = 0x01;
+ vrrp->hwaddr[5] = vrrp->vrid;
+
+ vrrp->state = VRRP_STATE_INIT;
+ if (!vrrp->adver_int) vrrp->adver_int = VRRP_ADVER_DFL * TIMER_HZ;
+ if (!vrrp->priority) vrrp->priority = VRRP_PRIO_DFL;
+ if (!vrrp->preempt) vrrp->preempt = VRRP_PREEMPT_DFL;
+
+ return(chk_min_cfg(vrrp));
}
void vrrp_complete_init(void)
{
list l = conf_data->vrrp;
element e;
- vrrp_instance *vrrp;
+ vrrp_rt *vrrp;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
vrrp = ELEMENT_DATA(e);
- vrrp_complete_instance(vrrp->vsrv);
+ vrrp_complete_instance(vrrp);
}
}
*
* Part: vrrp.c program include file.
*
- * Version: $Id: vrrp.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: vrrp.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
* Based on the Jerome Etienne, <jetienne@arobas.net> code.
/* local include */
#include "vrrp_ipaddress.h"
#include "vrrp_ipsecah.h"
+#include "vrrp_if.h"
#include "timer.h"
#include "utils.h"
-
/* Default dir to notify file */
#define VRRP_NOTIFY_DFL "/etc/init.d"
#define VRRP_ADVER_DFL 1 /* advert. interval (in sec) -- rfc2338.5.3.7 */
#define VRRP_PREEMPT_DFL 1 /* rfc2338.6.1.2.Preempt_Mode */
-/* parameters per interface -- rfc2338.6.1.1 */
typedef struct {
- int auth_type; /* authentification type. VRRP_AUTH_* */
- uint8_t auth_data[8]; /* authentification data */
-
- uint32_t ipaddr; /* the address of the interface */
- char hwaddr[6]; /* hardcoded for ethernet */
- char *ifname; /* the device name for this ipaddr */
- /*
- * To have my own ip_id creates collision with kernel ip->id
- * but it should be ok because the packets are unlikely to be
- * fragmented (they are non routable and small)
- * This packet isnt routed, i can check the outgoing MTU
- * to warn the user only if the outoing mtu is too small
- */
- int ip_id;
-} vrrp_if;
-
-typedef struct {
- uint32_t addr; /* the ip address */
- int deletable; /* TRUE if one of my primary addr */
+ uint32_t addr; /* the ip address */
+ int set; /* TRUE if addr is set */
} vip_addr;
/* parameters per virtual router -- rfc2338.6.1.2 */
-typedef struct {
+typedef struct _vrrp_rt {
+ char *iname; /* Instance Name */
+ char *isync; /* Instance Name to be sync with */
+ interface *ifp; /* Interface we belong to */
+ char *lvs_syncd_if; /* handle LVS sync daemon state using this
+ * instance FSM & running on specific interface
+ * => eth0 for example.
+ */
+
int vrid; /* virtual id. from 1(!) to 255 */
int priority; /* priority value */
int naddr; /* number of ip addresses */
int wantstate; /* user explicitly wants a state (back/mast) */
int fd; /* the socket descriptor */
- int debug; /* Debug level 0-4 */
- int notify_exec;
- char notify_file[FILENAME_MAX];
+ int debug; /* Debug level 0-4 */
+ int notify_exec;
+ char notify_file[FILENAME_MAX];
/* rfc2336.6.2 */
uint32_t ms_down_timer;
struct timeval sands;
+ /* Authentication data */
+ int auth_type; /* authentification type. VRRP_AUTH_* */
+ uint8_t auth_data[8]; /* authentification data */
+
+ /*
+ * To have my own ip_id creates collision with kernel ip->id
+ * but it should be ok because the packets are unlikely to be
+ * fragmented (they are non routable and small)
+ * This packet isnt routed, i can check the outgoing MTU
+ * to warn the user only if the outoing mtu is too small
+ */
+ int ip_id;
+
/* IPSEC AH counter def --rfc2402.3.3.2 */
seq_counter *ipsecah_counter;
-
- /* interface parameters */
- vrrp_if *vif;
} vrrp_rt;
/* VRRP state machine -- rfc2338.6.4 */
-#define VRRP_DISPATCHER 0 /* internal */
-#define VRRP_STATE_INIT 1 /* rfc2338.6.4.1 */
-#define VRRP_STATE_BACK 2 /* rfc2338.6.4.2 */
-#define VRRP_STATE_MAST 3 /* rfc2338.6.4.3 */
-#define VRRP_STATE_GOTO_MASTER 4 /* internal */
-#define VRRP_STATE_LEAVE_MASTER 5 /* internal */
-#define VRRP_STATE_FAULT 99 /* internal */
+#define VRRP_DISPATCHER 0 /* internal */
+#define VRRP_STATE_INIT 1 /* rfc2338.6.4.1 */
+#define VRRP_STATE_BACK 2 /* rfc2338.6.4.2 */
+#define VRRP_STATE_MAST 3 /* rfc2338.6.4.3 */
+#define VRRP_STATE_GOTO_MASTER 4 /* internal */
+#define VRRP_STATE_LEAVE_MASTER 5 /* internal */
+#define VRRP_STATE_GOTO_DUMMY_MAST 96 /* internal */
+#define VRRP_STATE_DUMMY_MAST 97 /* internal */
+#define VRRP_STATE_GOTO_FAULT 98 /* internal */
+#define VRRP_STATE_FAULT 99 /* internal */
+#define VRRP_MCAST_RETRY 10 /* internal */
/* VRRP packet handling */
#define VRRP_PACKET_OK 0
#define VRRP_MAX(a, b) ((a) > (b)?(a):(b))
/* prototypes */
+extern int open_vrrp_socket(const int proto, const int index);
+extern void new_vrrp_socket(vrrp_rt *vrrp);
+extern void close_vrrp_socket(vrrp_rt *vrrp);
+extern void vrrp_send_gratuitous_arp(vrrp_rt *vrrp);
+extern int vrrp_state_fault_rx(vrrp_rt *vrrp, char *buf, int buflen);
+extern int vrrp_state_master_rx(vrrp_rt *vrrp, char *buf, int buflen);
+extern void vrrp_state_master_tx(vrrp_rt *vrrp, const int prio);
+extern void vrrp_state_backup(vrrp_rt *vrrp, char *buf, int buflen);
+extern void vrrp_state_goto_master(vrrp_rt *vrrp);
+extern void vrrp_state_leave_master(vrrp_rt *vrrp);
extern int vrrp_ipsecah_len(void);
extern void vrrp_complete_init(void);
extern void shutdown_vrrp_instances(void);
--- /dev/null
+/*
+ * Soft: Keepalived is a failover program for the LVS project
+ * <www.linuxvirtualserver.org>. It monitor & manipulate
+ * a loadbalanced server pool using multi-layer checks.
+ *
+ * Part: Interfaces manipulation.
+ *
+ * Version: $Id: vrrp_if.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
+ *
+ * Author: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program 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.
+ *
+ * This program 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 of the License, or (at your option) any later version.
+ */
+
+/* global include */
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/ip.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <ctype.h>
+#ifdef use_linux_libc5
+ #include <linux/if_arp.h>
+ #include <linux/if_ether.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+
+/* local include */
+#include "scheduler.h"
+#include "data.h"
+#include "vrrp_if.h"
+#include "vrrp_netlink.h"
+#include "memory.h"
+#include "utils.h"
+
+/* Global vars */
+extern thread_master *master;
+extern data *conf_data;
+static struct ifreq ifr;
+
+/* Helper functions */
+/* Return interface from interface index */
+interface *if_get_by_ifindex(const int ifindex)
+{
+ interface *ifp;
+ element e;
+
+ for (e = LIST_HEAD(if_queue); e; ELEMENT_NEXT(e)) {
+ ifp = ELEMENT_DATA(e);
+ if (ifp->ifindex == ifindex)
+ return ifp;
+ }
+ return NULL;
+}
+
+interface *if_get_by_ifname(const char *ifname)
+{
+ interface *ifp;
+ element e;
+
+ for (e = LIST_HEAD(if_queue); e; ELEMENT_NEXT(e)) {
+ ifp = ELEMENT_DATA(e);
+ if (!strcmp(ifp->ifname, ifname))
+ return ifp;
+ }
+ return NULL;
+}
+
+/* MII Transceiver Registers poller functions */
+static int if_mii_read(const int fd, const int phy_id, int location)
+{
+ uint16_t *data = (uint16_t *)(&ifr.ifr_data);
+
+ data[0] = phy_id;
+ data[1] = location;
+
+ if (ioctl(fd, SIOCGMIIREG, &ifr) < 0) {
+ syslog(LOG_ERR, "SIOCGMIIREG on %s failed: %s"
+ , ifr.ifr_name
+ , strerror(errno));
+ return -1;
+ }
+ return data[3];
+}
+
+/*
+static void if_mii_dump(const uint16_t mii_regs[32], unsigned phy_id)
+{
+ int mii_reg;
+
+ printf(" MII PHY #%d transceiver registers:\n", phy_id);
+ for (mii_reg = 0; mii_reg < 32; mii_reg++)
+ printf("%s %4.4x", (mii_reg % 8) == 0 ? "\n ":"", mii_regs[mii_reg]);
+}
+*/
+
+static int if_mii_status(const int fd)
+{
+ uint16_t *data = (uint16_t *)(&ifr.ifr_data);
+ unsigned phy_id = data[0];
+ uint16_t mii_regs[32];
+ int mii_reg;
+ uint16_t bmsr, new_bmsr;
+
+ /* Reset MII registers */
+ memset(mii_regs, 0, sizeof(mii_regs));
+
+ for (mii_reg = 0; mii_reg < 32; mii_reg++)
+ mii_regs[mii_reg] = if_mii_read(fd, phy_id, mii_reg);
+
+// if_mii_dump(mii_regs, phy_id);
+
+ if (mii_regs[0] == 0xffff) {
+ syslog(LOG_ERR, "No MII transceiver present for %s !!!"
+ , ifr.ifr_name);
+ return -1;
+ }
+
+ bmsr = mii_regs[1];
+
+ /*
+ * For Basic Mode Status Register (BMSR).
+ * Sticky field (Link established & Jabber detected), we need to read
+ * a second time the BMSR to get current status.
+ */
+ new_bmsr = if_mii_read(fd, phy_id, 1);
+
+// printf(" \nBasic Mode Status Register 0x%4.4x ... 0x%4.4x\n", bmsr, new_bmsr);
+
+ if (bmsr & 0x0004)
+ return LINK_UP;
+ else if (new_bmsr & 0x0004)
+ return LINK_UP;
+ else
+ return LINK_DOWN;
+}
+
+int if_mii_probe(const char *ifname)
+{
+ int fd = socket(AF_INET, SOCK_DGRAM, 0);
+ int status = 0;
+
+ if (fd < 0) return -1;
+ memset(&ifr, 0, sizeof(struct ifreq));
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGMIIPHY, &ifr) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ /* Dump the MII transceiver */
+ status = if_mii_status(fd);
+ close(fd);
+ return status;
+}
+
+/* Interfaces lookup */
+static void free_if(void *data)
+{
+ FREE(data);
+}
+void dump_if(void *data)
+{
+ interface *ifp = data;
+
+ syslog(LOG_INFO, "------< NIC >------");
+ syslog(LOG_INFO, " Name = %s", ifp->ifname);
+ syslog(LOG_INFO, " index = %d", ifp->ifindex);
+ syslog(LOG_INFO, " address = %s", ip_ntoa(ifp->address));
+
+ /* FIXME: Harcoded for ethernet */
+ if (ifp->hw_type == ARPHRD_ETHER)
+ syslog(LOG_INFO, " MAC = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x"
+ , ifp->hw_addr[0], ifp->hw_addr[1], ifp->hw_addr[2]
+ , ifp->hw_addr[3], ifp->hw_addr[4], ifp->hw_addr[5]);
+
+ if (ifp->flags & IFF_UP)
+ syslog(LOG_INFO, " is UP");
+
+ if (ifp->flags & IFF_RUNNING)
+ syslog(LOG_INFO, " is RUNNING");
+
+ if (!(ifp->flags & IFF_UP) && !(ifp->flags & IFF_RUNNING))
+ syslog(LOG_INFO, " is DOWN");
+
+ syslog(LOG_INFO, " MTU = %d", ifp->mtu);
+
+ switch (ifp->hw_type) {
+ case ARPHRD_LOOPBACK:
+ syslog(LOG_INFO, " HW Type = LOOPBACK");
+ break;
+ case ARPHRD_ETHER:
+ syslog(LOG_INFO, " HW Type = ETHERNET");
+ break;
+ default:
+ syslog(LOG_INFO, " HW Type = UNKNOWN");
+ break;
+ }
+
+ /* MII registers supported ? */
+ if (IF_MII_SUPPORTED(ifp))
+ syslog(LOG_INFO, " NIC support MII regs");
+}
+
+static void init_if_queue(void)
+{
+ if_queue = alloc_list(free_if, dump_if);
+}
+void if_add_queue(interface *ifp)
+{
+ list_add(if_queue, ifp);
+}
+
+static void init_if_mii(void)
+{
+ interface *ifp;
+ element e;
+ int status;
+
+ for (e = LIST_HEAD(if_queue); e; ELEMENT_NEXT(e)) {
+ ifp = ELEMENT_DATA(e);
+ status = if_mii_probe(ifp->ifname);
+ if (status < 0)
+ ifp->mii = 0;
+ else {
+ ifp->mii = 1;
+ ifp->mii_linkbeat = (status)?1:0;
+ }
+ }
+}
+
+static void if_mii_refresh(void)
+{
+ interface *ifp;
+ element e;
+
+ for (e = LIST_HEAD(if_queue); e; ELEMENT_NEXT(e)) {
+ ifp = ELEMENT_DATA(e);
+ if (IF_MII_SUPPORTED(ifp)) {
+ if (IF_LINK_ISUP(ifp->ifname))
+ ifp->mii_linkbeat = 1;
+ else
+ ifp->mii_linkbeat = 0;
+ }
+ }
+}
+
+int if_mii_linkbeat(const interface *ifp)
+{
+ if (IF_MII_SUPPORTED(ifp))
+ return IF_MII_LINKBEAT(ifp);
+ return 1;
+}
+
+/* Our interface Heartbeat thread */
+int if_monitor_thread(thread *thread)
+{
+ /* If present, refresh link beat status from MII BMSR */
+ if_mii_refresh();
+
+ /* Register new monitor thread */
+ thread_add_timer(master, if_monitor_thread
+ , NULL
+ , POLLING_DELAY);
+ return 0;
+}
+
+/* Interface queue helpers*/
+void free_interface_queue(void)
+{
+ if (!LIST_ISEMPTY(if_queue))
+ free_list(if_queue);
+}
+void init_interface_queue(void)
+{
+ init_if_queue();
+ netlink_interface_lookup();
+ init_if_mii();
+ kernel_netlink_init();
+// dump_list(if_queue);
+
+ /* Register NIC Heartbeat monitoring thread */
+ thread_add_timer(master, if_monitor_thread
+ , NULL
+ , POLLING_DELAY);
+}
--- /dev/null
+/*
+ * Soft: Keepalived is a failover program for the LVS project
+ * <www.linuxvirtualserver.org>. It monitor & manipulate
+ * a loadbalanced server pool using multi-layer checks.
+ *
+ * Part: vrrp_if.c include file.
+ *
+ * Version: $Id: vrrp_if.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
+ *
+ * Author: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program 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.
+ *
+ * This program 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 of the License, or (at your option) any later version.
+ */
+
+#ifndef _VRRP_IF_H
+#define _VRRP_IF_H
+
+/* global includes */
+#include <net/if.h>
+
+/* local includes */
+#include "scheduler.h"
+#include "list.h"
+
+/* types definition */
+#ifndef SIOCGMIIPHY
+ #define SIOCGMIIPHY (SIOCDEVPRIVATE) /* Get the PHY in use. */
+ #define SIOCGMIIREG (SIOCDEVPRIVATE+1) /* Read a PHY register. */
+ #define SIOCSMIIREG (SIOCDEVPRIVATE+2) /* Write a PHY register. */
+ #define SIOCGPARAMS (SIOCDEVPRIVATE+3) /* Read operational parameters. */
+ #define SIOCSPARAMS (SIOCDEVPRIVATE+4) /* Set operational parameters. */
+#endif
+#define LINK_UP 1
+#define LINK_DOWN 0
+#define IF_NAMESIZ 20 /* Max interface lenght size */
+#define IF_HWADDR_MAX 20 /* Max MAC address length size */
+#define ARPHRD_ETHER 1
+#define ARPHRD_LOOPBACK 772
+#define POLLING_DELAY 1
+
+/* Interface structure definition */
+typedef struct _interface {
+ char ifname[IF_NAMESIZ + 1]; /* Interface name */
+ unsigned int ifindex; /* Interface index */
+ uint32_t address; /* Interface main primary IP address */
+// list primary;
+// list secondary;
+ unsigned long flags; /* flags */
+ unsigned int mtu; /* MTU for this interface */
+ unsigned short hw_type; /* Type of hardware address */
+ u_char hw_addr[IF_HWADDR_MAX]; /* MAC address */
+ int hw_addr_len; /* MAC addresss length */
+ int mii; /* Interface support MII regs ? */
+ int mii_linkbeat; /* LinkBeat from MII BMSR req */
+} interface;
+
+/* Global interface queue */
+list if_queue;
+
+/* Macros */
+#define IF_NAME(X) ((X)->ifname)
+#define IF_INDEX(X) ((X)->ifindex)
+#define IF_ADDR(X) ((X)->address)
+#define IF_HWADDR(X) ((X)->hw_addr)
+#define IF_LINK_ISUP(X) (if_mii_probe(X))
+#define IF_MII_SUPPORTED(X) ((X)->mii)
+#define IF_MII_LINKBEAT(X) ((X)->mii_linkbeat)
+#define IF_ISUP(X) (((X)->flags & IFF_UP) && \
+ ((X)->flags & IFF_RUNNING) && \
+ if_mii_linkbeat(X))
+
+/* prototypes */
+extern interface *if_get_by_ifindex(const int ifindex);
+extern interface *if_get_by_ifname(const char *ifname);
+extern int if_mii_linkbeat(const interface *ifp);
+extern int if_mii_probe(const char *ifname);
+extern void if_add_queue(interface *ifp);
+extern int if_monitor_thread(thread *thread);
+extern void init_interface_queue(void);
+extern void free_interface_queue(void);
+extern void dump_if(void *data);
+
+#endif
*
* Part: NETLINK IPv4 address manipulation.
*
- * Version: $Id: vrrp_ipaddress.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: vrrp_ipaddress.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "vrrp_ipaddress.h"
#include "vrrp_netlink.h"
+/* Check if interface is UP */
+
+
+/* Add/Delete IP address to a specific interface */
int netlink_address_ipv4(int ifindex, uint32_t addr, int cmd)
{
struct nl_handle nlh;
+ int status = 1;
struct {
struct nlmsghdr n;
struct ifaddrmsg ifa;
return -1;
if (netlink_talk(&nlh, &req.n) < 0)
- return -1;
-
+ status = -1;
+
/* to close the clocket */
netlink_close(&nlh);
-
- return(0);
+ return status;
}
*
* Part: vrrp_ipaddress.c include file.
*
- * Version: $Id: vrrp_ipaddress.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: vrrp_ipaddress.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* authentication data encryption using HMAC MD5 according to
* RFCs 2085 & 2104.
*
- * Version: $Id: vrrp_ipsecah.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: vrrp_ipsecah.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include <openssl/md5.h>
/* hmac_md5 computation according to the RFCs 2085 & 2104 */
-void hmac_md5(unsigned char *buffer,int buffer_len,
- unsigned char *key,int key_len,unsigned char *digest)
+void hmac_md5(unsigned char *buffer, int buffer_len
+ , unsigned char *key
+ , int key_len
+ , unsigned char *digest)
{
MD5_CTX context;
unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */
*
* Part: vrrp_ipsecah.c include file.
*
- * Version: $Id: vrrp_ipsecah.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: vrrp_ipsecah.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: NETLINK kernel command channel.
*
- * Version: $Id: vrrp_netlink.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: vrrp_netlink.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* 2 of the License, or (at your option) any later version.
*/
-/* local include */
+/* global include */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/uio.h>
+/* local include */
#include "vrrp_netlink.h"
+#include "vrrp_if.h"
+#include "memory.h"
+#include "scheduler.h"
+#include "utils.h"
+
+/* Global vars */
+extern thread_master *master;
/* Create a socket to netlink interface */
int netlink_socket(struct nl_handle *nl, unsigned long groups)
return 0;
}
+static void parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len)
+{
+ while (RTA_OK(rta, len)) {
+ if (rta->rta_type <= max)
+ tb[rta->rta_type] = rta;
+ rta = RTA_NEXT(rta, len);
+ }
+}
+
/* Our netlink parser */
static int netlink_parse_info(int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
struct nl_handle *nl)
status = netlink_parse_info(netlink_talk_filter, nl);
return status;
}
+
+/* Fetch a specific type information from netlink kernel */
+static int netlink_request(struct nl_handle *nl, int family, int type)
+{
+ int status;
+ struct sockaddr_nl snl;
+ struct {
+ struct nlmsghdr nlh;
+ struct rtgenmsg g;
+ } req;
+
+ /* Cleanup the room */
+ memset(&snl, 0, sizeof(snl));
+ snl.nl_family = AF_NETLINK;
+
+ req.nlh.nlmsg_len = sizeof(req);
+ req.nlh.nlmsg_type = type;
+ req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
+ req.nlh.nlmsg_pid = 0;
+ req.nlh.nlmsg_seq = ++nl->seq;
+ req.g.rtgen_family = family;
+
+ status = sendto(nl->fd, (void *) &req
+ , sizeof(req)
+ , 0
+ , (struct sockaddr *) &snl
+ , sizeof(snl));
+ if (status < 0) {
+ syslog(LOG_INFO, "Netlink: sendto() failed: %s"
+ , strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+/* Netlink interface link lookup filter */
+static int netlink_if_link_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
+{
+ struct ifinfomsg *ifi;
+ struct rtattr *tb[IFLA_MAX + 1];
+ interface *ifp;
+ int i, len;
+ char *name;
+
+ ifi = NLMSG_DATA(h);
+
+ if (h->nlmsg_type != RTM_NEWLINK)
+ return 0;
+
+ len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ if (len < 0)
+ return -1;
+
+ /* Interface name lookup */
+ memset(tb, 0, sizeof(tb));
+ parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+ if (tb[IFLA_IFNAME] == NULL)
+ return -1;
+ name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
+
+ /* Return if loopback */
+ if (ifi->ifi_type == ARPHRD_LOOPBACK)
+ return 0;
+
+ /* Fill the interface structure */
+ ifp = (interface *)MALLOC(sizeof(interface));
+ memcpy(ifp->ifname, name, strlen(name));
+ ifp->ifindex = ifi->ifi_index;
+ ifp->flags = ifi->ifi_flags;
+ ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]);
+ ifp->hw_type = ifi->ifi_type;
+
+ if (tb[IFLA_ADDRESS]) {
+ int hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
+
+ if (hw_addr_len > IF_HWADDR_MAX)
+ syslog(LOG_ERR, "MAC address for %s is too large: %d"
+ , name
+ , hw_addr_len);
+ else {
+ ifp->hw_addr_len = hw_addr_len;
+ memcpy(ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]), hw_addr_len);
+ for (i = 0; i < hw_addr_len; i++)
+ if (ifp->hw_addr[i] != 0)
+ break;
+ if (i == hw_addr_len)
+ ifp->hw_addr_len = 0;
+ else
+ ifp->hw_addr_len = hw_addr_len;
+ }
+ }
+
+ /* Queue this new interface */
+ if_add_queue(ifp);
+ return 0;
+}
+
+/*
+ * Netlink interface address lookup filter
+ * We need to handle multiple primary address and
+ * multiple secondary address to the same interface.
+ */
+static int netlink_if_address_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
+{
+ struct ifaddrmsg *ifa;
+ struct rtattr *tb[IFA_MAX + 1];
+ interface *ifp;
+ int len;
+
+ ifa = NLMSG_DATA(h);
+
+ /* Only IPV4 are valid us */
+ if (ifa->ifa_family != AF_INET)
+ return 0;
+
+ if (h->nlmsg_type != RTM_NEWADDR &&
+ h->nlmsg_type != RTM_DELADDR)
+ return 0;
+
+ len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
+ if (len < 0)
+ return -1;
+
+ memset(tb, 0, sizeof(tb));
+ parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len);
+
+ /* Fetch interface */
+ ifp = if_get_by_ifindex(ifa->ifa_index);
+ if (!ifp)
+ return 0;
+
+ if (ifa->ifa_flags & IFA_F_SECONDARY)
+ return 0;
+
+ if (tb[IFA_ADDRESS] == NULL)
+ tb[IFA_ADDRESS] = tb[IFA_LOCAL];
+
+ if (ifp->flags & IFF_POINTOPOINT) {
+ if (tb[IFA_LOCAL]) {
+ ifp->address = *(uint32_t *)RTA_DATA(tb[IFA_LOCAL]);
+ } else {
+ if (tb[IFA_ADDRESS])
+ ifp->address = *(uint32_t *)RTA_DATA(tb[IFA_LOCAL]);
+ }
+ } else {
+ if (tb[IFA_ADDRESS])
+ ifp->address = *(uint32_t *)RTA_DATA(tb[IFA_ADDRESS]);
+ }
+
+ return 0;
+}
+
+/* Interface lookup bootstrap function */
+int netlink_interface_lookup(void)
+{
+ struct nl_handle nlh;
+ int status = 0;
+
+ if (netlink_socket(&nlh, 0) < 0)
+ return -1;
+
+ /* Interface lookup */
+ if (netlink_request(&nlh, AF_PACKET, RTM_GETLINK) < 0) {
+ status = -1;
+ goto end;
+ }
+ status = netlink_parse_info(netlink_if_link_filter, &nlh);
+
+ /* Address lookup */
+ if (netlink_request(&nlh, AF_INET, RTM_GETADDR) < 0) {
+ status = -1;
+ goto end;
+ }
+ status = netlink_parse_info(netlink_if_address_filter, &nlh);
+
+end:
+ netlink_close(&nlh);
+ return status;
+}
+
+/* Netlink flag Link update */
+static int netlink_reflect_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
+{
+ struct ifinfomsg *ifi;
+ struct rtattr *tb[IFLA_MAX + 1];
+ interface *ifp;
+ int len;
+
+ ifi = NLMSG_DATA(h);
+ if ( !(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
+ return 0;
+
+ len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ if (len < 0)
+ return -1;
+
+ /* Interface name lookup */
+ memset(tb, 0, sizeof(tb));
+ parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+ if (tb[IFLA_IFNAME] == NULL)
+ return -1;
+
+ /* ignore loopback device */
+ if (ifi->ifi_type == ARPHRD_LOOPBACK)
+ return 0;
+
+ /* find the interface */
+ ifp = if_get_by_ifindex(ifi->ifi_index);
+ if (!ifp)
+ return -1;
+
+ /* Update flags */
+ ifp->flags = ifi->ifi_flags;
+
+ return 0;
+}
+
+/* Netlink kernel message reflection */
+static int netlink_broadcast_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
+{
+ switch (h->nlmsg_type) {
+ case RTM_NEWLINK:
+ case RTM_DELLINK:
+ return netlink_reflect_filter(snl, h);
+ break;
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+// return netlink_if_address_filter(snl, h);
+ break;
+ default:
+ syslog(LOG_INFO, "Kernel is reflecting an unknown netlink nlmsg_type: %d"
+ , h->nlmsg_type);
+ break;
+ }
+ return 0;
+}
+
+int kernel_netlink(thread *thread)
+{
+ int status = 0;
+
+ if (thread->type != THREAD_READ_TIMEOUT)
+ status = netlink_parse_info(netlink_broadcast_filter, &nl_kernel);
+ thread_add_read(master, kernel_netlink
+ , NULL
+ , nl_kernel.fd
+ , NETLINK_TIMER);
+ return 0;
+}
+
+void kernel_netlink_init(void)
+{
+ unsigned long groups;
+
+ groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
+ netlink_socket(&nl_kernel, groups);
+
+ if (nl_kernel.fd > 0) {
+ syslog(LOG_INFO, "Registering Kernel netlink reflector");
+ thread_add_read(master, kernel_netlink
+ , NULL
+ , nl_kernel.fd
+ , NETLINK_TIMER);
+ }
+}
*
* Part: vrrp_netlink.c include file.
*
- * Version: $Id: vrrp_netlink.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: vrrp_netlink.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
__u32 seq;
};
+/* Define types */
+#define NETLINK_TIMER 30
+
+/* Our global netlink reflection handler */
+struct nl_handle nl_kernel;
+
/* prototypes */
extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen);
extern int netlink_socket(struct nl_handle *nl, unsigned long groups);
extern int netlink_close(struct nl_handle *nl);
extern int netlink_talk (struct nl_handle *nl, struct nlmsghdr *n);
+extern int netlink_interface_lookup(void);
+extern int netlink_interface_refresh(void);
+extern void kernel_netlink_init(void);
#endif
*
* Part: Sheduling framework for vrrp code.
*
- * Version: $Id: vrrp_scheduler.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: vrrp_scheduler.c,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "vrrp_scheduler.h"
#include "vrrp_ipsecah.h"
+#include "vrrp_netlink.h"
+#include "vrrp_if.h"
#include "vrrp.h"
+#include "ipvswrapper.h"
#include "memory.h"
#include "list.h"
+#include "data.h"
extern thread_master *master;
extern data *conf_data;
*/
static void vrrp_init_state(list l)
{
- vrrp_instance *vrrp;
+ vrrp_rt *vrrp;
element e;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
vrrp = ELEMENT_DATA(e);
- if (vrrp->vsrv->priority == VRRP_PRIO_OWNER ||
- vrrp->vsrv->wantstate == VRRP_STATE_MAST) {
- vrrp->vsrv->state = VRRP_STATE_GOTO_MASTER;
+ if (vrrp->priority == VRRP_PRIO_OWNER ||
+ vrrp->wantstate == VRRP_STATE_MAST) {
+ vrrp->state = VRRP_STATE_GOTO_MASTER;
} else {
- vrrp->vsrv->ms_down_timer = 3 * vrrp->vsrv->adver_int
- + VRRP_TIMER_SKEW(vrrp->vsrv);
- vrrp->vsrv->state = VRRP_STATE_BACK;
+ vrrp->ms_down_timer = 3 * vrrp->adver_int
+ + VRRP_TIMER_SKEW(vrrp);
+ /* Check if sync daemon handling is needed */
+ if (vrrp->lvs_syncd_if)
+ ipvs_syncd_cmd(IPVS_STARTDAEMON, vrrp->lvs_syncd_if
+ , IPVS_BACKUP);
+ vrrp->state = VRRP_STATE_BACK;
}
}
}
-static void vrrp_init_instance_sands(vrrp_instance *vrrp)
+static void vrrp_init_instance_sands(vrrp_rt *vrrp)
{
TIMEVAL timer;
timer = timer_now();
- if (vrrp->vsrv->state == VRRP_STATE_BACK) {
- vrrp->vsrv->sands.tv_sec = timer.tv_sec +
- vrrp->vsrv->ms_down_timer / TIMER_HZ;
- vrrp->vsrv->sands.tv_usec = timer.tv_usec +
- vrrp->vsrv->ms_down_timer % TIMER_HZ;
+ if (vrrp->state == VRRP_STATE_BACK ||
+ vrrp->state == VRRP_STATE_FAULT) {
+ vrrp->sands.tv_sec = timer.tv_sec +
+ vrrp->ms_down_timer / TIMER_HZ;
+ vrrp->sands.tv_usec = timer.tv_usec +
+ vrrp->ms_down_timer % TIMER_HZ;
}
- if (vrrp->vsrv->state == VRRP_STATE_GOTO_MASTER ||
- vrrp->vsrv->state == VRRP_STATE_MAST) {
- vrrp->vsrv->sands.tv_sec = timer.tv_sec +
- vrrp->vsrv->adver_int / TIMER_HZ;
- vrrp->vsrv->sands.tv_usec = timer.tv_usec;
+ if (vrrp->state == VRRP_STATE_GOTO_MASTER ||
+ vrrp->state == VRRP_STATE_GOTO_DUMMY_MAST ||
+ vrrp->state == VRRP_STATE_MAST ||
+ vrrp->state == VRRP_STATE_DUMMY_MAST ||
+ vrrp->state == VRRP_STATE_GOTO_FAULT) {
+ vrrp->sands.tv_sec = timer.tv_sec +
+ vrrp->adver_int / TIMER_HZ;
+ vrrp->sands.tv_usec = timer.tv_usec;
}
}
static void vrrp_init_sands(list l)
{
- vrrp_instance *vrrp;
+ vrrp_rt *vrrp;
element e;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
/* Timer functions */
static TIMEVAL vrrp_compute_timer(const int fd)
{
- vrrp_instance *vrrp;
+ vrrp_rt *vrrp;
TIMEVAL timer;
element e;
list l = conf_data->vrrp;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
vrrp = ELEMENT_DATA(e);
- if (vrrp->vsrv->fd == fd) {
- if (timer_cmp(vrrp->vsrv->sands, timer) < 0 ||
+ if (vrrp->fd == fd) {
+ if (timer_cmp(vrrp->sands, timer) < 0 ||
TIMER_ISNULL(timer))
- timer = timer_dup(vrrp->vsrv->sands);
+ timer = timer_dup(vrrp->sands);
}
}
static int vrrp_timer_vrid_timeout(const int fd)
{
- vrrp_instance *vrrp;
+ vrrp_rt *vrrp;
list l = conf_data->vrrp;
element e;
TIMEVAL vrrp_timer;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
vrrp = ELEMENT_DATA(e);
- if (timer_cmp(vrrp->vsrv->sands, vrrp_timer) == 0)
- vrid = vrrp->vsrv->vrid;
+ if (timer_cmp(vrrp->sands, vrrp_timer) == 0)
+ vrid = vrrp->vrid;
}
return vrid;
}
-/* Simple dump function
-static void vrrp_timer_dump(vrrp_instance *vrrp)
-{
- vrrp_instance *ptr = vrrp;
- TIMEVAL timer_now;
- TIMEVAL timer;
- long vrrp_timer = 0;
-
- memset(&timer, 0, sizeof(struct timeval));
-
- while (vrrp) {
- timer = timer_sub_now(vrrp->vsrv->sands);
- vrrp_timer = timer.tv_sec * TIMER_HZ + timer.tv_usec;
- syslog(LOG_DEBUG, "Timer(vrid,value) : (%d,%d)", vrrp->vsrv->vrid, vrrp_timer);
-
- vrrp = (vrrp_instance *)vrrp->next;
- }
- vrrp = ptr;
-}
-*/
-
/* Thread functions */
static void vrrp_register_workers(list l)
{
static void vrrp_create_sockpool(list l)
{
- vrrp_instance *vrrp;
+ vrrp_rt *vrrp;
list p = conf_data->vrrp;
element e;
int ifindex;
for (e = LIST_HEAD(p); e; ELEMENT_NEXT(e)) {
vrrp = ELEMENT_DATA(e);
- ifindex = ifname_to_idx(vrrp->vsrv->vif->ifname);
- if (vrrp->vsrv->vif->auth_type == VRRP_AUTH_AH)
+ ifindex = IF_INDEX(vrrp->ifp);
+ if (vrrp->auth_type == VRRP_AUTH_AH)
proto = IPPROTO_IPSEC_AH;
else
proto = IPPROTO_VRRP;
}
}
-static void vrrp_open_sockpool(list l)
+static int vrrp_open_sockpool(list l)
{
sock *sock;
element e;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
sock = ELEMENT_DATA(e);
sock->fd = open_vrrp_socket(sock->proto, sock->ifindex);
+ if (sock->fd == -1)
+ return -1;
}
+ return 1;
}
static void vrrp_set_fds(list l)
{
sock *sock;
- vrrp_instance *vrrp;
+ vrrp_rt *vrrp;
list p = conf_data->vrrp;
element e_sock;
element e_vrrp;
sock = ELEMENT_DATA(e_sock);
for (e_vrrp = LIST_HEAD(p); e_vrrp; ELEMENT_NEXT(e_vrrp)) {
vrrp = ELEMENT_DATA(e_vrrp);
- if (vrrp->vsrv->vif->auth_type == VRRP_AUTH_AH)
+ if (vrrp->auth_type == VRRP_AUTH_AH)
proto = IPPROTO_IPSEC_AH;
else
proto = IPPROTO_VRRP;
- if ((sock->ifindex == ifname_to_idx(vrrp->vsrv->vif->ifname)) &&
+ if ((sock->ifindex == IF_INDEX(vrrp->ifp)) &&
(sock->proto == proto))
- vrrp->vsrv->fd = sock->fd;
+ vrrp->fd = sock->fd;
}
}
}
int vrrp_dispatcher_init(thread *thread)
{
list pool;
+ int ret = 0;
/* allocate the sockpool */
pool = alloc_list(free_sock, dump_sock);
vrrp_create_sockpool(pool);
/* open the VRRP socket pool */
- vrrp_open_sockpool(pool);
+ ret = vrrp_open_sockpool(pool);
+ if (ret < 0) {
+ syslog(LOG_INFO, "Something is wrong with your hardware configuration");
+ free_list(pool);
+ thread_add_terminate_event(thread->master);
+ return -1;
+ }
/* set VRRP instance fds to sockpool */
vrrp_set_fds(pool);
dump_list(pool);
free_list(pool);
- return 0;
+ return 1;
}
-static vrrp_instance *vrrp_search_instance_isync(char *isync)
+static vrrp_rt *vrrp_search_instance_isync(char *isync)
{
- vrrp_instance *vrrp;
+ vrrp_rt *vrrp;
list l = conf_data->vrrp;
element e;
return NULL;
}
-static vrrp_instance *vrrp_search_instance(const int vrid)
+static vrrp_rt *vrrp_search_instance(const int vrid)
{
- vrrp_instance *vrrp;
+ vrrp_rt *vrrp;
list l = conf_data->vrrp;
element e;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
vrrp = ELEMENT_DATA(e);
- if (vrrp->vsrv->vrid == vrid)
+ if (vrrp->vrid == vrid)
return vrrp;
}
return NULL;
}
-static void vrrp_handle_backup(vrrp_instance *instance
+static void vrrp_handle_backup(vrrp_rt *vrrp
, char *vrrp_buffer
, int len)
{
- vrrp_state_backup(instance, vrrp_buffer, len);
+ struct iphdr *iph = (struct iphdr *)vrrp_buffer;
+ ipsec_ah *ah;
+
+ if (iph->protocol == IPPROTO_IPSEC_AH) {
+ ah = (ipsec_ah *)(vrrp_buffer + sizeof(struct iphdr));
+ if (ah->seq_number >= vrrp->ipsecah_counter->seq_number) {
+ vrrp->ipsecah_counter->seq_number = ah->seq_number + 10;
+ vrrp->ipsecah_counter->cycle = 0;
+ }
+ }
+
+ vrrp_state_backup(vrrp, vrrp_buffer, len);
}
-static void vrrp_handle_become_master(vrrp_instance *instance
+static void vrrp_handle_become_master(vrrp_rt *vrrp
, char *vrrp_buffer
, int len)
{
- vrrp_rt *vsrv = instance->vsrv;
struct iphdr *iph = (struct iphdr *)vrrp_buffer;
ipsec_ah *ah;
* with the remote IPSEC AH VRRP instance counter.
*/
if (iph->protocol == IPPROTO_IPSEC_AH) {
+ syslog(LOG_INFO, "VRRP_Instance(%s) AH seq_num sync"
+ , vrrp->iname);
ah = (ipsec_ah *)(vrrp_buffer + sizeof(struct iphdr));
- vsrv->ipsecah_counter->seq_number = ah->seq_number + 1;
- vsrv->ipsecah_counter->cycle = 0;
+ vrrp->ipsecah_counter->seq_number = ah->seq_number + 5;
+ vrrp->ipsecah_counter->cycle = 0;
}
+
+ /* Then jump to master state */
+ vrrp->wantstate = VRRP_STATE_MAST;
+ vrrp_state_goto_master(vrrp);
}
-static void vrrp_handle_leave_master(vrrp_instance *instance
+static void vrrp_handle_leave_master(vrrp_rt *vrrp
, char *vrrp_buffer
, int len)
{
- if (vrrp_state_master_rx(instance, vrrp_buffer, len)) {
- syslog(LOG_INFO, "VRRP_Instance(%s) Received higher prio advert"
- , instance->iname);
- vrrp_state_leave_master(instance);
+ if (!IF_ISUP(vrrp->ifp)) {
+ syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN"
+ , IF_NAME(vrrp->ifp));
+ vrrp->wantstate = VRRP_STATE_GOTO_FAULT;
+ } else if (vrrp_state_master_rx(vrrp, vrrp_buffer, len))
+ vrrp->wantstate = VRRP_STATE_BACK;
+
+ vrrp_state_leave_master(vrrp);
+}
+
+static void vrrp_handle_leave_fault(vrrp_rt *vrrp
+ , char *vrrp_buffer
+ , int len)
+{
+ vrrp_rt *vrrp_isync;
+
+ if (vrrp_state_fault_rx(vrrp, vrrp_buffer, len)) {
+ if (vrrp->isync) {
+ vrrp_isync = vrrp_search_instance_isync(vrrp->isync);
+
+ if (vrrp_isync->state != VRRP_STATE_FAULT ||
+ (vrrp_isync->state == VRRP_STATE_FAULT &&
+ IF_ISUP(vrrp_isync->ifp))) {
+ syslog(LOG_INFO, "VRRP_Instance(%s) prio is higher than received advert"
+ , vrrp->iname);
+ vrrp_handle_become_master(vrrp, vrrp_buffer, len);
+ }
+ } else {
+ syslog(LOG_INFO, "VRRP_Instance(%s) prio is higher than received advert"
+ , vrrp->iname);
+ vrrp_handle_become_master(vrrp, vrrp_buffer, len);
+ }
+ } else {
+ vrrp->state = VRRP_STATE_BACK;
+ }
+}
+
+static void vrrp_handle_leave_dummy_master(vrrp_rt *vrrp
+ , char *vrrp_buffer
+ , int len)
+{
+ vrrp_rt *vrrp_isync;
+
+ if (vrrp->isync) {
+ vrrp_isync = vrrp_search_instance_isync(vrrp->isync);
+
+ if (vrrp_isync->state == VRRP_STATE_FAULT &&
+ vrrp->wantstate == VRRP_STATE_GOTO_DUMMY_MAST) {
+ vrrp->wantstate = VRRP_STATE_DUMMY_MAST;
+ syslog(LOG_INFO, "VRRP_Instance(%s) leaving DUMMY MASTER state"
+ , vrrp->iname);
+ vrrp_state_leave_master(vrrp);
+ }
+
+ if (vrrp_isync->state != VRRP_STATE_FAULT) {
+ switch (vrrp_isync->state) {
+ case VRRP_STATE_BACK:
+ vrrp->state = VRRP_STATE_BACK;
+ break;
+ case VRRP_STATE_MAST:
+ vrrp_handle_become_master(vrrp, vrrp_buffer, len);
+ break;
+ }
+ }
}
}
-static int vrrp_handle_state(vrrp_instance *instance
+static int vrrp_handle_state(vrrp_rt *vrrp
, char *vrrp_buffer
, int len)
{
int previous_state;
- previous_state = instance->vsrv->state;
+ previous_state = vrrp->state;
- switch (instance->vsrv->state) {
+ switch (vrrp->state) {
case VRRP_STATE_BACK:
- vrrp_handle_backup(instance, vrrp_buffer, len);
+ vrrp_handle_backup(vrrp, vrrp_buffer, len);
break;
case VRRP_STATE_GOTO_MASTER:
- vrrp_handle_become_master(instance, vrrp_buffer, len);
+ vrrp_handle_become_master(vrrp, vrrp_buffer, len);
+ break;
+ case VRRP_STATE_DUMMY_MAST:
+// vrrp_handle_leave_dummy_master(vrrp, vrrp_buffer, len);
break;
case VRRP_STATE_MAST:
- vrrp_handle_leave_master(instance, vrrp_buffer, len);
+ vrrp_handle_leave_master(vrrp, vrrp_buffer, len);
+ break;
+ case VRRP_STATE_FAULT:
+ vrrp_handle_leave_fault(vrrp, vrrp_buffer, len);
break;
}
return previous_state;
}
-static void vrrp_handle_goto_master(vrrp_instance *instance)
+static void vrrp_handle_goto_master(vrrp_rt *vrrp)
{
- vrrp_rt *vsrv = instance->vsrv;
+// if (!IF_ISUP(vrrp->ifp)) {
+// syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN"
+// , IF_NAME(vrrp->ifp));
+// vrrp->state = VRRP_STATE_FAULT;
+// } else {
+ /* If becoming MASTER in IPSEC AH AUTH, we reset the anti-replay */
+ if (vrrp->ipsecah_counter->cycle) {
+ vrrp->ipsecah_counter->cycle = 0;
+ vrrp->ipsecah_counter->seq_number = 0;
+ }
+
+ if (vrrp->wantstate != VRRP_STATE_GOTO_DUMMY_MAST)
+ vrrp->wantstate = VRRP_STATE_MAST;
- /* If becoming MASTER in IPSEC AH AUTH, we reset the anti-replay */
- if (vsrv->ipsecah_counter->cycle) {
- vsrv->ipsecah_counter->cycle = 0;
- vsrv->ipsecah_counter->seq_number = 0;
+ /* handle master state transition */
+ vrrp_state_goto_master(vrrp);
+// }
+}
+
+static void vrrp_handle_master(vrrp_rt *vrrp)
+{
+ /* Check if interface we are running on is UP */
+ if (vrrp->wantstate != VRRP_STATE_GOTO_FAULT) {
+ if (!IF_ISUP(vrrp->ifp)) {
+ syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN"
+ , IF_NAME(vrrp->ifp));
+ vrrp->wantstate = VRRP_STATE_GOTO_FAULT;
+ }
}
- vsrv->state = VRRP_STATE_BACK;
- vsrv->wantstate = VRRP_STATE_MAST;
+ /* Then perform the state transition */
+ if (vrrp->wantstate == VRRP_STATE_GOTO_FAULT ||
+ vrrp->wantstate == VRRP_STATE_BACK ||
+ vrrp->ipsecah_counter->cycle) {
+ vrrp->ms_down_timer = 3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
- /* handle master state transition */
- vrrp_state_goto_master(instance);
+ /* handle backup state transition */
+ vrrp_state_leave_master(vrrp);
+
+ if (vrrp->state == VRRP_STATE_BACK)
+ syslog(LOG_INFO, "VRRP_Instance(%s) Now in BACKUP state"
+ , vrrp->iname);
+ if (vrrp->state == VRRP_STATE_FAULT)
+ syslog(LOG_INFO, "VRRP_Instance(%s) Now in FAULT state"
+ , vrrp->iname);
+ } else if (vrrp->state == VRRP_STATE_MAST) {
+ /* send the VRRP advert */
+ vrrp_state_master_tx(vrrp, 0);
+ }
}
-static void vrrp_handle_master(vrrp_instance *instance)
+static void vrrp_handle_fault(vrrp_rt *vrrp)
{
- vrrp_rt *vsrv = instance->vsrv;
+ if (IF_ISUP(vrrp->ifp)) {
+ syslog(LOG_INFO, "Kernel is reporting: interface %s UP"
+ , IF_NAME(vrrp->ifp));
+ /* refresh the multicast fd */
+ new_vrrp_socket(vrrp);
- if (vsrv->wantstate == VRRP_STATE_BACK ||
- vsrv->ipsecah_counter->cycle) {
- vsrv->ms_down_timer = 3 * vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);
+ /*
+ * We force the IPSEC AH seq_number sync
+ * to be done in read advert handler.
+ * So we ignore this timeouted state until remote
+ * VRRP MASTER send its advert for the concerned
+ * instance.
+ */
+ if (vrrp->auth_type == VRRP_AUTH_AH) {
+ /*
+ * Transition to BACKUP state for AH
+ * seq number synchronization.
+ */
+ syslog(LOG_INFO, "VRRP_Instance(%s) in FAULT state jump to AH sync"
+ , vrrp->iname);
+ vrrp->wantstate = VRRP_STATE_BACK;
+ vrrp_state_leave_master(vrrp);
+ } else {
+ /* Otherwise, we transit to init state */
+ if (vrrp->init_state == VRRP_STATE_BACK)
+ vrrp->state = VRRP_STATE_BACK;
+ else
+ vrrp_handle_goto_master(vrrp);
+ }
+ }
+}
- /* handle backup state transition */
- vsrv->state = VRRP_STATE_BACK;
- vrrp_state_leave_master(instance);
+static void vrrp_handle_dummy_master(vrrp_rt *vrrp)
+{
+ /* Check if interface we are running on is UP */
+ if (!IF_ISUP(vrrp->ifp))
+ vrrp->wantstate = VRRP_STATE_GOTO_FAULT;
+
+ if (vrrp->wantstate == VRRP_STATE_GOTO_FAULT) {
+ vrrp->ms_down_timer = 3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
- syslog(LOG_INFO, "VRRP_Instance(%s) Becoming BACKUP"
- , instance->iname);
+ /* handle backup state transition */
+ vrrp_state_leave_master(vrrp);
} else {
/* send the VRRP advert */
- vrrp_state_master_tx(instance, 0);
+ vrrp_state_master_tx(vrrp, 0);
}
}
-static int vrrp_handle_state_timeout(vrrp_instance *instance)
+static int vrrp_handle_state_timeout(vrrp_rt *vrrp)
{
int previous_state;
- previous_state = instance->vsrv->state;
+ previous_state = vrrp->state;
- switch (instance->vsrv->state) {
+ switch (vrrp->state) {
case VRRP_STATE_BACK:
- vrrp_handle_goto_master(instance);
+ vrrp_handle_goto_master(vrrp);
break;
case VRRP_STATE_GOTO_MASTER:
- vrrp_handle_goto_master(instance);
+ vrrp_handle_goto_master(vrrp);
+ break;
+ case VRRP_STATE_DUMMY_MAST:
+ vrrp_handle_dummy_master(vrrp);
break;
case VRRP_STATE_MAST:
- vrrp_handle_master(instance);
+ vrrp_handle_master(vrrp);
break;
case VRRP_STATE_FAULT:
- vrrp_handle_master(instance);
+ vrrp_handle_fault(vrrp);
break;
}
return previous_state;
}
-/* Our read packet dispatcher */
-int vrrp_read_dispatcher_thread(thread *thread)
+/* Handle dispatcher read timeout */
+static int vrrp_dispatcher_read_to(int fd)
{
- vrrp_instance *vrrp_isync;
- vrrp_instance *vrrp_instance;
- long vrrp_timer = 0;
- char *vrrp_buffer;
- struct iphdr *iph;
- vrrp_pkt *hd;
- int len = 0;
+ vrrp_rt *vrrp;
+ vrrp_rt *vrrp_isync;
int vrid = 0;
int previous_state = 0;
- if (thread->type == THREAD_READ_TIMEOUT) {
-
- /* Searching for matching instance */
- vrid = vrrp_timer_vrid_timeout(thread->u.fd);
- vrrp_instance = vrrp_search_instance(vrid);
-
- previous_state = vrrp_handle_state_timeout(vrrp_instance);
-
- /* handle master instance synchronization */
- if (previous_state == VRRP_STATE_BACK && vrrp_instance->isync) {
- vrrp_isync = vrrp_search_instance_isync(vrrp_instance->isync);
-
- if (vrrp_isync->vsrv->state == VRRP_STATE_BACK) {
- syslog(LOG_INFO, "VRRP_Instance(%s) must be sync with %s"
- , vrrp_instance->iname
- , vrrp_isync->iname);
-
- /* Send the higher priority advert */
- syslog(LOG_INFO, "VRRP_Instance(%s) sending OWNER advert"
- , vrrp_isync->iname);
- vrrp_state_master_tx(vrrp_isync, VRRP_PRIO_OWNER);
- } else {
- /* Otherwise, we simply update remotes arp tables */
- syslog(LOG_INFO, "VRRP_Instance(%s) gratuitous arp on %s"
- , vrrp_isync->iname
- , vrrp_isync->vsrv->vif->ifname);
- vrrp_isync->vsrv->state = VRRP_STATE_MAST;
- vrrp_send_gratuitous_arp(vrrp_isync);
- }
- }
+ /* Searching for matching instance */
+ vrid = vrrp_timer_vrid_timeout(fd);
+ vrrp = vrrp_search_instance(vrid);
- /*
- * We are sure the instance exist. So we can
- * compute new sands timer safely.
- */
- vrrp_init_instance_sands(vrrp_instance);
+ previous_state = vrrp_handle_state_timeout(vrrp);
- } else {
+ /* handle master instance synchronization */
+ if (previous_state == VRRP_STATE_BACK &&
+ vrrp->state == VRRP_STATE_MAST &&
+ vrrp->isync) {
+ vrrp_isync = vrrp_search_instance_isync(vrrp->isync);
- /* allocate & clean the read buffer */
- vrrp_buffer = (char *)MALLOC(VRRP_PACKET_TEMP_LEN);
-
- /* read & affect received buffer */
- len = read(thread->u.fd, vrrp_buffer, VRRP_PACKET_TEMP_LEN);
- iph = (struct iphdr *)vrrp_buffer;
-
- /* GCC bug : Workaround */
- hd = (vrrp_pkt *) ((char *)iph + (iph->ihl << 2));
- if (iph->protocol == IPPROTO_IPSEC_AH)
- hd = (vrrp_pkt *) ((char *)hd + vrrp_ipsecah_len());
- /* GCC bug : end */
-
- /* Searching for matching instance */
- vrrp_instance = vrrp_search_instance(hd->vrid);
-
- if (vrrp_instance) {
-
- previous_state = vrrp_handle_state(vrrp_instance, vrrp_buffer, len);
-
- /* handle backup instance synchronization */
- if (previous_state == VRRP_STATE_MAST &&
- vrrp_instance->vsrv->state == VRRP_STATE_BACK &&
- vrrp_instance->isync) {
- vrrp_isync = vrrp_search_instance_isync(vrrp_instance->isync);
-
- /* synchronized instance probably failed */
- if (vrrp_isync->vsrv->state == VRRP_STATE_MAST &&
- vrrp_isync->vsrv->init_state == VRRP_STATE_MAST) {
- syslog(LOG_INFO, "VRRP_Instance(%s) transition to FAULT state"
- , vrrp_instance->iname);
- vrrp_isync->vsrv->state = VRRP_STATE_FAULT;
- } else if (vrrp_isync->vsrv->state == VRRP_STATE_MAST) {
- syslog(LOG_INFO, "VRRP_Instance(%s) must be sync with %s"
- , vrrp_instance->iname
- , vrrp_isync->iname);
-
- /* Transition to BACKUP state */
- vrrp_isync->vsrv->wantstate = VRRP_STATE_BACK;
- }
- }
+ if (vrrp_isync->state == VRRP_STATE_BACK) {
+ syslog(LOG_INFO, "VRRP_Instance(%s) must be sync with %s"
+ , vrrp->iname
+ , vrrp_isync->iname);
+ /* Send the higher priority advert */
+ syslog(LOG_INFO, "VRRP_Instance(%s) sending OWNER advert"
+ , vrrp_isync->iname);
+ vrrp_state_master_tx(vrrp_isync, VRRP_PRIO_OWNER);
+ } else {
+ /* Otherwise, we simply update remotes arp caches */
+ vrrp_isync->state = VRRP_STATE_MAST;
+ vrrp_send_gratuitous_arp(vrrp_isync);
+ }
+ }
+
+ /* handle synchronization in FAULT state */
+ if (previous_state == VRRP_STATE_MAST &&
+ vrrp->state == VRRP_STATE_FAULT &&
+ vrrp->isync) {
+ vrrp_isync = vrrp_search_instance_isync(vrrp->isync);
+
+ if (vrrp_isync->state == VRRP_STATE_MAST) {
/*
- * Refresh sands only if found matching instance.
- * Otherwize the packet is simply ignored...
- *
- * FIXME: Add a dropping packet framework to not
- * degrade the instance timer during dropping.
+ * We force sync instance to backup mode.
+ * This reduce instance takeover to less than ms_down_timer.
+ * => by default ms_down_timer is set to 3secs.
+ * => Takeover will be less than 3secs !
*/
- vrrp_init_instance_sands(vrrp_instance);
+ //vrrp_isync->wantstate = VRRP_STATE_BACK;
+ vrrp_isync->wantstate = VRRP_STATE_GOTO_FAULT;
}
+ }
- /* cleanup the room */
+ /*
+ * Break a MASTER/BACKUP state loop after sync instance
+ * FAULT state transition.
+ * => We doesn't receive remote MASTER adverts.
+ * => Emulate a DUMMY master to break the loop.
+ */
+ if (previous_state == VRRP_STATE_MAST &&
+ vrrp->state == VRRP_STATE_BACK &&
+ vrrp->isync) {
+ vrrp_isync = vrrp_search_instance_isync(vrrp->isync);
+
+ if (vrrp_isync->state == VRRP_STATE_FAULT) {
+ syslog(LOG_INFO, "VRRP_Instance(%s) Transition to DUMMY MASTER"
+ , vrrp->iname);
+ vrrp->wantstate = VRRP_STATE_GOTO_DUMMY_MAST;
+ }
+ }
+
+ /* previous state symetry */
+ if (vrrp->state == VRRP_STATE_DUMMY_MAST &&
+ vrrp->isync) {
+ vrrp_isync = vrrp_search_instance_isync(vrrp->isync);
+
+ if (vrrp_isync->state == VRRP_STATE_MAST)
+ vrrp->state = VRRP_STATE_MAST;
+ }
+
+ /*
+ * We are sure the instance exist. So we can
+ * compute new sands timer safely.
+ */
+ vrrp_init_instance_sands(vrrp);
+ return vrrp->fd;
+}
+
+/* Handle dispatcher read packet */
+static int vrrp_dispatcher_read(int fd)
+{
+ vrrp_rt *vrrp;
+ vrrp_rt *vrrp_isync;
+ char *vrrp_buffer;
+ struct iphdr *iph;
+ vrrp_pkt *hd;
+ int len = 0;
+ int previous_state = 0;
+
+ /* allocate & clean the read buffer */
+ vrrp_buffer = (char *)MALLOC(VRRP_PACKET_TEMP_LEN);
+
+ /* read & affect received buffer */
+ len = read(fd, vrrp_buffer, VRRP_PACKET_TEMP_LEN);
+ iph = (struct iphdr *)vrrp_buffer;
+
+ /* GCC bug : Workaround */
+ hd = (vrrp_pkt *) ((char *)iph + (iph->ihl << 2));
+ if (iph->protocol == IPPROTO_IPSEC_AH)
+ hd = (vrrp_pkt *) ((char *)hd + vrrp_ipsecah_len());
+ /* GCC bug : end */
+
+ /* Searching for matching instance */
+ vrrp = vrrp_search_instance(hd->vrid);
+
+ /* If no instance found => ignore the advert */
+ if (!vrrp) {
FREE(vrrp_buffer);
+ return fd;
+ }
+
+ previous_state = vrrp_handle_state(vrrp, vrrp_buffer, len);
+ /* handle backup instance synchronization */
+ if (previous_state == VRRP_STATE_MAST &&
+ vrrp->state == VRRP_STATE_BACK &&
+ vrrp->isync) {
+ vrrp_isync = vrrp_search_instance_isync(vrrp->isync);
+
+ if (vrrp_isync->state == VRRP_STATE_MAST) {
+ syslog(LOG_INFO, "VRRP_Instance(%s) must be sync with %s"
+ , vrrp->iname
+ , vrrp_isync->iname);
+
+ /* Transition to BACKUP state */
+ vrrp_isync->wantstate = VRRP_STATE_BACK;
+ }
}
+ /*
+ * Refresh sands only if found matching instance.
+ * Otherwize the packet is simply ignored...
+ *
+ * FIXME: Add a dropping packet framework to not
+ * degrade the instance timer during dropping.
+ */
+ vrrp_init_instance_sands(vrrp);
+
+ /* cleanup the room */
+ FREE(vrrp_buffer);
+
+ return fd;
+}
+
+/* Our read packet dispatcher */
+int vrrp_read_dispatcher_thread(thread *thread)
+{
+ long vrrp_timer = 0;
+ int fd;
+
+ /* Dispatcher state handler */
+ if (thread->type == THREAD_READ_TIMEOUT)
+ fd = vrrp_dispatcher_read_to(thread->u.fd);
+ else
+ fd = vrrp_dispatcher_read(thread->u.fd);
+
/* register next dispatcher thread */
- vrrp_timer = vrrp_timer_fd(thread->u.fd);
+ vrrp_timer = vrrp_timer_fd(fd);
thread_add_read(thread->master, vrrp_read_dispatcher_thread
, NULL
- , thread->u.fd
+ , fd
, vrrp_timer);
return 0;
}
/* Register VRRP thread */
void register_vrrp_thread(void)
{
+ /* Init the packet dispatcher */
if (!LIST_ISEMPTY(conf_data->vrrp))
thread_add_event(master, vrrp_dispatcher_init
, NULL
*
* Part: vrrp_scheduler.c include file.
*
- * Version: $Id: vrrp_scheduler.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ * Version: $Id: vrrp_scheduler.h,v 0.5.5 2002/04/10 02:34:23 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* local include */
#include "scheduler.h"
-#include "data.h"
+#include "vrrp.h"
/*
* Our instance dispatcher use a socket pool.
- * That way we handle VRRP protocole type per
+ * That way we handle VRRP protocol type per
* physical interface.
*/
typedef struct {
} sock;
/* extern prototypes */
-extern int open_vrrp_socket(const int proto, const int index);
-extern int ifname_to_idx(const char *ifname);
-extern void vrrp_send_gratuitous_arp(vrrp_instance *vrrp_instance);
extern int vrrp_read_dispatcher_thread(thread *thread);
-extern int vrrp_state_master_rx(vrrp_instance *instance, char *buf, int buflen);
-extern void vrrp_state_master_tx(vrrp_instance *instance, const int prio);
-extern void vrrp_state_backup(vrrp_instance *instance, char *buf, int buflen);
-extern void vrrp_state_goto_master(vrrp_instance *vrrp_instance);
-extern void vrrp_state_leave_master(vrrp_instance *instance);
#endif