keepalived-1.1.0 v1.1.0
authorAlexandre Cassen <acassen@freebox.fr>
Mon, 21 Jul 2003 15:32:20 +0000 (17:32 +0200)
committerAlexandre Cassen <acassen@freebox.fr>
Mon, 28 Sep 2009 08:58:58 +0000 (10:58 +0200)
* keepalived-1.1.0 released.
* The release focus is : "High Performance"
* Name cleanup for the healthchecking directory. use check
  instead of healthcheck to be in conformance with watchdog and
  global software architecture.
* updated the SYNOPSIS file for documenting the table arg inside
  virtual/static_routes declaration. You can set routes refering
  to a specific TABLE-ID.
* Added a dummy debug var in the genhash declaration code to
  support compilation when compilation is done with debug flag.
* Added a set flag inside the real_server declaration correctly
  relfect the IPVS topology when inhibit_on_failure is used.
* fixed a daemon.h include depandency on signal.h
* VRRP : Added support to a global shared buffer for incoming
  advert handling. A new buffer is no longer allocated each time
  processing incoming advert, instead a shared room is used.
* VRRP : Added support to pre-allocated shared buffer for
  outgoing adverts. Each vrrp instance use a 'one time'
  allocated buffer instead of a 'all time' one.
* VRRP : Extended the socket pool design to support shared fd
  for the outbound channel. Now, socket pool create a sending
  socket and affect the fd returned to vrrp instances. This
  forces instances to use a shared socket instead of creating
  new socket for each outgoing adverts. The error detection
  is based on the incoming socket, so that outgoing socket is
  not created as long as incoming socket can not be created.
* Added support to netlink ipaddress as global keyword
  "static_ipaddress".
  look at doc/samples/keepalived.conf.static_ipaddress.
  IP addresses specified into this block will be added during
  daemon bootstrap and removed during daemon shutdown.
  Differential conf parsing is enabled for this block,
  removing/adding static_ipaddress can be done on the fly
  sending SIGHUP signal to daemon.
* VRRP : Extended track_interface to support multiple interface
  tracking. For those familiar with Nokia monitored circuit,
  this extention provide the same functionality.
  look at doc/samples/keepalived.conf.track_interface.
* VRRP : The VRRP instance lookup framework has been extended
  to use a o(1) scheduling design. Rewrote the whole instance
  lookup to use o(1) lookup instead of previous o(n^2). When
  receiving incoming adverts vrrp_scheduler performs a lookup
  over the VRID received to get local instance representation.
  Since the internal instance representation is an non-sorted
  linked list, then we run a lookup at o(n^2) complexity that
  introduce lantency and scheduling jitter side effect when
  runing large number of instances. To avoid this limitation
  a static hash table of 255 buckets were created. Since
  lookup is performed over VRID and since VRID is 8bit fixed,
  then the hashkey will be VRID. In order to extend code the
  hashkey is based on incoming fd too. Internally, a NIC is
  represented by a 2 fds : sending socket and receiving socket.
  Those fds are NIC specific so we are using them as a hash
  table lookup collision resolver. With this design we can now
  use the same VRID on different NICs. The collision design
  is a linked list so lookup is o(n^2) but due to low number
  of entries we can consider o(1) speed. But to reach best
  perf, differents VRID on all instance must be used. The
  design can be sumed by :
  VRID hash table :
     +---+---+---+---+---+---+.........+-----+
     | 1 | 2 | 3 | 4 | 5 | 6 |.........| 255 |
     +---+---+---+---+---+---+.........+-----+
           |       |
         +---+   +---+
         |fd3|   |fd1|
         +---+   +---+
                   |
                 +---+
                 |fd5|
                 +---+
  This hash table is filled during configuration parsing and
  VRRP instances are not duplicated but dynamically pointed
  to optimize memory.
* VRRP : The VRRP synchronization group lookup has been
  extended. During bootstrap a VRRP instance index is built upon
  sync_group instance name. This extension speed up
  synchronization since while synchronizing it perfoms the
  instance index instead of lookup by instance_name. The
  previous synchornization code has been rewritten to use this
  'list visiting' design for FAULT/BACKUP/MASTER states
  synchronization.
* VRRP : Optimized the vrrp_timer_vrid_timeout(...) to speed
  up vrid lookup over timeouted fd using a one pass lookup.
* Bradley Baetz, <bradley.baetz@optusnet.com.au> extended
  the scheduler framework to support child process handling.
  Adding support to new thread child facility for handling
  child processes, and modifying the scheduling select
  loop & signal handling to catch SIGCHLD, and call the
  appropriate process.
* Bradley Baetz, <bradley.baetz@optusnet.com.au> fixed
  the misc_check healthchecker using new thread child
  scheduling facility. Introduced a new keyword
  "misc_timeout" to kill processes which take too long
  time (default is delay_loop). SIGKILL is send to processes
  if they take too long time to shutdown.
* Bradley Baetz, <bradley.baetz@optusnet.com.au> extended
  daemon framework to block SIGCHLD to only receive it
  whn its unblocked in the scheduling loop.
* Extended healthchecker delay_loop to support long
  delay (ie: >1000s).
* VRRP : Added support to a shared kernel netlink command
  channel for setting ip address and routes.
* Extended the genhash code to support verbose output
  selection. command arg '-v' will generate a very verbose
  output.
* VRRP : Extended the logging code to select verbose log
  output or not. This selection is done by passing the
  '-D' option to command line while starting daemon.
  By default the output is silent.
* VRRP : Extended the gratuitous ARP framework to support
  shared buffer and shared socket. This increase performances
  for instances owning a bunch of VIP.
* VRRP : Extended the scheduling timer computation to support
  timer auto-recalibrating. While computing next instance
  timer, the scheduler will substract the time taken by
  previous advert handling. This provide software overhead
  adaptation. The recalibration is performed over usec timer
  to not pertube global scheduler.
* VRRP : Fixed a gratuitous ARP issue. Extended the
  ipaddress framework to point directly to interface
  reflected by netlink channel instead of storing device
  index. Extended the gratuitous ARP code to use new
  ipaddress structure and for sending garp over device
  ipaddess belong to. Needed if you run an instance on
  one device interface and set VRRP VIP on different
  interface.
* Extended watchdog framework to support polling delay
  selection via daemon command line. Created two new
  cmdline options :
       --wdog-vrrp  -R  Define VRRP watchdog polling
                        delay. (default=5s)
       --wdog-check -H  Define checkers watchdog
                        polling delay. (default=5s)
* Extended SMTP code to support bigger buffer while
  processing remote mta messages.
* Erik Barker, <erikb@netnation.com> extended initscript
  to support native redhat init functions.
* Extended the autoconf scripts and Makefile(s) to support
  code profiling. New configure option : --enable-profile
* list library has been extended to support multi-sized list &
  specific element deletion. Extended to return when list is
  empty. This reduce duplicated code to test is list is empty
  while processing.
* VRRP : Extended VRRP scheduler to support fd hash
  table design. Speed up instance lookup while
  computing instance sands. This offer o(1) design
  if we consider limited number of instances per
  device.
* VRRP : Extended vrrp new socket creation to replace
  refreshed instance fd into fd hash table index.
* VRRP : Extended vrrp framework to support
  blank virtual_ipaddress block, can be usefull
  if someone want to use just the VRRP advert
  as hello monitoring channel.
* Some code cleaning.

92 files changed:
CONTRIBUTORS
ChangeLog
Makefile.in
VERSION
configure
configure.in
doc/keepalived.conf.SYNOPSIS
doc/samples/keepalived.conf.track_interface
doc/samples/keepalived.conf.vrrp.static_ipaddress [new file with mode: 0644]
genhash/http.c
genhash/main.h
gmon.out [new file with mode: 0644]
keepalived.spec
keepalived/Makefile.in
keepalived/check/Makefile.in [moved from keepalived/healthcheck/Makefile.in with 96% similarity]
keepalived/check/check_api.c [moved from keepalived/healthcheck/check_api.c with 94% similarity]
keepalived/check/check_ci.c [moved from keepalived/healthcheck/check_ci.c with 98% similarity]
keepalived/check/check_daemon.c [moved from keepalived/healthcheck/check_daemon.c with 94% similarity]
keepalived/check/check_data.c [moved from keepalived/healthcheck/check_data.c with 97% similarity]
keepalived/check/check_http.c [moved from keepalived/healthcheck/check_http.c with 99% similarity]
keepalived/check/check_misc.c [moved from keepalived/healthcheck/check_misc.c with 55% similarity]
keepalived/check/check_parser.c [moved from keepalived/healthcheck/check_parser.c with 98% similarity]
keepalived/check/check_ssl.c [moved from keepalived/healthcheck/check_ssl.c with 99% similarity]
keepalived/check/check_tcp.c [moved from keepalived/healthcheck/check_tcp.c with 98% similarity]
keepalived/check/ipfwwrapper.c [moved from keepalived/healthcheck/ipfwwrapper.c with 97% similarity]
keepalived/check/ipvswrapper.c [moved from keepalived/healthcheck/ipvswrapper.c with 97% similarity]
keepalived/check/ipwrapper.c [moved from keepalived/healthcheck/ipwrapper.c with 98% similarity]
keepalived/core/daemon.c
keepalived/core/global_data.c
keepalived/core/global_parser.c
keepalived/core/layer4.c
keepalived/core/main.c
keepalived/core/pidfile.c
keepalived/core/smtp.c
keepalived/etc/init.d/keepalived.init
keepalived/etc/init.d/keepalived.rh.init [new file with mode: 0755]
keepalived/healthcheck/Makefile [deleted file]
keepalived/include/check_api.h
keepalived/include/check_ci.h
keepalived/include/check_daemon.h
keepalived/include/check_data.h
keepalived/include/check_http.h
keepalived/include/check_misc.h
keepalived/include/check_parser.h
keepalived/include/check_ssl.h
keepalived/include/check_tcp.h
keepalived/include/daemon.h
keepalived/include/global_data.h
keepalived/include/global_parser.h
keepalived/include/ipfwwrapper.h
keepalived/include/ipvswrapper.h
keepalived/include/ipwrapper.h
keepalived/include/layer4.h
keepalived/include/main.h
keepalived/include/pidfile.h
keepalived/include/smtp.h
keepalived/include/vrrp.h
keepalived/include/vrrp_arp.h
keepalived/include/vrrp_daemon.h
keepalived/include/vrrp_data.h
keepalived/include/vrrp_if.h
keepalived/include/vrrp_index.h [new file with mode: 0644]
keepalived/include/vrrp_ipaddress.h
keepalived/include/vrrp_iproute.h
keepalived/include/vrrp_ipsecah.h
keepalived/include/vrrp_netlink.h
keepalived/include/vrrp_notify.h
keepalived/include/vrrp_parser.h
keepalived/include/vrrp_scheduler.h
keepalived/include/vrrp_sync.h
keepalived/include/vrrp_track.h [new file with mode: 0644]
keepalived/libipvs/Makefile [deleted file]
keepalived/vrrp/Makefile.in
keepalived/vrrp/vrrp.c
keepalived/vrrp/vrrp_arp.c
keepalived/vrrp/vrrp_daemon.c
keepalived/vrrp/vrrp_data.c
keepalived/vrrp/vrrp_if.c
keepalived/vrrp/vrrp_index.c [new file with mode: 0644]
keepalived/vrrp/vrrp_ipaddress.c
keepalived/vrrp/vrrp_iproute.c
keepalived/vrrp/vrrp_ipsecah.c
keepalived/vrrp/vrrp_netlink.c
keepalived/vrrp/vrrp_notify.c
keepalived/vrrp/vrrp_parser.c
keepalived/vrrp/vrrp_scheduler.c
keepalived/vrrp/vrrp_sync.c
keepalived/vrrp/vrrp_track.c [new file with mode: 0644]
lib/list.c
lib/list.h
lib/scheduler.c
lib/scheduler.h

index 801a6bb..066a0d3 100644 (file)
@@ -1 +1,11 @@
-Jan Holmberg, <jan@artech.net>
+Jan Holmberg, <jan@artech.net> :
+       o Memory framework
+       o HTTP/SSL checkers
+
+Bradley Baetz, <bradley.baetz@optusnet.com.au> :
+       o MISC checker redesign
+       o Scheduler framework extension to support
+         child process handling.
+       o Daemon framework extension to block SIGCHLD
+         to only receive it when its unblocked in the
+         scheduling select loop.
index 3ed4188..f3eae65 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,164 @@
+2003-07-22  Alexandre Cassen  <acassen@linux-vs.org>
+       * keepalived-1.1.0 released.
+       * The release focus is : "High Performance"
+       * Name cleanup for the healthchecking directory. use check 
+         instead of healthcheck to be in conformance with watchdog and 
+         global software architecture.
+       * updated the SYNOPSIS file for documenting the table arg inside
+         virtual/static_routes declaration. You can set routes refering
+         to a specific TABLE-ID.
+       * Added a dummy debug var in the genhash declaration code to
+         support compilation when compilation is done with debug flag.
+       * Added a set flag inside the real_server declaration correctly
+         relfect the IPVS topology when inhibit_on_failure is used.
+       * fixed a daemon.h include depandency on signal.h
+       * VRRP : Added support to a global shared buffer for incoming
+         advert handling. A new buffer is no longer allocated each time
+         processing incoming advert, instead a shared room is used.
+       * VRRP : Added support to pre-allocated shared buffer for 
+         outgoing adverts. Each vrrp instance use a 'one time'
+         allocated buffer instead of a 'all time' one.
+       * VRRP : Extended the socket pool design to support shared fd
+         for the outbound channel. Now, socket pool create a sending
+         socket and affect the fd returned to vrrp instances. This
+         forces instances to use a shared socket instead of creating
+         new socket for each outgoing adverts. The error detection
+         is based on the incoming socket, so that outgoing socket is
+         not created as long as incoming socket can not be created.
+       * Added support to netlink ipaddress as global keyword
+         "static_ipaddress".
+         look at doc/samples/keepalived.conf.static_ipaddress.
+         IP addresses specified into this block will be added during
+         daemon bootstrap and removed during daemon shutdown. 
+         Differential conf parsing is enabled for this block, 
+         removing/adding static_ipaddress can be done on the fly 
+         sending SIGHUP signal to daemon.
+       * VRRP : Extended track_interface to support multiple interface
+         tracking. For those familiar with Nokia monitored circuit, 
+         this extention provide the same functionality.
+         look at doc/samples/keepalived.conf.track_interface.
+       * VRRP : The VRRP instance lookup framework has been extended
+         to use a o(1) scheduling design. Rewrote the whole instance
+         lookup to use o(1) lookup instead of previous o(n^2). When
+         receiving incoming adverts vrrp_scheduler performs a lookup
+         over the VRID received to get local instance representation.
+         Since the internal instance representation is an non-sorted
+         linked list, then we run a lookup at o(n^2) complexity that
+         introduce lantency and scheduling jitter side effect when
+         runing large number of instances. To avoid this limitation
+         a static hash table of 255 buckets were created. Since
+         lookup is performed over VRID and since VRID is 8bit fixed,
+         then the hashkey will be VRID. In order to extend code the
+         hashkey is based on incoming fd too. Internally, a NIC is
+         represented by a 2 fds : sending socket and receiving socket.
+         Those fds are NIC specific so we are using them as a hash
+         table lookup collision resolver. With this design we can now
+         use the same VRID on different NICs. The collision design
+         is a linked list so lookup is o(n^2) but due to low number
+         of entries we can consider o(1) speed. But to reach best
+         perf, differents VRID on all instance must be used. The
+         design can be sumed by :
+
+          VRID hash table :
+
+             +---+---+---+---+---+---+.........+-----+
+             | 1 | 2 | 3 | 4 | 5 | 6 |.........| 255 |
+             +---+---+---+---+---+---+.........+-----+
+                   |       |
+                 +---+   +---+
+                 |fd3|   |fd1|
+                 +---+   +---+
+                           |
+                         +---+
+                         |fd5|
+                         +---+ 
+
+         This hash table is filled during configuration parsing and
+         VRRP instances are not duplicated but dynamically pointed
+         to optimize memory.
+       * VRRP : The VRRP synchronization group lookup has been 
+         extended. During bootstrap a VRRP instance index is built upon
+         sync_group instance name. This extension speed up 
+         synchronization since while synchronizing it perfoms the 
+         instance index instead of lookup by instance_name. The 
+         previous synchornization code has been rewritten to use this 
+         'list visiting' design for FAULT/BACKUP/MASTER states 
+         synchronization.
+       * VRRP : Optimized the vrrp_timer_vrid_timeout(...) to speed
+         up vrid lookup over timeouted fd using a one pass lookup.
+       * Bradley Baetz, <bradley.baetz@optusnet.com.au> extended
+         the scheduler framework to support child process handling.
+         Adding support to new thread child facility for handling
+         child processes, and modifying the scheduling select
+         loop & signal handling to catch SIGCHLD, and call the
+         appropriate process.
+       * Bradley Baetz, <bradley.baetz@optusnet.com.au> fixed
+         the misc_check healthchecker using new thread child
+         scheduling facility. Introduced a new keyword
+         "misc_timeout" to kill processes which take too long
+         time (default is delay_loop). SIGKILL is send to processes
+         if they take too long time to shutdown.
+       * Bradley Baetz, <bradley.baetz@optusnet.com.au> extended
+         daemon framework to block SIGCHLD to only receive it
+         whn its unblocked in the scheduling loop.
+       * Extended healthchecker delay_loop to support long
+         delay (ie: >1000s).
+       * VRRP : Added support to a shared kernel netlink command
+         channel for setting ip address and routes.
+       * Extended the genhash code to support verbose output
+         selection. command arg '-v' will generate a very verbose
+         output.
+       * VRRP : Extended the logging code to select verbose log
+         output or not. This selection is done by passing the
+         '-D' option to command line while starting daemon.
+         By default the output is silent.
+       * VRRP : Extended the gratuitous ARP framework to support
+         shared buffer and shared socket. This increase performances
+         for instances owning a bunch of VIP.
+       * VRRP : Extended the scheduling timer computation to support
+         timer auto-recalibrating. While computing next instance
+         timer, the scheduler will substract the time taken by
+         previous advert handling. This provide software overhead
+         adaptation. The recalibration is performed over usec timer
+         to not pertube global scheduler.
+       * VRRP : Fixed a gratuitous ARP issue. Extended the
+         ipaddress framework to point directly to interface
+         reflected by netlink channel instead of storing device
+         index. Extended the gratuitous ARP code to use new
+         ipaddress structure and for sending garp over device
+         ipaddess belong to. Needed if you run an instance on
+         one device interface and set VRRP VIP on different
+         interface.
+       * Extended watchdog framework to support polling delay
+         selection via daemon command line. Created two new
+         cmdline options :
+              --wdog-vrrp  -R  Define VRRP watchdog polling
+                               delay. (default=5s)
+               --wdog-check -H  Define checkers watchdog
+                               polling delay. (default=5s)
+       * Extended SMTP code to support bigger buffer while
+         processing remote mta messages.
+       * Erik Barker, <erikb@netnation.com> extended initscript
+         to support native redhat init functions.
+       * Extended the autoconf scripts and Makefile(s) to support
+         code profiling. New configure option : --enable-profile
+       * list library has been extended to support multi-sized list &
+         specific element deletion. Extended to return when list is
+         empty. This reduce duplicated code to test is list is empty
+         while processing.
+       * VRRP : Extended VRRP scheduler to support fd hash
+         table design. Speed up instance lookup while
+         computing instance sands. This offer o(1) design
+         if we consider limited number of instances per
+         device.
+       * VRRP : Extended vrrp new socket creation to replace
+         refreshed instance fd into fd hash table index.
+       * VRRP : Extended vrrp framework to support
+         blank virtual_ipaddress block, can be usefull
+         if someone want to use just the VRRP advert
+         as hello monitoring channel.
+       * Some code cleaning.
+
 2003-05-12  Alexandre Cassen  <acassen@linux-vs.org>
        * keepalived-1.0.3 released.
        * This release has been sponsorized by :
index 4881e90..a0890d3 100644 (file)
@@ -17,6 +17,12 @@ debug:
        @echo ""
        @echo "Make complete"
 
+profile:
+       $(MAKE) -C lib || exit 1;
+       $(MAKE) -C keepalived profile
+       @echo ""
+       @echo "Make complete"
+
 clean:
        $(MAKE) -C lib clean
        $(MAKE) -C keepalived clean
diff --git a/VERSION b/VERSION
index 21e8796..9084fa2 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.3
+1.1.0
index dc83b73..269b62d 100755 (executable)
--- a/configure
+++ b/configure
@@ -23,6 +23,8 @@ ac_help="$ac_help
   --with-ci_linux         Compile with Cluster Infrastructure support (default no)"
 ac_help="$ac_help
   --enable-debug          compile with debugging flags"
+ac_help="$ac_help
+  --enable-profile        compile with profiling flags"
 
 # Initialize some variables set by options.
 # The variables have the same names as the options, with
@@ -539,7 +541,7 @@ OUTPUT_TARGET="Makefile genhash/Makefile keepalived/core/Makefile"
 # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:543: checking for $ac_word" >&5
+echo "configure:545: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -569,7 +571,7 @@ if test -z "$CC"; then
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:573: checking for $ac_word" >&5
+echo "configure:575: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -620,7 +622,7 @@ fi
       # Extract the first word of "cl", so it can be a program name with args.
 set dummy cl; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:624: checking for $ac_word" >&5
+echo "configure:626: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -652,7 +654,7 @@ fi
 fi
 
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:656: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:658: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
 
 ac_ext=c
 # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -663,12 +665,12 @@ cross_compiling=$ac_cv_prog_cc_cross
 
 cat > conftest.$ac_ext << EOF
 
-#line 667 "configure"
+#line 669 "configure"
 #include "confdefs.h"
 
 main(){return(0);}
 EOF
-if { (eval echo configure:672: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:674: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   ac_cv_prog_cc_works=yes
   # If we can't run a trivial program, we are probably using a cross compiler.
   if (./conftest; exit) 2>/dev/null; then
@@ -694,12 +696,12 @@ if test $ac_cv_prog_cc_works = no; then
   { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
 fi
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:698: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:700: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
 cross_compiling=$ac_cv_prog_cc_cross
 
 echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:703: checking whether we are using GNU C" >&5
+echo "configure:705: checking whether we are using GNU C" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -708,7 +710,7 @@ else
   yes;
 #endif
 EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:712: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:714: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
   ac_cv_prog_gcc=yes
 else
   ac_cv_prog_gcc=no
@@ -727,7 +729,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
 ac_save_CFLAGS="$CFLAGS"
 CFLAGS=
 echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:731: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:733: checking whether ${CC-cc} accepts -g" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -789,7 +791,7 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:793: checking for a BSD compatible install" >&5
+echo "configure:795: checking for a BSD compatible install" >&5
 if test -z "$INSTALL"; then
 if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -882,9 +884,15 @@ if test "${enable_debug+set}" = set; then
   :
 fi
 
+# Check whether --enable-profile or --disable-profile was given.
+if test "${enable_profile+set}" = set; then
+  enableval="$enable_profile"
+  :
+fi
+
 
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:888: checking how to run the C preprocessor" >&5
+echo "configure:896: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -899,13 +907,13 @@ else
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 903 "configure"
+#line 911 "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:909: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:917: \"$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
   :
@@ -916,13 +924,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 920 "configure"
+#line 928 "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:926: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:934: \"$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
   :
@@ -933,13 +941,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -nologo -E"
   cat > conftest.$ac_ext <<EOF
-#line 937 "configure"
+#line 945 "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:943: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:951: \"$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
   :
@@ -964,12 +972,12 @@ fi
 echo "$ac_t""$CPP" 1>&6
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:968: checking for ANSI C header files" >&5
+echo "configure:976: 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 973 "configure"
+#line 981 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -977,7 +985,7 @@ else
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:981: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:989: \"$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*
@@ -994,7 +1002,7 @@ rm -f 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 998 "configure"
+#line 1006 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -1012,7 +1020,7 @@ fi
 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 1016 "configure"
+#line 1024 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -1033,7 +1041,7 @@ if test "$cross_compiling" = yes; then
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 1037 "configure"
+#line 1045 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1044,7 +1052,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
 exit (0); }
 
 EOF
-if { (eval echo configure:1048: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1056: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -1068,12 +1076,12 @@ EOF
 fi
 
 echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
-echo "configure:1072: checking for sys/wait.h that is POSIX.1 compatible" >&5
+echo "configure:1080: 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 1077 "configure"
+#line 1085 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -1089,7 +1097,7 @@ wait (&s);
 s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
 ; return 0; }
 EOF
-if { (eval echo configure:1093: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1101: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_header_sys_wait_h=yes
 else
@@ -1113,17 +1121,17 @@ for ac_hdr in fcntl.h syslog.h unistd.h sys/ioctl.h sys/time.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1117: checking for $ac_hdr" >&5
+echo "configure:1125: 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 1122 "configure"
+#line 1130 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1127: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1135: \"$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*
@@ -1153,17 +1161,17 @@ for ac_hdr in linux/netlink.h linux/rtnetlink.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1157: checking for $ac_hdr" >&5
+echo "configure:1165: 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 1162 "configure"
+#line 1170 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1167: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1175: \"$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*
@@ -1193,17 +1201,17 @@ 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:1197: checking for $ac_hdr" >&5
+echo "configure:1205: 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 1202 "configure"
+#line 1210 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1207: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1215: \"$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*
@@ -1237,17 +1245,17 @@ if test "${ci_linux}" = "yes"; then
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1241: checking for $ac_hdr" >&5
+echo "configure:1249: 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 1246 "configure"
+#line 1254 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1251: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1259: \"$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*
@@ -1277,7 +1285,7 @@ done
 fi
 
 echo $ac_n "checking for MD5_Init in -lcrypto""... $ac_c" 1>&6
-echo "configure:1281: checking for MD5_Init in -lcrypto" >&5
+echo "configure:1289: 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
@@ -1285,7 +1293,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lcrypto  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1289 "configure"
+#line 1297 "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
@@ -1296,7 +1304,7 @@ int main() {
 MD5_Init()
 ; return 0; }
 EOF
-if { (eval echo configure:1300: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1308: \"$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
@@ -1325,7 +1333,7 @@ else
 fi
 
 echo $ac_n "checking for SSL_CTX_new in -lssl""... $ac_c" 1>&6
-echo "configure:1329: checking for SSL_CTX_new in -lssl" >&5
+echo "configure:1337: 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
@@ -1333,7 +1341,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lssl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1337 "configure"
+#line 1345 "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
@@ -1344,7 +1352,7 @@ int main() {
 SSL_CTX_new()
 ; return 0; }
 EOF
-if { (eval echo configure:1348: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1356: \"$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
@@ -1373,7 +1381,7 @@ else
 fi
 
 echo $ac_n "checking for poptGetContext in -lpopt""... $ac_c" 1>&6
-echo "configure:1377: checking for poptGetContext in -lpopt" >&5
+echo "configure:1385: 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
@@ -1381,7 +1389,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lpopt  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1385 "configure"
+#line 1393 "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
@@ -1392,7 +1400,7 @@ int main() {
 poptGetContext()
 ; return 0; }
 EOF
-if { (eval echo configure:1396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1404: \"$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
@@ -1422,7 +1430,7 @@ fi
 
 if test "${ci_linux}" = "yes"; then
   echo $ac_n "checking for cluster_maxnodes in -lcluster""... $ac_c" 1>&6
-echo "configure:1426: checking for cluster_maxnodes in -lcluster" >&5
+echo "configure:1434: checking for cluster_maxnodes in -lcluster" >&5
 ac_lib_var=`echo cluster'_'cluster_maxnodes | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1430,7 +1438,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lcluster  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1434 "configure"
+#line 1442 "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
@@ -1441,7 +1449,7 @@ int main() {
 cluster_maxnodes()
 ; return 0; }
 EOF
-if { (eval echo configure:1445: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1453: \"$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
@@ -1474,7 +1482,7 @@ fi
 CPPFLAGS="$CPPFLAGS -I$kernelinc"
 CFLAGS="$CFLAGS -I$kernelinc"
 echo $ac_n "checking for kernel >= 2.4.0""... $ac_c" 1>&6
-echo "configure:1478: checking for kernel >= 2.4.0" >&5
+echo "configure:1486: checking for kernel >= 2.4.0" >&5
 if test "$cross_compiling" = yes; then
   
     KERN="_KRNL_2_2_"
@@ -1482,7 +1490,7 @@ if test "$cross_compiling" = yes; then
   
 else
   cat > conftest.$ac_ext <<EOF
-#line 1486 "configure"
+#line 1494 "configure"
 #include "confdefs.h"
 
   #include <stdlib.h>
@@ -1495,7 +1503,7 @@ else
   #endif
   }
 EOF
-if { (eval echo configure:1499: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1507: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   
     KERN="_KRNL_2_4_"
@@ -1519,17 +1527,17 @@ IPVS_SUPPORT="_WITHOUT_LVS_"
 if test "$enable_lvs" != "no"; then
   ac_safe=`echo "net/ip_vs.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for net/ip_vs.h""... $ac_c" 1>&6
-echo "configure:1523: checking for net/ip_vs.h" >&5
+echo "configure:1531: checking for net/ip_vs.h" >&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 1528 "configure"
+#line 1536 "configure"
 #include "confdefs.h"
 #include <net/ip_vs.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1533: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1541: \"$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*
@@ -1561,7 +1569,7 @@ fi
 
 if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
   echo $ac_n "checking for IPVS version""... $ac_c" 1>&6
-echo "configure:1565: checking for IPVS version" >&5
+echo "configure:1573: checking for IPVS version" >&5
   if test "$cross_compiling" = yes; then
   
     IPVS_MAJOR="0"
@@ -1570,7 +1578,7 @@ echo "configure:1565: checking for IPVS version" >&5
   
 else
   cat > conftest.$ac_ext <<EOF
-#line 1574 "configure"
+#line 1582 "configure"
 #include "confdefs.h"
  
     #include <stdlib.h>
@@ -1585,7 +1593,7 @@ else
     } 
   
 EOF
-if { (eval echo configure:1589: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1597: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   
     IPVS_MAJOR=`head -n 1 ipvsinfo | tail -n 1`
@@ -1619,14 +1627,14 @@ fi
 VRRP_SUPPORT="_WITHOUT_VRRP_"
 if test "$enable_vrrp" != "no"; then
   echo $ac_n "checking for kernel netlink support""... $ac_c" 1>&6
-echo "configure:1623: checking for kernel netlink support" >&5
+echo "configure:1631: checking for kernel netlink support" >&5
   if test "$cross_compiling" = yes; then
   
       echo "$ac_t""no" 1>&6
     
 else
   cat > conftest.$ac_ext <<EOF
-#line 1630 "configure"
+#line 1638 "configure"
 #include "confdefs.h"
 
     #include <asm/types.h>
@@ -1640,7 +1648,7 @@ else
       exit(0);
     }
 EOF
-if { (eval echo configure:1644: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1652: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   
       echo "$ac_t""yes" 1>&6
@@ -1675,6 +1683,10 @@ if test "${enable_debug}" = "yes"; then
   
 fi
 
+if test "${enable_profile}" = "yes"; then
+  CFLAGS="$CFLAGS -pg"
+fi
+
 
 
 
@@ -1683,7 +1695,7 @@ fi
 IPVS_SYNCD="_WITHOUT_IPVS_SYNCD_"
 if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
   echo $ac_n "checking for LVS syncd support""... $ac_c" 1>&6
-echo "configure:1687: checking for LVS syncd support" >&5
+echo "configure:1699: checking for LVS syncd support" >&5
   if test "$IPVS_MAJOR" -ge 1 -a "$KERN" = "_KRNL_2_4_"; then
     IPVS_SYNCD="_HAVE_IPVS_SYNCD_"
   elif test "$IPVS_MINOR" -ge 9 -a "$IPVS_PATCH" -ge 2 -a "$KERN" = "_KRNL_2_4_"; then
@@ -1706,12 +1718,12 @@ fi
 
 
 echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:1710: checking for working const" >&5
+echo "configure:1722: 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 1715 "configure"
+#line 1727 "configure"
 #include "confdefs.h"
 
 int main() {
@@ -1760,7 +1772,7 @@ ccp = (char const *const *) p;
 
 ; return 0; }
 EOF
-if { (eval echo configure:1764: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1776: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_const=yes
 else
@@ -1781,12 +1793,12 @@ EOF
 fi
 
 echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:1785: checking for pid_t" >&5
+echo "configure:1797: 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 1790 "configure"
+#line 1802 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -1814,12 +1826,12 @@ EOF
 fi
 
 echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:1818: checking whether time.h and sys/time.h may both be included" >&5
+echo "configure:1830: 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 1823 "configure"
+#line 1835 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/time.h>
@@ -1828,7 +1840,7 @@ int main() {
 struct tm *tp;
 ; return 0; }
 EOF
-if { (eval echo configure:1832: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1844: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_header_time=yes
 else
@@ -1851,13 +1863,13 @@ fi
 
 if test $ac_cv_prog_gcc = yes; then
     echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
-echo "configure:1855: checking whether ${CC-cc} needs -traditional" >&5
+echo "configure:1867: 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 1861 "configure"
+#line 1873 "configure"
 #include "confdefs.h"
 #include <sgtty.h>
 Autoconf TIOCGETP
@@ -1875,7 +1887,7 @@ rm -f conftest*
 
   if test $ac_cv_prog_gcc_traditional = no; then
     cat > conftest.$ac_ext <<EOF
-#line 1879 "configure"
+#line 1891 "configure"
 #include "confdefs.h"
 #include <termio.h>
 Autoconf TCGETA
@@ -1897,12 +1909,12 @@ echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6
 fi
 
 echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:1901: checking return type of signal handlers" >&5
+echo "configure:1913: 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 1906 "configure"
+#line 1918 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -1919,7 +1931,7 @@ int main() {
 int i;
 ; return 0; }
 EOF
-if { (eval echo configure:1923: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1935: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_type_signal=void
 else
@@ -1940,12 +1952,12 @@ EOF
 for ac_func in gettimeofday select socket strerror strtol uname
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1944: checking for $ac_func" >&5
+echo "configure:1956: 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 1949 "configure"
+#line 1961 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -1968,7 +1980,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:1972: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1984: \"$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
@@ -1998,7 +2010,7 @@ if test "${VRRP_SUPPORT}" = "_WITH_VRRP_"; then
   OUTPUT_TARGET="$OUTPUT_TARGET keepalived/vrrp/Makefile"
 fi
 if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
-  OUTPUT_TARGET="$OUTPUT_TARGET keepalived/healthcheck/Makefile"
+  OUTPUT_TARGET="$OUTPUT_TARGET keepalived/check/Makefile"
   if test "$KERN" = "_KRNL_2_4_"; then
     OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipvs/Makefile"
   else
index 9c2ee23..359c426 100644 (file)
@@ -32,6 +32,8 @@ AC_ARG_WITH(ci_linux,
   [ci_linux="no"])
 AC_ARG_ENABLE(debug,
   [  --enable-debug          compile with debugging flags])
+AC_ARG_ENABLE(profile,
+  [  --enable-profile        compile with profiling flags])
 
 dnl ----[ Checks for header files ]----
 AC_HEADER_STDC
@@ -169,6 +171,10 @@ if test "${enable_debug}" = "yes"; then
   AC_SUBST(DFLAGS)
 fi
 
+if test "${enable_profile}" = "yes"; then
+  CFLAGS="$CFLAGS -pg"
+fi
+
 AC_SUBST(IPVS_SUPPORT)
 AC_SUBST(VRRP_SUPPORT)
 AC_SUBST(CI_LINUX)
@@ -217,7 +223,7 @@ if test "${VRRP_SUPPORT}" = "_WITH_VRRP_"; then
   OUTPUT_TARGET="$OUTPUT_TARGET keepalived/vrrp/Makefile"
 fi
 if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
-  OUTPUT_TARGET="$OUTPUT_TARGET keepalived/healthcheck/Makefile"
+  OUTPUT_TARGET="$OUTPUT_TARGET keepalived/check/Makefile"
   if test "$KERN" = "_KRNL_2_4_"; then
     OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipvs/Makefile"
   else
index edbc757..f905194 100644 (file)
@@ -22,7 +22,7 @@ This block is divided in 2 sub-block :
        The configuration block looks like :
 
 global_defs {                          # Block identification
-    notification_email {                       # Email to send alertes to
+    notification_email {               # Email to send alertes to
        <EMAIL ADDRESS>                 # Standard email address
       <EMAIL ADDRESS>
       ...
@@ -34,13 +34,30 @@ global_defs {                               # Block identification
     lvs_id <STRING>                       # String identifying router
 }
 
-       1.2. Static routes
+       1.2. Static addresses
+
+       The configuration block looks like :
+
+static_ipaddress {                     # block identification
+    <IP ADDRESS>/<MASK> dev <STRING> scope <SCOPE>
+    <IP ADDRESS>/<MASK> dev <STRING> scope <SCOPE>
+    ...
+}
+
+SCOPE can take the following values :
+       * site
+       * link
+       * host
+       * nowhere
+       * global
+
+       1.3. Static routes
 
        The configuration block looks like :
 
 static_routes {                                                        # block identification
-    src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> # to is optional
-    src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> # to is optional
+    src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> table <TABLE-ID> # to is optional
+    src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> table <TABLE-ID> # to is optional
     ...
 }
 
@@ -81,7 +98,11 @@ vrrp_sync_group <STRING> {   # VRRP sync group declaration
 vrrp_instance <STRING> {               # VRRP instance declaration
     state MASTER|BACKUP                        # Start-up default state
     interface <STRING>                 # Binding interface
-    track_interface <STRING>           # Interface state we monitor
+    track_interface {                  # Interfaces state we monitor
+      <STRING>
+      <STRING>
+      ...
+    }
     mcast_src_ip <IP ADDRESS>          # src_ip to use into the VRRP packets
     lvs_sync_daemon_interface <STRING> # Binding interface for lvs syncd
     garp_master_delay <INTEGER>                # delay for gratuitous ARP after MASTER
@@ -104,8 +125,8 @@ vrrp_instance <STRING> {            # VRRP instance declaration
         ...
     }
     virtual_routes {                    # VRRP virtual routes
-       src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> # to is optional
-       src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> # to is optional
+       src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> table <TABLE-ID> # to is optional
+       src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> table <TABLE-ID> # to is optional
         ...
     }
     preempt                            # VRRP preempt mode (default set)
@@ -217,5 +238,17 @@ virtual_server group <STRING>      {       # VS group declaration
             connect_timeout <INTEGER>  # Timeout connection
         }
     }
+
+    real_server <IP ADDRESS> <PORT> {  # Idem
+        weight <INTEGER>               # Idem
+        inhibit_on_failure             # Idem
+        notify_up <STRING>|<QUOTED-STRING> # Idem
+        notify_down <STRING>|<QUOTED-STRING> # Idem
+
+        MISC_CHECK {                           # MISC healthchecker
+            misc_path <STRING>|<QUOTED-STRING> # External system script or program
+            misc_timeout <INTEGER>             # Script execution timeout
+        }
+    }
 }
 
index 88f460b..bc7c2cf 100644 (file)
@@ -14,7 +14,10 @@ static_route {
 vrrp_instance VI_1 {
     state MASTER
     interface eth0.1           # Vlaned interface
-    track_interface eth0       # Interface state we monitor
+    track_interface {          # Interface state we monitor
+      eth0
+      eth1
+    }
     virtual_router_id 51
     priority 100
     virtual_ipaddress {
diff --git a/doc/samples/keepalived.conf.vrrp.static_ipaddress b/doc/samples/keepalived.conf.vrrp.static_ipaddress
new file mode 100644 (file)
index 0000000..baab1f1
--- /dev/null
@@ -0,0 +1,27 @@
+! Configuration File for keepalived
+
+global_defs {
+   lvs_id LVS_DEVEL
+}
+
+static_ipaddress {
+    192.168.200.16 dev eth0 scope link
+    192.168.200.17 dev eth1 scope link
+    192.168.200.18 dev eth2
+}
+
+vrrp_instance VI_1 {
+    state MASTER
+    interface eth0
+    virtual_router_id 51
+    priority 100
+    virtual_ipaddress {
+        192.168.200.20
+    }
+    virtual_routes {
+        src 192.168.100.1 192.168.109.0/24 via 192.168.200.254 dev eth1
+        192.168.110.0/24 via 192.168.200.254 dev eth1
+        192.168.111.0/24 dev eth2
+        192.168.112.0/24 via 192.168.100.254
+    }
+}
index b138787..b68d53d 100644 (file)
@@ -91,13 +91,16 @@ finalize(thread *thread)
        unsigned char digest[16];
        int i;
 
-       printf("\n");
        /* Compute final MD5 digest */
        MD5_Final(digest, &sock->context);
-       printf(HTML_MD5);
-       print_buffer(16, digest);
-
-       printf(HTML_MD5_FINAL);
+       if (req->verbose) {
+               printf("\n");
+               printf(HTML_MD5);
+               print_buffer(16, digest);
+       
+               printf(HTML_MD5_FINAL);
+       }
+       printf("MD5SUM = ");
        for (i = 0; i < 16; i++)
                printf("%02x", digest[i]);
        printf("\n\n");
@@ -114,19 +117,22 @@ int http_process_stream(SOCK *sock, int r)
        sock->total_size += r;
 
        if (!sock->extracted) {
-               printf(HTTP_HEADER_HEXA);
+               if (req->verbose)
+                       printf(HTTP_HEADER_HEXA);
                if ((sock->extracted =
                    extract_html(sock->buffer, sock->size))) {
-                       print_buffer(sock->extracted - sock->buffer, sock->buffer);
-                       printf(HTTP_HEADER_ASCII);
-                       for (r = 0; r < sock->extracted - sock->buffer; r++)
-                               printf("%c", sock->buffer[r]);
-                       printf("\n");
-
-                       printf(HTML_HEADER_HEXA);
+                       if (req->verbose) {
+                               print_buffer(sock->extracted - sock->buffer, sock->buffer);
+                               printf(HTTP_HEADER_ASCII);
+                               for (r = 0; r < sock->extracted - sock->buffer; r++)
+                                       printf("%c", sock->buffer[r]);
+                               printf("\n");
+                               printf(HTML_HEADER_HEXA);
+                       }
                        r = sock->size - (sock->extracted - sock->buffer);
                        if (r) {
-                               print_buffer(r, sock->extracted);
+                               if (req->verbose)
+                                       print_buffer(r, sock->extracted);
                                memcpy(sock->buffer, sock->extracted, r);
                                MD5_Update(&sock->context, sock->buffer,
                                           r);
@@ -142,7 +148,8 @@ int http_process_stream(SOCK *sock, int r)
                        }
                }
        } else if (sock->size) {
-               print_buffer(r, sock->buffer);
+               if (req->verbose)
+                       print_buffer(r, sock->buffer);
                MD5_Update(&sock->context, sock->buffer,
                           sock->size);
                sock->size = 0;
index 4ced6e2..c7ead3c 100644 (file)
@@ -70,6 +70,7 @@ typedef struct {
 
 /* Global variables */
 REQ *req;                              /* Cmd line arguments */
+unsigned int debug;
 
 /* Data buffer length description */
 #define BUFSIZE             1024
diff --git a/gmon.out b/gmon.out
new file mode 100644 (file)
index 0000000..3f53d23
Binary files /dev/null and b/gmon.out differ
index 4da837c..0484969 100644 (file)
@@ -1,7 +1,7 @@
 Name: keepalived
 Summary: HA monitor built upon LVS, VRRP and services poller
 Packager: Christophe Varoqui, <christophe.varoqui@free.fr>
-Version: 1.0.3
+Version: 1.1.0
 Release: 1
 Source: http://www.keepalived.org/software/%{name}-%{version}.tar.gz
 Copyright: GPL
index 2942975..89aac8a 100644 (file)
@@ -22,7 +22,7 @@ LDFLAGS = @LIBS@ @LDFLAGS@
 SUBDIRS = core
 
 ifeq ($(IPVS_FLAG),_WITH_LVS_)
-  SUBDIRS += healthcheck
+  SUBDIRS += check
 endif
 
 ifeq ($(VRRP_FLAG),_WITH_VRRP_)
@@ -56,6 +56,15 @@ debug:
        @echo ""
        @echo "Make complete"
 
+profile:
+       @set -e; \
+       for i in $(SUBDIRS); do \
+       $(MAKE) -C $$i || exit 1; done && \
+       echo "Building $(BIN)/$(EXEC)" && \
+       $(CC) -o $(BIN)/$(EXEC) $(LDFLAGS) -pg `find $(SUBDIRS) ../lib -name '*.[oa]'`
+       @echo ""
+       @echo "Make complete"
+
 clean:
        @set -e; \
        for i in $(SUBDIRS); do \
similarity index 96%
rename from keepalived/healthcheck/Makefile.in
rename to keepalived/check/Makefile.in
index e837fb6..a4ba5b1 100644 (file)
@@ -43,7 +43,8 @@ check_daemon.o: check_daemon.c ../include/check_daemon.h \
   ../include/check_parser.h ../include/check_data.h ../include/check_api.h \
   ../include/global_data.h ../include/ipwrapper.h ../include/pidfile.h \
   ../include/daemon.h ../../lib/list.h ../../lib/memory.h \
-  ../../lib/parser.h ../../lib/watchdog.h
+  ../../lib/parser.h ../../lib/watchdog.h ../include/vrrp_netlink.h \
+  ../include/vrrp_if.h
 check_data.o: check_data.c ../include/check_data.h \
   ../include/check_api.h ../../lib/memory.h ../../lib/utils.h
 check_parser.o: check_parser.c ../include/check_parser.h \
similarity index 94%
rename from keepalived/healthcheck/check_api.c
rename to keepalived/check/check_api.c
index 5502fe1..ea8fc84 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Checkers registration.
  *
- * Version:     $Id: check_api.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_api.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -35,6 +35,7 @@
 /* External vars */
 extern thread_master *master;
 extern check_conf_data *check_data;
+extern unsigned int debug;
 
 /* free checker data */
 static void
@@ -130,8 +131,9 @@ update_checker_activity(uint32_t address, int enable)
        element e;
 
        /* Display netlink operation */
-       syslog(LOG_INFO, "Netlink reflector reports IP %s %s",
-              inet_ntop2(address), (enable) ? "added" : "removed");
+       if (debug & 32)
+               syslog(LOG_INFO, "Netlink reflector reports IP %s %s",
+                      inet_ntop2(address), (enable) ? "added" : "removed");
 
        /* Processing Healthcheckers queue */
        if (!LIST_ISEMPTY(checkers_queue))
similarity index 98%
rename from keepalived/healthcheck/check_ci.c
rename to keepalived/check/check_ci.c
index eafb95c..6021edd 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        CI-LINUX checker. Integration to Compaq Cluster Infrastructure.
  *
- * Version:     $Id: check_ci.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_ci.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Aneesh Kumar K.V, <aneesh.kumar@digital.com>
similarity index 94%
rename from keepalived/healthcheck/check_daemon.c
rename to keepalived/check/check_daemon.c
index 58ac0c2..1bc89bf 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Healthcheckrs child process handling.
  *
- * Version:     $Id: check_daemon.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_daemon.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -32,6 +32,8 @@
 #include "memory.h"
 #include "parser.h"
 #include "watchdog.h"
+#include "vrrp_netlink.h"
+#include "vrrp_if.h"
 
 /* Global vars */
 check_conf_data *check_data;
@@ -55,6 +57,7 @@ extern int reload;
 extern pid_t checkers_child;
 extern char *conf_file;
 extern int init_ssl_ctx(void);
+extern int wdog_delay_check;
 
 /* Daemon stop sequence */
 static void
@@ -73,6 +76,7 @@ stop_check(void)
        /* Clean data */
        free_global_data(data);
        free_check_data(check_data);
+       free_interface_queue();
 
 #ifdef _DEBUG_
        keepalived_free_final("Healthcheck child process");
@@ -95,6 +99,8 @@ start_check(void)
 {
        /* Initialize sub-system */
        init_checkers_queue();
+       init_interface_queue();
+       kernel_netlink_init();
 
        /* Parse configuration file */
        data = alloc_global_data();
@@ -187,7 +193,7 @@ check_signal_init(void)
        signal_set(SIGINT, sigend_check);
        signal_set(SIGTERM, sigend_check);
        signal_set(SIGKILL, sigend_check);
-       signal_set(SIGCHLD, sigchld);
+       signal_noignore_sigchld();
 }
 
 /* Register VRRP thread */
@@ -210,13 +216,14 @@ start_check_child(void)
                               , strerror(errno));
                return -1;
        } else if (pid) {
+               int poll_delay = (wdog_delay_check) ? wdog_delay_check : WATCHDOG_DELAY;
                checkers_child = pid;
                syslog(LOG_INFO, "Starting Healthcheck child process, pid=%d"
                               , pid);
                /* Connect child watchdog */
                check_wdog_data.wdog_pid = pid;
                thread_add_timer(master, wdog_boot_thread, &check_wdog_data,
-                                WATCHDOG_DELAY);
+                                poll_delay);
                return 0;
        }
 
similarity index 97%
rename from keepalived/healthcheck/check_data.c
rename to keepalived/check/check_data.c
index e6b3a6b..1d50b79 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Healthcheckers dynamic data structure definition.
  *
- * Version:     $Id: check_data.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_data.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -153,8 +153,7 @@ free_vs(void *data)
        FREE_PTR(vs->vsgname);
        FREE_PTR(vs->virtualhost);
        FREE_PTR(vs->s_svr);
-       if (!LIST_ISEMPTY(vs->rs))
-               free_list(vs->rs);
+       free_list(vs->rs);
        FREE(vs);
 }
 static void
@@ -171,7 +170,9 @@ dump_vs(void *data)
                       , ntohs(SVR_PORT(vs)));
        if (vs->virtualhost)
                syslog(LOG_INFO, "   VirtualHost = %s", vs->virtualhost);
-       syslog(LOG_INFO, "   delay_loop = %d, lb_algo = %s", vs->delay_loop,
+       syslog(LOG_INFO, "   delay_loop = %lu, lb_algo = %s",
+              (vs->delay_loop >= TIMER_MAX_SEC) ? vs->delay_loop/TIMER_HZ :
+                                                  vs->delay_loop,
               vs->sched);
        if (atoi(vs->timeout_persistence) > 0)
                syslog(LOG_INFO, "   persistence timeout = %s",
similarity index 99%
rename from keepalived/healthcheck/check_http.c
rename to keepalived/check/check_http.c
index a5714f4..ab118e1 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        WEB CHECK. Common HTTP/SSL checker primitives.
  *
- * Version:     $Id: check_http.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_http.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Jan Holmberg, <jan@artech.net>
@@ -280,7 +280,7 @@ epilog(thread * thread, int method, int t, int c)
        http_arg *http_arg = HTTP_ARG(http_get_check);
        REQ *req = HTTP_REQ(http_arg);
        uint16_t addr_port = get_service_port(checker);
-       int delay = 0;
+       long delay = 0;
 
        if (method) {
                http_arg->url_it += t ? t : -http_arg->url_it;
similarity index 55%
rename from keepalived/healthcheck/check_misc.c
rename to keepalived/check/check_misc.c
index da58eb4..2ad2e42 100644 (file)
@@ -6,10 +6,11 @@
  * Part:        MISC CHECK. Perform a system call to run an extra
  *              system prog or script.
  *
- * Version:     $Id: check_misc.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_misc.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
+ *             Bradley Baetz, <bradley.baetz@optusnet.com.au>
  *
  *              This program is distributed in the hope that it will be useful,
  *              but WITHOUT ANY WARRANTY; without even the implied warranty of
 #include "utils.h"
 #include "parser.h"
 #include "notify.h"
+#include "daemon.h"
 
 int misc_check_thread(thread *);
+int misc_check_child_thread(thread *);
+int misc_check_child_timeout_thread(thread *);
 
 /* Configuration stream handling */
 void
@@ -51,6 +55,7 @@ dump_misc_check(void *data)
 
        syslog(LOG_INFO, "   Keepalive method = MISC_CHECK");
        syslog(LOG_INFO, "   script = %s", misc_chk->path);
+       syslog(LOG_INFO, "   timeout = %d", misc_chk->timeout);
 }
 
 void
@@ -67,16 +72,23 @@ void
 misc_path_handler(vector strvec)
 {
        misc_checker *misc_chk = CHECKER_GET();
-
        misc_chk->path = CHECKER_VALUE_STRING(strvec);
 }
 
 void
+misc_timeout_handler(vector strvec)
+{
+       misc_checker *misc_chk = CHECKER_GET();
+       misc_chk->timeout = CHECKER_VALUE_INT(strvec);
+}
+
+void
 install_misc_check_keyword(void)
 {
        install_keyword("MISC_CHECK", &misc_check_handler);
        install_sublevel();
        install_keyword("misc_path", &misc_path_handler);
+       install_keyword("misc_timeout", &misc_timeout_handler);
        install_sublevel_end();
 }
 
@@ -116,8 +128,14 @@ misc_check_thread(thread * thread)
        }
 
        /* In case of this is parent process */
-       if (pid)
+       if (pid) {
+               long timeout;
+               timeout = (misc_chk->timeout) ? misc_chk->timeout : checker->vs->delay_loop;
+
+               thread_add_child(thread->master, misc_check_child_thread,
+                                checker, pid, timeout);
                return 0;
+       }
 
        /* Child part */
        closeall(0);
@@ -126,26 +144,109 @@ misc_check_thread(thread * thread)
        dup(0);
        dup(0);
 
+       /* Also need to reset the signal state */
+       {
+               sigset_t empty_set;
+               sigemptyset(&empty_set);
+               sigprocmask(SIG_SETMASK, &empty_set, NULL);
+
+               signal(SIGHUP, SIG_DFL);
+               signal(SIGINT, SIG_DFL);
+               signal(SIGTERM, SIG_DFL);
+               signal(SIGKILL, SIG_DFL);
+       }
+
        status = system_call(misc_chk->path);
 
-       if (status >= 0) {      /* script error assumed  not an svr error */
+       if (status < 0 || !WIFEXITED(status))
+               status = 0; /* Script errors aren't server errors */
+       else
+               status = WEXITSTATUS(status);
+
+       exit(status);
+}
+
+int
+misc_check_child_thread(thread * thread)
+{
+       int wait_status;
+       checker *checker;
+       misc_checker *misc_chk;
+
+       checker = THREAD_ARG(thread);
+       misc_chk = CHECKER_ARG(checker);
+
+       if (thread->type == THREAD_CHILD_TIMEOUT) {
+               pid_t pid;
+
+               pid = THREAD_CHILD_PID(thread);
+
+               /* The child hasn't responded. Kill it off. */
+               if (ISALIVE(checker->rs)) {
+                       syslog(LOG_INFO, "Misc check to [%s] for [%s] timed out",
+                              inet_ntop2(CHECKER_RIP(checker)),
+                              misc_chk->path);
+                       smtp_alert(thread->master, checker->rs, NULL, NULL,
+                                  "DOWN",
+                                  "=> MISC CHECK script timeout on service <=");
+                       perform_svr_state(DOWN, checker->vs, checker->rs);
+               }
+
+               kill(pid, SIGTERM);
+               thread_add_child(thread->master, misc_check_child_timeout_thread,
+                                checker, pid, 2);
+               return 0;
+       }
+
+       wait_status = THREAD_CHILD_STATUS(thread);
+
+       if (WIFEXITED(wait_status)) {
+               int status;
+               status = WEXITSTATUS(wait_status);
                if (status == 0) {
                        /* everything is good */
                        if (!ISALIVE(checker->rs)) {
+                               syslog(LOG_INFO, "Misc check to [%s] for [%s] success.",
+                                      inet_ntop2(CHECKER_RIP(checker)),
+                                      misc_chk->path);
                                smtp_alert(thread->master, checker->rs, NULL, NULL,
                                           "UP",
                                           "=> MISC CHECK succeed on service <=");
-                               perform_svr_state(UP, checker->vs, checker->rs);
                        }
                } else {
                        if (ISALIVE(checker->rs)) {
+                               syslog(LOG_INFO, "Misc check to [%s] for [%s] failed.",
+                                      inet_ntop2(CHECKER_RIP(checker)),
+                                      misc_chk->path);
                                smtp_alert(thread->master, checker->rs, NULL, NULL,
                                           "DOWN",
                                           "=> MISC CHECK failed on service <=");
-                               perform_svr_state(DOWN, checker->vs, checker->rs);
                        }
                }
        }
 
-       exit(0);
+       return 0;
+}
+
+int
+misc_check_child_timeout_thread(thread * thread)
+{
+       pid_t pid;
+
+       if (thread->type != THREAD_CHILD_TIMEOUT)
+               return 0;
+
+       /* OK, it still hasn't exited. Now really kill it off. */
+       pid = THREAD_CHILD_PID(thread);
+       if (kill(pid, SIGKILL) < 0) {
+               /* Its possible it finished while we're handing this */
+               if (errno != ESRCH)
+                       DBG("kill error: %s", strerror(errno));
+               return 0;
+       }
+
+       syslog(LOG_WARNING, "Process [%d] didn't respond to SIGTERM", pid);
+       waitpid(pid, NULL, 0);
+
+       return 0;
 }
similarity index 98%
rename from keepalived/healthcheck/check_parser.c
rename to keepalived/check/check_parser.c
index 9c8b8c8..e36b0ac 100644 (file)
@@ -7,7 +7,7 @@
  *              data structure representation the conf file representing
  *              the loadbalanced server pool.
  *  
- * Version:     $Id: check_parser.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_parser.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
@@ -79,7 +79,7 @@ static void
 delay_handler(vector strvec)
 {
        virtual_server *vs = LIST_TAIL_DATA(check_data->vs);
-       vs->delay_loop = atoi(VECTOR_SLOT(strvec, 1));
+       vs->delay_loop = atoi(VECTOR_SLOT(strvec, 1)) * TIMER_HZ;
 }
 static void
 lbalgo_handler(vector strvec)
similarity index 99%
rename from keepalived/healthcheck/check_ssl.c
rename to keepalived/check/check_ssl.c
index f6f5452..09e18fe 100644 (file)
@@ -7,7 +7,7 @@
  *              url, compute a MD5 over this result and match it to the
  *              expected value.
  *
- * Version:     $Id: check_ssl.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_ssl.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Jan Holmberg, <jan@artech.net>
similarity index 98%
rename from keepalived/healthcheck/check_tcp.c
rename to keepalived/check/check_tcp.c
index 87ea8fc..8094d34 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        TCP checker.
  *
- * Version:     $Id: check_tcp.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_tcp.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
similarity index 97%
rename from keepalived/healthcheck/ipfwwrapper.c
rename to keepalived/check/ipfwwrapper.c
index 7a786e9..206f05b 100644 (file)
@@ -7,7 +7,7 @@
  *              library to add/remove server MASQ rules to the kernel 
  *              firewall framework.
  *
- * Version:     $Id: ipfwwrapper.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: ipfwwrapper.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
similarity index 97%
rename from keepalived/healthcheck/ipvswrapper.c
rename to keepalived/check/ipvswrapper.c
index f3729f9..b16e46b 100644 (file)
@@ -6,7 +6,7 @@
  * Part:        IPVS Kernel wrapper. Use setsockopt call to add/remove
  *              server to/from the loadbalanced server pool.
  *  
- * Version:     $Id: ipvswrapper.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: ipvswrapper.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
@@ -325,9 +325,15 @@ ipvs_cmd(int cmd, list vs_group, virtual_server * vs, real_server * rs)
                urule->weight = 0;
                cmd = IP_VS_SO_SET_EDITDEST;
        }
-       if (cmd == IP_VS_SO_SET_ADDDEST && rs->inhibit && !rs->alive)
+       if (cmd == IP_VS_SO_SET_ADDDEST && rs->inhibit && rs->set)
                cmd = IP_VS_SO_SET_EDITDEST;
 
+       /* Set flag */
+       if (cmd == IP_VS_SO_SET_ADDDEST && !rs->set)
+               rs->set = 1;
+       if (cmd == IP_VS_SO_SET_DELDEST && rs->set)
+               rs->set = 0;
+
        /* Set vs rule and send to kernel */
        if (vs->vsgname) {
                err = ipvs_group_cmd(cmd, vs_group, rs, urule, vs->vsgname);
similarity index 98%
rename from keepalived/healthcheck/ipwrapper.c
rename to keepalived/check/ipwrapper.c
index 9f9aac4..7eead72 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Manipulation functions for IPVS & IPFW wrappers.
  *
- * Version:     $id: ipwrapper.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $id: ipwrapper.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -429,6 +429,7 @@ rs_exist(real_server * old_rs, list l)
                         * already set IPVS rule.
                         */
                        rs->alive = old_rs->alive;
+                       rs->set = old_rs->set;
                        return 1;
                }
        }
@@ -442,12 +443,12 @@ get_rs_list(virtual_server * vs)
 {
        element e;
        list l = check_data->vs;
-       virtual_server *vsrv;
+       virtual_server *vsvr;
 
        for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-               vsrv = ELEMENT_DATA(e);
-               if (VS_ISEQ(vs, vsrv))
-                       return vsrv->rs;
+               vsvr = ELEMENT_DATA(e);
+               if (VS_ISEQ(vs, vsvr))
+                       return vsvr->rs;
        }
 
        /* most of the time never reached */
index b1e8902..6216437 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Main program structure.
  *
- * Version:     $Id: main.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: main.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -80,9 +80,31 @@ xdaemon(int nochdir, int noclose, int exitflag)
  * stuck waiting child termination.
  */
 void
-sigchld(int sig)
+dummy_handler(int sig)
 {
-       while (waitpid(-1, NULL, WNOHANG) > 0);
+       /* Dummy */
+}
+
+void
+signal_noignore_sigchld(void)
+{
+       struct sigaction sa;
+       sigset_t mask;
+
+       /* Need to remove the NOCHLD flag */
+       sigemptyset(&mask);
+       sa.sa_handler = dummy_handler;
+       sa.sa_mask = mask;
+       sa.sa_flags = 0;
+
+       sigaction(SIGCHLD, &sa, NULL);
+
+       /* Block SIGCHLD so that we only receive it
+        * when required (ie when its unblocked in the
+        * select loop)
+        */
+       sigaddset(&mask, SIGCHLD);
+       sigprocmask(SIG_BLOCK, &mask, NULL);
 }
 
 /* Signal wrapper */
index c76a6c3..318ab8c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Dynamic data structure definition.
  *
- * Version:     $Id: global_data.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: global_data.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index c40f502..1ff0c8c 100644 (file)
@@ -7,7 +7,7 @@
  *              data structure representation the conf file representing
  *              the loadbalanced server pool.
  *  
- * Version:     $Id: global_parser.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: global_parser.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
index dc60b13..2a05f3a 100644 (file)
@@ -6,7 +6,7 @@
  * Part:        Layer4 checkers handling. Register worker threads &
  *              upper layer checkers.
  *
- * Version:     $Id: layer4.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: layer4.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 887cb4a..1050c2a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Main program structure.
  *
- * Version:     $Id: main.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: main.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -78,19 +78,29 @@ void
 sigend(int sig)
 {
        int status;
+       sigset_t mask;
 
        /* register the terminate thread */
        syslog(LOG_INFO, "Terminating on signal");
        thread_add_terminate_event(master);
 
-       /* Signal child process */
+       /*
+        * Signal child process.
+        * Disable and unblock the SIGCHLD handler
+        * so that wait() works.
+        */
+       signal_ignore(SIGCHLD);
+       sigemptyset(&mask);
+       sigaddset(&mask, SIGCHLD);
+       sigprocmask(SIG_UNBLOCK, &mask, NULL);
+
        if (vrrp_child > 0) {
                kill(vrrp_child, SIGTERM);
-               wait(&status);
+               waitpid(vrrp_child, &status, WNOHANG);
        }
        if (checkers_child > 0) {
                kill(checkers_child, SIGTERM);
-               wait(&status);
+               waitpid(checkers_child, &status, WNOHANG);
        }
 }
 
@@ -102,7 +112,7 @@ signal_init(void)
        signal_set(SIGINT, sigend);
        signal_set(SIGTERM, sigend);
        signal_set(SIGKILL, sigend);
-       signal_set(SIGCHLD, sigchld);
+       signal_noignore_sigchld();
 }
 
 /* Usage function */
@@ -125,11 +135,14 @@ usage(const char *prog)
                "  %s --dont-fork          -n    Dont fork the daemon process.\n"
                "  %s --use-file           -f    Use the specified configuration file.\n"
                "                                Default is /etc/keepalived/keepalived.conf.\n"
+               "  %s --wdog-vrrp          -R    Define VRRP watchdog polling delay. (default=5s)\n"
+               "  %s --wdog-check         -H    Define checkers watchdog polling delay. (default=5s)\n"
                "  %s --dump-conf          -d    Dump the configuration data.\n"
                "  %s --log-console        -l    Log message to local console.\n"
+               "  %s --log-detail         -D    Detailed log messages.\n"
                "  %s --help               -h    Display this short inlined help screen.\n"
                "  %s --version            -v    Display the version number\n",
-               prog, prog, prog, prog, prog, prog, prog, prog);
+               prog, prog, prog, prog, prog, prog, prog, prog, prog, prog, prog);
 }
 
 /* Command line parser */
@@ -144,11 +157,14 @@ parse_cmdline(int argc, char **argv)
                {"version", 'v', POPT_ARG_NONE, NULL, 'v'},
                {"help", 'h', POPT_ARG_NONE, NULL, 'h'},
                {"log-console", 'l', POPT_ARG_NONE, NULL, 'l'},
+               {"log-detail", 'D', POPT_ARG_NONE, NULL, 'D'},
                {"dont-release-vrrp", 'V', POPT_ARG_NONE, NULL, 'V'},
                {"dont-release-ipvs", 'I', POPT_ARG_NONE, NULL, 'I'},
                {"dont-fork", 'n', POPT_ARG_NONE, NULL, 'n'},
                {"dump-conf", 'd', POPT_ARG_NONE, NULL, 'd'},
                {"use-file", 'f', POPT_ARG_STRING, &optarg, 'f'},
+               {"wdog-vrrp", 'R', POPT_ARG_STRING, &optarg, 'R'},
+               {"wdog-check", 'H', POPT_ARG_STRING, &optarg, 'H'},
                {NULL, 0, 0, NULL, 0}
        };
 
@@ -183,9 +199,18 @@ parse_cmdline(int argc, char **argv)
        case 'I':
                debug |= 16;
                break;
+       case 'D':
+               debug |= 32;
+               break;
        case 'f':
                conf_file = optarg;
                break;
+       case 'R':
+               wdog_delay_vrrp = atoi(optarg);
+               break;
+       case 'H':
+               wdog_delay_check = atoi(optarg);
+               break;
        }
 
        /* the others */
@@ -206,9 +231,18 @@ parse_cmdline(int argc, char **argv)
                case 'I':
                        debug |= 16;
                        break;
+               case 'D':
+                       debug |= 32;
+                       break;
                case 'f':
                        conf_file = optarg;
                        break;
+               case 'R':
+                       wdog_delay_vrrp = atoi(optarg);
+                       break;
+               case 'H':
+                       wdog_delay_check = atoi(optarg);
+                       break;
                }
        }
 
index fa19010..447e2e3 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        pidfile utility.
  *
- * Version:     $Id: pidfile.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: pidfile.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 0862167..46e8310 100644 (file)
@@ -7,7 +7,7 @@
  *              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 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: smtp.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index bb1f48e..c070c8d 100755 (executable)
@@ -15,7 +15,7 @@ PID_FILE="/var/run/keepalived.pid"
 case "$1" in
   start)
        echo -n "Starting Keepalived for LVS: "
-       keepalived
+       keepalived -D
        touch /var/lock/subsys/keepalived
        echo
        ;;
@@ -32,7 +32,7 @@ case "$1" in
        kill $PID
        echo
        echo -n "Starting Keepalived for LVS: "
-       keepalived
+       keepalived -D
        echo
        ;;
   reload)
diff --git a/keepalived/etc/init.d/keepalived.rh.init b/keepalived/etc/init.d/keepalived.rh.init
new file mode 100755 (executable)
index 0000000..cba6cb7
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# Startup script for the Keepalived daemon
+#
+# processname: keepalived
+# pidfile: /var/run/keepalived.pid
+# config: /etc/keepalived/keepalived.conf
+# chkconfig: 35 21 79
+# description: Start and stop Keepalived
+
+# Global definitions
+PID_FILE="/var/run/keepalived.pid"
+
+# source function library
+. /etc/init.d/functions
+
+RETVAL=0
+
+start() {
+       echo -n "Starting Keepalived for LVS: "
+       daemon keepalived -D
+       RETVAL=$?
+        echo
+        [ $RETVAL -eq 0 ] && touch /var/lock/subsys/keepalived
+        return $RETVAL
+}
+
+stop() {
+       echo -n "Shutting down Keepalived for LVS: "
+       killproc keepalived
+       RETVAL=0
+        echo
+        [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/keepalived
+        return $RETVAL
+}
+
+reload() {
+       echo -n "Reloading Keepalived config: "
+       killproc keepalived -1
+       RETVAL=$?
+        echo
+        return $RETVAL
+}
+
+# See how we were called.
+case "$1" in
+  start)
+        start
+        ;;
+  stop)
+        stop
+        ;;
+  restart)
+        stop
+        start
+        ;;
+  reload)
+        reload
+        ;;
+  status)
+        status keepalived
+        ;;
+  condrestart)
+        [ -f /var/lock/subsys/keepalived ] && $0 restart || :
+        ;;
+  *)
+       echo "Usage: $0 {start|stop|restart|reload|condrestart|status}"
+       exit 1
+esac
+
+exit 0
diff --git a/keepalived/healthcheck/Makefile b/keepalived/healthcheck/Makefile
deleted file mode 100644 (file)
index c462284..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-# Generated automatically from Makefile.in by configure.
-# Makefile
-#
-# Keepalived OpenSource project.
-#
-# Copyright (C) 2001, 2002, 2003 Alexandre Cassen, <acassen@linux-vs.org>
-
-KERNEL   = _KRNL_2_4_
-CC      = gcc
-CI_LINUX = 
-ifeq ($(CI_LINUX),_WITH_CI_LINUX_)
-CI_LINUX_OBJ = check_ci.o
-CIFLAGS = -D$(CI_LINUX)
-endif
-INCLUDES = -I../include -I../../lib
-CFLAGS  = -g -O2 -I/usr/src/linux/include $(INCLUDES) \
-          -Wall -Wunused -Wstrict-prototypes
-DEFS    = -D$(KERNEL) -D_WITH_LVS_ -D_HAVE_IPVS_SYNCD_ -D_WITH_VRRP_  $(CIFLAGS)
-COMPILE         = $(CC) $(CFLAGS) $(DEFS)
-
-OBJS =         check_daemon.o check_data.o check_parser.o \
-       check_api.o check_tcp.o check_http.o check_ssl.o \
-       check_misc.o ipwrapper.o ipvswrapper.o $(CI_LINUX_OBJ)
-
-ifeq ($(KERNEL),_KRNL_2_2_)
-  OBJS += ipfwwrapper.o
-  HEADERS += ipfwwrapper.h
-endif
-
-HEADERS = $(OBJS:.o=.h)
-
-.c.o:
-       $(COMPILE) -c $<
-
-all:   $(OBJS)
-
-clean:
-       rm -f *.a *.o *~
-
-distclean: clean
-       rm -f Makefile
-
-check_daemon.o: check_daemon.c ../include/check_daemon.h \
-  ../include/check_parser.h ../include/check_data.h ../include/check_api.h \
-  ../include/global_data.h ../include/ipwrapper.h ../include/pidfile.h \
-  ../include/daemon.h ../../lib/list.h ../../lib/memory.h \
-  ../../lib/parser.h ../../lib/watchdog.h
-check_data.o: check_data.c ../include/check_data.h \
-  ../include/check_api.h ../../lib/memory.h ../../lib/utils.h
-check_parser.o: check_parser.c ../include/check_parser.h \
-  ../include/check_data.h ../include/check_api.h ../include/global_data.h \
-  ../include/global_parser.h ../../lib/parser.h ../../lib/memory.h \
-  ../../lib/utils.h
-check_api.o: check_api.c ../include/check_api.h ../../lib/parser.h \
-  ../../lib/memory.h ../../lib/utils.h ../include/check_misc.h \
-  ../include/check_tcp.h ../include/check_http.h ../include/check_ssl.h
-check_tcp.o: check_tcp.c ../include/check_tcp.h ../include/check_api.h \
-  ../../lib/memory.h ../include/ipwrapper.h ../include/layer4.h \
-  ../include/smtp.h ../../lib/utils.h ../../lib/parser.h
-check_http.o: check_http.c ../include/check_http.h ../include/check_ssl.h \
-  ../include/check_api.h ../../lib/memory.h ../../lib/parser.h \
-  ../../lib/utils.h
-check_ssl.o: check_ssl.c ../include/check_ssl.h ../include/check_api.h \
-  ../../lib/memory.h ../../lib/parser.h ../include/smtp.h \
-  ../../lib/utils.h
-check_misc.o: check_misc.c ../include/check_misc.h ../include/check_api.h \
-  ../../lib/memory.h ../include/ipwrapper.h ../include/smtp.h \
-  ../../lib/utils.h ../../lib/notify.h ../../lib/parser.h ../include/daemon.h
-ipwrapper.o: ipwrapper.c ../include/ipwrapper.h ../../lib/utils.h \
-  ../../lib/notify.h
-ipvswrapper.o: ipvswrapper.c ../include/ipvswrapper.h ../../lib/utils.h \
-  ../../lib/memory.h
index e5aa845..1811423 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Checkers arguments structures definitions.
  *
- * Version:     $Id: check_api.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_api.h,v 1.1.0 2003/07/20 23:41:34 ACAssen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 394c4c7..9711648 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_ci.c include file.
  *
- * Version:     $Id: check_ci.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_ci.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Aneesh Kumar K.V, <aneesh.kumar@digital.com>
index 252d04b..fc075de 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_daemon.c include file.
  * 
- * Version:     $Id: check_daemon.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_daemon.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
index d892672..116a8a3 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Healthcheckers dynamic data structure definition.
  *
- * Version:     $Id: check_data.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_data.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -76,6 +76,7 @@ typedef struct _real_server {
        char *notify_up;        /* Script to launch when RS is added to LVS */
        char *notify_down;      /* Script to launch when RS is removed from LVS */
        int alive;
+       int set;                /* in the IPVS table */
 } real_server;
 
 /* Virtual Server group definition */
@@ -101,7 +102,7 @@ typedef struct _virtual_server {
        uint16_t addr_port;
        uint32_t vfwmark;
        uint16_t service_type;
-       int delay_loop;
+       long delay_loop;
        int ha_suspend;
        char sched[SCHED_MAX_LENGTH];
        char timeout_persistence[MAX_TIMEOUT_LENGTH];
index 740b0d4..a8f5567 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_http.c include file.
  *
- * Version:     $Id: check_http.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_http.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Jan Holmberg, <jan@artech.net>
index 23e40fc..01a65d4 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_misc.c include file.
  *
- * Version:     $Id: check_misc.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_misc.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
@@ -33,6 +33,7 @@
 /* Checker argument structure  */
 typedef struct _misc_checker {
        char *path;
+       int timeout;
 } misc_checker;
 
 /* Prototypes defs */
index 917c40f..db44808 100644 (file)
@@ -5,7 +5,7 @@
  * 
  * Part:        check_parser.c include file.
  *  
- * Version:     $Id: check_parser.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_parser.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index f6ade6c..5059900 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_http.c include file.
  *
- * Version:     $Id: check_http.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_http.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Jan Holmberg, <jan@artech.net>
index 9aaf6a2..d4c7d22 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_tcp.c include file.
  *
- * Version:     $Id: check_tcp.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: check_tcp.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 93b8834..749d5fa 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Daemon process handling.
  *
- * Version:     $Id: daemon.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: daemon.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <signal.h>
 
 /* prototype */
 extern pid_t xdaemon(int, int, int);
-extern void sigchld(int sig);
 extern void *signal_set(int signo, void (*func) (int));
 extern void *signal_ignore(int signo);
+extern void signal_noignore_sigchld(void);
 
 #endif
index c44c0a5..9c7f07b 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Dynamic data structure definition.
  *
- * Version:     $Id: global_data.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: global_data.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 3e2ba1d..d2ed7a3 100644 (file)
@@ -5,7 +5,7 @@
  * 
  * Part:        vrrp_parser.c include file.
  *  
- * Version:     $Id: global_parser.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: global_parser.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 2424a8a..b3d1afb 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipfwwrapper.c include file.
  *
- * Version:     $Id: ipfwwrapper.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: ipfwwrapper.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 7556db6..d8f5aad 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipvswrapper.c include file.
  *
- * Version:     $Id: ipvswrapper.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: ipvswrapper.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index b8ce309..1e8dcb6 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipwrapper.c include file.
  *
- * Version:     $Id: ipwrapper.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: ipwrapper.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 2bf44cb..45fe021 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        layer4.c include file.
  *
- * Version:     $Id: layer4.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: layer4.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 6273b4c..6f15050 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Main program include file.
  *
- * Version:     $Id: main.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: main.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -46,13 +46,15 @@ int reload = 0;                             /* Global reloading flag */
 unsigned int debug;                    /* Debugging flags */
 pid_t vrrp_child = -1;                 /* VRRP child process ID */
 pid_t checkers_child = -1;             /* Healthcheckers child process ID */
+int wdog_delay_vrrp = 0;               /* VRRP child polling delay */
+int wdog_delay_check = 0;              /* Healthchecker child polling delay */
 conf_data *data;                       /* Global configuration data */
 
 /* Build version */
 #define PROG    "Keepalived"
 
-#define VERSION_CODE 0x010003
-#define DATE_CODE    0x0C0503
+#define VERSION_CODE 0x010100
+#define DATE_CODE    0x140703
 
 #define KEEPALIVED_VERSION(version)    \
        (version >> 16) & 0xFF,         \
index 73947f8..8f0de7d 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        pidfile.c include file.
  *
- * Version:     $Id: pidfile.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: pidfile.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index d758ab6..0195cc0 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        smtp.c include file.
  *
- * Version:     $Id: smtp.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: smtp.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -35,8 +35,8 @@
 
 /* global defs */
 #define SMTP_PORT              25
-#define SMTP_BUFFER_LENGTH     128
-#define SMTP_BUFFER_MAX                256
+#define SMTP_BUFFER_LENGTH     512
+#define SMTP_BUFFER_MAX                1024
 #define SMTP_MAX_FSM_STATE     10
 
 /* SMTP command stage */
index 8d5d818..e48ce1f 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Part:        vrrp.c program include file.
  *
- * Version:     $Id: vrrp.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -32,6 +32,7 @@
 #include "vrrp_iproute.h"
 #include "vrrp_ipsecah.h"
 #include "vrrp_if.h"
+#include "vrrp_track.h"
 #include "timer.h"
 #include "utils.h"
 #include "vector.h"
@@ -72,6 +73,7 @@ typedef struct {              /* rfc2338.5.1 */
 typedef struct _vrrp_sgroup {
        char *gname;            /* Group name */
        vector iname;           /* Set of VRRP instances in this group */
+       list index;             /* List of VRRP instances */
        int state;              /* current stable state */
 
        /* State transition notification */
@@ -85,9 +87,9 @@ typedef struct _vrrp_sgroup {
 /* parameters per virtual router -- rfc2338.6.1.2 */
 typedef struct _vrrp_rt {
        char *iname;            /* Instance Name */
-       vrrp_sgroup *sync;
+       vrrp_sgroup *sync;      /* Sync group we belong to */
        interface *ifp;         /* Interface we belong to */
-       interface *track_ifp;   /* Interface state we monitor */
+       list track_ifp;         /* Interface state we monitor */
        uint32_t mcast_saddr;   /* Src IP address to use in VRRP IP header */
        char *lvs_syncd_if;     /* handle LVS sync daemon state using this
                                 * instance FSM & running on specific interface
@@ -108,7 +110,8 @@ typedef struct _vrrp_rt {
        int state;              /* internal state (init/backup/master) */
        int init_state;         /* the initial state of the instance */
        int wantstate;          /* user explicitly wants a state (back/mast) */
-       int fd;                 /* the socket descriptor */
+       int fd_in;              /* IN socket descriptor */
+       int fd_out;             /* OUT socket descriptor */
 
        int debug;              /* Debug level 0-4 */
 
@@ -123,6 +126,10 @@ typedef struct _vrrp_rt {
        uint32_t ms_down_timer;
        struct timeval sands;
 
+       /* Sending buffer */
+       char *send_buffer;      /* Allocated send buffer */
+       int send_buffer_size;
+
        /* Authentication data */
        int auth_type;          /* authentification type. VRRP_AUTH_* */
        uint8_t auth_data[8];   /* authentification data */
@@ -161,7 +168,7 @@ typedef struct _vrrp_rt {
 
 /* VRRP Packet fixed lenght */
 #define VRRP_MAX_VIP           20
-#define VRRP_PACKET_TEMP_LEN   512
+#define VRRP_PACKET_TEMP_LEN   1024
 #define VRRP_AUTH_LEN          8
 #define VRRP_VIP_TYPE          (1 << 0)
 #define VRRP_EVIP_TYPE         (1 << 1)
@@ -171,8 +178,10 @@ typedef struct _vrrp_rt {
 #define VRRP_IS_BAD_PRIORITY(p)                ((p)<1 || (p)>255)      /* rfc2338.6.1.prio */
 #define VRRP_IS_BAD_ADVERT_INT(d)      ((d)<1)
 #define VRRP_IS_BAD_DEBUG_INT(d)       ((d)<0 || (d)>4)
+#define VRRP_SEND_BUFFER(V)            ((V)->send_buffer)
+#define VRRP_SEND_BUFFER_SIZE(V)       ((V)->send_buffer_size)
 
-#define VRRP_TIMER_SKEW(srv)   ((256-(srv)->priority)*TIMER_HZ/256)
+#define VRRP_TIMER_SKEW(svr)   ((256-(svr)->priority)*TIMER_HZ/256)
 #define VRRP_VIP_ISSET(V)      ((V)->vipset)
 
 #define VRRP_MIN(a, b) ((a) < (b)?(a):(b))
@@ -180,9 +189,11 @@ typedef struct _vrrp_rt {
 
 #define VRRP_PKT_SADDR(V) (((V)->mcast_saddr) ? (V)->mcast_saddr : IF_ADDR((V)->ifp))
 
-#define VRRP_ISUP(V)   (IF_ISUP((V)->ifp) & (((V)->track_ifp) ? IF_ISUP((V)->track_ifp) : 1))
+#define VRRP_ISUP(V)   (IF_ISUP((V)->ifp) & \
+                       ((!LIST_ISEMPTY((V)->track_ifp)) ? TRACK_ISUP((V)->track_ifp) : 1))
 
 /* prototypes */
+extern int open_vrrp_send_socket(const int proto, const int index);
 extern int open_vrrp_socket(const int proto, const int index);
 extern int new_vrrp_socket(vrrp_rt * vrrp);
 extern void close_vrrp_socket(vrrp_rt * vrrp);
index ff5c331..4ab774c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_arp.c include file.
  *
- * Version:     $Id: vrrp_arp.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_arp.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -29,6 +29,7 @@
 
 /* local includes */
 #include "vrrp.h"
+#include "vrrp_ipaddress.h"
 
 /* local definitions */
 #define ETHERNET_HW_LEN                6
@@ -49,7 +50,13 @@ typedef struct _m_arphdr {
        unsigned char __ar_tip[4];              /* Target IP address.  */
 } m_arphdr;
 
+/* Global var */
+char *garp_buffer;
+int garp_fd;
+
 /* prototypes */
-extern int send_gratuitous_arp(vrrp_rt * vrrp, int addr);
+extern void gratuitous_arp_init(void);
+extern void gratuitous_arp_close(void);
+extern int send_gratuitous_arp(ip_address *ipaddress);
 
 #endif
index 56dfd59..fef7fdc 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_daemon.c include file.
  * 
- * Version:     $Id: vrrp_daemon.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_daemon.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
index abad107..5cb223e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Dynamic data structure definition.
  *
- * Version:     $Id: vrrp_data.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_data.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 
 /* Configuration data root */
 typedef struct _vrrp_conf_data {
+       list static_addresses;
        list static_routes;
        list vrrp_sync_group;
        list vrrp;
+       list vrrp_index;
+       list vrrp_index_fd;
 } vrrp_conf_data;
 
+/* Global Vars */
+char *vrrp_buffer;
+
 /* prototypes */
+extern void alloc_saddress(vector strvec);
 extern void alloc_sroute(vector strvec);
 extern void alloc_vrrp_sync_group(char *gname);
 extern void alloc_vrrp(char *iname);
+extern void alloc_vrrp_track(vector strvec);
 extern void alloc_vrrp_vip(vector strvec);
 extern void alloc_vrrp_evip(vector strvec);
 extern void alloc_vrrp_vroute(vector strvec);
index 5e05c67..d0d3bf7 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_if.c include file.
  *
- * Version:     $Id: vrrp_if.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_if.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
diff --git a/keepalived/include/vrrp_index.h b/keepalived/include/vrrp_index.h
new file mode 100644 (file)
index 0000000..f7fee2e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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_index.c include file.
+ *
+ * Version:     $Id: vrrp_index.h,v 1.1.0 2003/07/20 23:41:34 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_INDEX_H
+#define _VRRP_INDEX_H
+
+/* global includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <syslog.h>
+
+/* local includes */
+#include "vrrp.h"
+
+/* Macro definition */
+
+/* prototypes */
+extern void alloc_vrrp_bucket(vrrp_rt *vrrp);
+extern void alloc_vrrp_fd_bucket(vrrp_rt *vrrp);
+extern void remove_vrrp_fd_bucket(vrrp_rt *vrrp);
+extern void set_vrrp_fd_bucket(int old_fd, vrrp_rt *vrrp);
+extern vrrp_rt *vrrp_index_lookup(const int vrid, const int fd);
+
+#endif
index c4f0ac0..253448f 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_ipaddress.c include file.
  *
- * Version:     $Id: vrrp_ipaddress.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_ipaddress.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -31,6 +31,7 @@
 #include <syslog.h>
 
 /* local includes */
+#include "vrrp_if.h"
 #include "list.h"
 #include "vector.h"
 
 typedef struct {
        uint32_t addr;          /* the ip address */
        uint8_t mask;           /* the ip address CIDR netmask */
-       int ifindex;            /* Interface owning IP address */
+       interface *ifp;         /* Interface owning IP address */
        int scope;              /* the ip address scope */
        int set;                /* TRUE if addr is set */
 } ip_address;
 
 #define IPADDRESS_DEL 0
 #define IPADDRESS_ADD 1
+#define DFLT_INT       "eth0"
 
 /* Macro definition */
-#define IP_ISEQ(X,Y)   ((X)->addr    == (Y)->addr && \
-                       (X)->mask    == (Y)->mask && \
-                       (X)->ifindex == (Y)->ifindex && \
-                       (X)->scope   == (Y)->scope)
+#define IP_ISEQ(X,Y)   ((X)->addr          == (Y)->addr && \
+                       (X)->mask          == (Y)->mask && \
+                       IF_INDEX((X)->ifp) == IF_INDEX((Y)->ifp) && \
+                       (X)->scope         == (Y)->scope)
 
 /* prototypes */
 extern int netlink_address_ipv4(ip_address *ipaddr, int cmd);
 extern void netlink_iplist_ipv4(list ip_list, int cmd);
 extern void free_ipaddress(void *data);
 extern void dump_ipaddress(void *data);
-extern void alloc_ipaddress(list ip_list, vector strvec, int ifindex);
+extern void alloc_ipaddress(list ip_list, vector strvec, interface *ifp);
 extern void clear_diff_address(list l, list n);
+extern void clear_diff_saddresses(void);
 
 #endif
index 7f75c7a..bb4cda5 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_iproute.c include file.
  *
- * Version:     $Id: vrrp_iproute.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_iproute.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -59,8 +59,8 @@ typedef struct _ip_route {
 /* prototypes */
 extern int netlink_route_ipv4(ip_route *iproute, int cmd);
 extern void netlink_rtlist_ipv4(list rt_list, int cmd);
-extern void free_route(void *data);
-extern void dump_route(void *data);
+extern void free_iproute(void *data);
+extern void dump_iproute(void *data);
 extern void alloc_route(list rt_list, vector strvec);
 extern void clear_diff_routes(list l, list n);
 extern void clear_diff_sroutes(void);
index a32d00a..d25eef1 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_ipsecah.c include file.
  * 
- * Version:     $Id: vrrp_ipsecah.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_ipsecah.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
index f5eec31..179c8ec 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_netlink.c include file.
  *
- * Version:     $Id: vrrp_netlink.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_netlink.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -43,8 +43,9 @@ struct nl_handle {
 /* Define types */
 #define NETLINK_TIMER 30
 
-/* Our global netlink reflection handler */
-struct nl_handle nl_kernel;
+/* Our global netlink handler */
+struct nl_handle nl_kernel;    /* Kernel reflection channel */
+struct nl_handle nl_cmd;       /* Command channel */
 
 /* prototypes */
 extern int addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data);
index b0b8519..39a7c0c 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Part:        vrrp_notify.c include file.
  *
- * Version:     $Id: vrrp_notify.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_notify.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index ecca214..244c950 100644 (file)
@@ -5,7 +5,7 @@
  * 
  * Part:        vrrp_parser.c include file.
  *  
- * Version:     $Id: vrrp_parser.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_parser.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 1913adf..bd30cb6 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_scheduler.c include file.
  * 
- * Version:     $Id: vrrp_scheduler.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_scheduler.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
@@ -41,7 +41,8 @@
 typedef struct {
        int ifindex;
        int proto;
-       int fd;
+       int fd_in;
+       int fd_out;
 } sock;
 
 /* VRRP FSM Macro */
index a4428ad..71b99d3 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_sync.c include file.
  * 
- * Version:     $Id: vrrp_sync.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_sync.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
@@ -42,7 +42,6 @@
 
 /* extern prototypes */
 extern void vrrp_init_instance_sands(vrrp_rt *);
-extern vrrp_sgroup *vrrp_get_sync_group(char *);
 extern void vrrp_sync_set_group(vrrp_sgroup *);
 extern int vrrp_sync_group_up(vrrp_sgroup *);
 extern int vrrp_sync_leave_fault(vrrp_rt *);
diff --git a/keepalived/include/vrrp_track.h b/keepalived/include/vrrp_track.h
new file mode 100644 (file)
index 0000000..d472da7
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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_track.c include file.
+ *
+ * Version:     $Id: vrrp_track.h,v 1.1.0 2003/07/20 23:41:34 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_TRACK_H
+#define _VRRP_TRACK_H
+
+/* global includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <syslog.h>
+
+/* local includes */
+#include "vector.h"
+#include "list.h"
+
+/* Macro definition */
+#define TRACK_ISUP(L)  (vrrp_tracked_up((L)))
+
+/* prototypes */
+extern void dump_track(void *data);
+extern void alloc_track(list track_list, vector strvec);
+extern int vrrp_tracked_up(list l);
+extern void vrrp_log_tracked_down(list l);
+
+#endif
diff --git a/keepalived/libipvs/Makefile b/keepalived/libipvs/Makefile
deleted file mode 100644 (file)
index 52eb277..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-# Generated automatically from Makefile.in by configure.
-# Makefile to make libipvsc.
-
-CC     = gcc
-CFLAGS = -g -O2 -I/usr/src/linux/include -Wall -Wunused
-
-export OBJS += libipvs.a
-
-all: libipvs.a
-
-libipvs.a: libipvs.a(libipvs.o)
-
-libipvsc.o: libipvs.h
-
-clean:
-       rm -f *.a *.o *~
-
-distclean: clean
-       rm -f Makefile
index 8251af3..7c7a47e 100644 (file)
@@ -12,8 +12,9 @@ DEFS   = -D@KERN@ -D@IPVS_SUPPORT@ -D@IPVS_SYNCD@ @DFLAGS@
 COMPILE         = $(CC) $(CFLAGS) $(DEFS)
 
 OBJS =         vrrp_daemon.o vrrp_data.o vrrp_parser.o \
-       vrrp.o vrrp_notify.o vrrp_scheduler.o vrrp_sync.o vrrp_netlink.o \
-       vrrp_arp.o vrrp_if.o vrrp_ipaddress.o vrrp_iproute.o vrrp_ipsecah.o
+       vrrp.o vrrp_notify.o vrrp_scheduler.o vrrp_sync.o vrrp_index.o \
+       vrrp_netlink.o vrrp_arp.o vrrp_if.o vrrp_track.o vrrp_ipaddress.o \
+       vrrp_iproute.o vrrp_ipsecah.o
 HEADERS = $(OBJS:.o=.h)
 
 .c.o:
@@ -28,37 +29,43 @@ distclean: clean
        rm -f Makefile
 
 vrrp_daemon.o: vrrp_daemon.c ../include/vrrp_daemon.h ../include/vrrp_scheduler.h \
-  ../include/vrrp_if.h ../include/vrrp_netlink.h ../include/vrrp_iproute.h \
-  ../include/vrrp_parser.h ../include/vrrp_data.h ../include/vrrp.h \
-  ../include/global_data.h ../include/pidfile.h ../include/daemon.h \
+  ../include/vrrp_if.h ../include/vrrp_arp.h ../include/vrrp_netlink.h ../include/vrrp_iproute.h \
+  ../include/vrrp_iproute.h ../include/vrrp_parser.h ../include/vrrp_data.h \
+  ../include/vrrp.h ../include/global_data.h ../include/pidfile.h ../include/daemon.h \
   ../../lib/list.h ../../lib/memory.h ../../lib/parser.h ../../lib/watchdog.h
 vrrp_data.o: vrrp_data.c ../include/vrrp_data.h \
-  ../include/vrrp_sync.h ../include/vrrp.h ../../lib/memory.h \
+  ../include/vrrp_sync.h ../include/vrrp_index.h ../include/vrrp.h ../../lib/memory.h \
   ../../lib/utils.h
 vrrp_parser.o: vrrp_parser.c ../include/vrrp_parser.h \
-  ../include/vrrp_data.h ../include/vrrp_sync.h ../include/vrrp.h \
-  ../include/global_data.h ../include/global_parser.h \
+  ../include/vrrp_data.h ../include/vrrp_sync.h ../include/vrrp_index.h \
+  ../include/vrrp.h ../include/global_data.h ../include/global_parser.h \
   ../../lib/parser.h ../../lib/memory.h
 vrrp.o: vrrp.c ../include/vrrp.h ../include/vrrp_scheduler.h \
   ../include/vrrp_notify.h ../include/ipvswrapper.h ../../lib/memory.h \
-  ../../lib/list.h ../include/vrrp_data.h ../include/vrrp_arp.h
+  ../../lib/list.h ../include/vrrp_data.h ../include/vrrp_sync.h ../include/vrrp_index.h \
+  ../include/vrrp_arp.h
 vrrp_notify.o: vrrp_notify.c ../include/vrrp_notify.h ../../lib/memory.h \
   ../../lib/notify.h
 vrrp_scheduler.o: vrrp_scheduler.c ../include/vrrp_scheduler.h \
   ../include/vrrp_ipsecah.h ../include/vrrp_if.h ../include/vrrp.h \
   ../include/vrrp_sync.h ../include/vrrp_notify.h ../include/ipvswrapper.h \
-  ../../lib/memory.h ../../lib/list.h ../include/vrrp_data.h ../include/smtp.h
+  ../../lib/memory.h ../../lib/list.h ../include/vrrp_data.h ../include/vrrp_index.h \
+  ../include/smtp.h
 vrrp_sync.o: vrrp_sync.c ../include/vrrp_sync.h ../include/vrrp_if.h \
   ../include/vrrp_notify.h ../include/vrrp_data.h
+vrrp_index.o: vrrp_index.c ../include/vrrp_index.h ../include/vrrp.h \
+  ../include/vrrp_data.h ../../lib/memory.h
 vrrp_netlink.o: vrrp_netlink.c ../include/vrrp_netlink.h ../include/check_api.h \
   ../include/vrrp_if.h ../../lib/memory.h ../../lib/scheduler.h \
   ../../lib/utils.h
 vrrp_arp.o: vrrp_arp.c ../include/vrrp_arp.h
+vrrp_track.o: vrrp_track.c ../include/vrrp_track.h ../include/vrrp_if.h \
+  ../include/vrrp_data.h ../../lib/memory.h
 vrrp_if.o: vrrp_if.c ../include/vrrp_if.h ../include/vrrp_netlink.h \
   ../../lib/scheduler.h ../include/vrrp_data.h ../../lib/memory.h \
   ../../lib/utils.h
-vrrp_ipaddress.o: vrrp_ipaddress.c ../include/vrrp_ipaddress.h \
-  ../include/vrrp_netlink.h ../../lib/utils.h
-vrrp_iproute.o: vrrp_iproute.c ../include/vrrp_iproute.h \
-  ../include/vrrp_netlink.h ../../lib/utils.h
+vrrp_ipaddress.o: vrrp_ipaddress.c ../include/vrrp_ipaddress.h ../include/vrrp_netlink.h \
+  ../include/vrrp_if.h  ../include/vrrp_data.h ../../lib/memory.h ../../lib/utils.h
+vrrp_iproute.o: vrrp_iproute.c ../include/vrrp_iproute.h ../include/vrrp_netlink.h \
+ ../include/vrrp_if.h  ../include/vrrp_data.h ../../lib/memory.h ../../lib/utils.h
 vrrp_ipsecah.o: vrrp_ipsecah.c ../include/vrrp_ipsecah.h
index 224e9aa..038c829 100644 (file)
@@ -8,7 +8,7 @@
  *              master fails, a backup server takes over.
  *              The original implementation has been made by jerome etienne.
  *
- * Version:     $Id: vrrp.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include "ipvswrapper.h"
 #include "vrrp.h"
 #include "vrrp_data.h"
+#include "vrrp_sync.h"
+#include "vrrp_index.h"
 #include "memory.h"
 #include "list.h"
 
 /* extern global vars */
 extern vrrp_conf_data *vrrp_data;
 extern vrrp_conf_data *old_vrrp_data;
+extern unsigned int debug;
 
 /* compute checksum */
 static u_short
@@ -76,9 +79,10 @@ in_csum(u_short * addr, int len, u_short csum)
 static int
 vrrp_handle_ipaddress(vrrp_rt * vrrp, int cmd, int type)
 {
-       syslog(LOG_INFO, "VRRP_Instance(%s) %s protocol %s", vrrp->iname,
-              (cmd == IPADDRESS_ADD) ? "setting" : "removing",
-              (type == VRRP_VIP_TYPE) ? "VIPs." : "E-VIPs");
+       if (debug & 32)
+               syslog(LOG_INFO, "VRRP_Instance(%s) %s protocol %s", vrrp->iname,
+                      (cmd == IPADDRESS_ADD) ? "setting" : "removing",
+                      (type == VRRP_VIP_TYPE) ? "VIPs." : "E-VIPs.");
        netlink_iplist_ipv4((type == VRRP_VIP_TYPE) ? vrrp->vip : vrrp->evip
                            , cmd);
        return 1;
@@ -88,9 +92,10 @@ vrrp_handle_ipaddress(vrrp_rt * vrrp, int cmd, int type)
 static int
 vrrp_handle_iproutes(vrrp_rt * vrrp, int cmd)
 {
-       syslog(LOG_INFO, "VRRP_Instance(%s) %s protocol Virtual Routes",
-              vrrp->iname,
-              (cmd == IPROUTE_ADD) ? "setting" : "removing");
+       if (debug & 32)
+               syslog(LOG_INFO, "VRRP_Instance(%s) %s protocol Virtual Routes",
+                      vrrp->iname,
+                      (cmd == IPROUTE_ADD) ? "setting" : "removing");
        netlink_rtlist_ipv4(vrrp->vroutes, cmd);
        return 1;
 }
@@ -113,9 +118,9 @@ vrrp_ipsecah_len(void)
 static int
 vrrp_hd_len(vrrp_rt * vrrp)
 {
-       return sizeof (vrrp_pkt)
-           + LIST_SIZE(vrrp->vip) * sizeof (uint32_t)
-           + VRRP_AUTH_LEN;
+       int len = sizeof (vrrp_pkt) + VRRP_AUTH_LEN;
+        return (!LIST_ISEMPTY(vrrp->vip)) ?
+               len + LIST_SIZE(vrrp->vip) * sizeof (uint32_t) : len;
 }
 
 /*
@@ -286,17 +291,17 @@ vrrp_in_chk(vrrp_rt * vrrp, char *buffer)
                return VRRP_PACKET_DROP;
        }
 
-       /*
-        * MAY verify that the IP address(es) associated with the
-        * VRID are valid
-        */
-       if (hd->naddr != LIST_SIZE(vrrp->vip)) {
-               syslog(LOG_INFO,
-                      "receive an invalid ip number count associated with VRID!");
-               return VRRP_PACKET_KO;
-       }
+       if (!LIST_ISEMPTY(vrrp->vip)) {
+               /*
+                * MAY verify that the IP address(es) associated with the
+                * VRID are valid
+                */
+               if (hd->naddr != LIST_SIZE(vrrp->vip)) {
+                       syslog(LOG_INFO,
+                              "receive an invalid ip number count associated with VRID!");
+                       return VRRP_PACKET_KO;
+               }
 
-       if (!LIST_ISEMPTY(vrrp->vip))
                for (e = LIST_HEAD(vrrp->vip); e; ELEMENT_NEXT(e)) {
                        ipaddress = ELEMENT_DATA(e);
                        if (!vrrp_in_chk_vips(vrrp, ipaddress->addr, vips)) {
@@ -309,6 +314,11 @@ vrrp_in_chk(vrrp_rt * vrrp, char *buffer)
                                return VRRP_PACKET_KO;
                        }
                }
+       } else if (hd->naddr > 0) {
+               syslog(LOG_INFO,
+                      "receive an invalid ip number count associated with VRID!");
+               return VRRP_PACKET_KO;
+       }
 
        /*
         * MUST verify that the Adver Interval in the packet is the same as
@@ -456,7 +466,7 @@ vrrp_build_vrrp(vrrp_rt * vrrp, int prio, char *buffer, int buflen)
        hd->vers_type = (VRRP_VERSION << 4) | VRRP_PKT_ADVERT;
        hd->vrid = vrrp->vrid;
        hd->priority = prio;
-       hd->naddr = LIST_SIZE(vrrp->vip);
+       hd->naddr = (!LIST_ISEMPTY(vrrp->vip)) ? LIST_SIZE(vrrp->vip) : 0;
        hd->auth_type = vrrp->auth_type;
        hd->adver_int = vrrp->adver_int / TIMER_HZ;
 
@@ -469,7 +479,8 @@ vrrp_build_vrrp(vrrp_rt * vrrp, int prio, char *buffer, int buflen)
 
        /* copy the passwd if the authentication is VRRP_AH_PASS */
        if (vrrp->auth_type == VRRP_AUTH_PASS) {
-               char *pw = (char *) hd + sizeof (*hd) + LIST_SIZE(vrrp->vip) * 4;
+               int vip_count = (!LIST_ISEMPTY(vrrp->vip)) ? LIST_SIZE(vrrp->vip) : 0;
+               char *pw = (char *) hd + sizeof (*hd) + vip_count * 4;
                memcpy(pw, vrrp->auth_data, sizeof (vrrp->auth_data));
        }
 
@@ -481,50 +492,47 @@ vrrp_build_vrrp(vrrp_rt * vrrp, int prio, char *buffer, int buflen)
 
 /* build VRRP packet */
 static void
-vrrp_build_pkt(vrrp_rt * vrrp, int prio, char *buffer, int buflen)
+vrrp_build_pkt(vrrp_rt * vrrp, int prio)
 {
        char *bufptr;
+       int len;
 
-       bufptr = buffer;
+       /* save reference values */
+       bufptr = VRRP_SEND_BUFFER(vrrp);
+       len = VRRP_SEND_BUFFER_SIZE(vrrp);
 
        /* build the ip header */
-       vrrp_build_ip(vrrp, buffer, buflen);
+       vrrp_build_ip(vrrp, VRRP_SEND_BUFFER(vrrp), VRRP_SEND_BUFFER_SIZE(vrrp));
 
        /* build the vrrp header */
-       buffer += vrrp_iphdr_len(vrrp);
+       vrrp->send_buffer += vrrp_iphdr_len(vrrp);
 
        if (vrrp->auth_type == VRRP_AUTH_AH)
-               buffer += vrrp_ipsecah_len();
-       buflen -= vrrp_iphdr_len(vrrp);
+               vrrp->send_buffer += vrrp_ipsecah_len();
+       vrrp->send_buffer_size -= vrrp_iphdr_len(vrrp);
 
        if (vrrp->auth_type == VRRP_AUTH_AH)
-               buflen -= vrrp_ipsecah_len();
-       vrrp_build_vrrp(vrrp, prio, buffer, buflen);
+               vrrp->send_buffer_size -= vrrp_ipsecah_len();
+       vrrp_build_vrrp(vrrp, prio, vrrp->send_buffer, vrrp->send_buffer_size);
 
        /* build the IPSEC AH header */
        if (vrrp->auth_type == VRRP_AUTH_AH) {
-               buflen += vrrp_iphdr_len(vrrp) + vrrp_ipsecah_len();
-               vrrp_build_ipsecah(vrrp, bufptr, buflen);
+               vrrp->send_buffer_size += vrrp_iphdr_len(vrrp) + vrrp_ipsecah_len();
+               vrrp_build_ipsecah(vrrp, bufptr, VRRP_SEND_BUFFER_SIZE(vrrp));
        }
+
+       /* restore reference values */
+       vrrp->send_buffer = bufptr;
+       vrrp->send_buffer_size = len;
 }
 
 /* send VRRP packet */
 static int
-vrrp_send_pkt(vrrp_rt * vrrp, char *buffer, int buflen)
+vrrp_send_pkt(vrrp_rt * vrrp)
 {
        struct sockaddr_in dst;
        struct msghdr msg;
        struct iovec iov;
-       int fd;
-       int ret;
-
-       /* Create and init socket descriptor */
-       fd = socket(AF_INET
-                   , SOCK_RAW
-                   , (vrrp->auth_type == VRRP_AUTH_AH) ? IPPROTO_IPSEC_AH : IPPROTO_VRRP);
-       if_setsockopt_hdrincl(fd);
-       if_setsockopt_bindtodevice(fd, vrrp->ifp);
-       if_setsockopt_mcast_loop(fd);
 
        /* Sending path */
        memset(&dst, 0, sizeof(dst));
@@ -538,39 +546,38 @@ vrrp_send_pkt(vrrp_rt * vrrp, char *buffer, int buflen)
        msg.msg_namelen = sizeof(dst);
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
-       iov.iov_base = buffer;
-       iov.iov_len = buflen;
+       iov.iov_base = VRRP_SEND_BUFFER(vrrp);
+       iov.iov_len = VRRP_SEND_BUFFER_SIZE(vrrp);
 
        /* Send the packet */
-       ret = sendmsg(fd, &msg, MSG_DONTROUTE);
+       return sendmsg(vrrp->fd_out, &msg, MSG_DONTROUTE);
+}
 
-       close(fd);
-       return 0;
+/* Allocate the sending buffer */
+static void
+vrrp_alloc_send_buffer(vrrp_rt * vrrp)
+{
+       vrrp->send_buffer_size = vrrp_iphdr_len(vrrp) + vrrp_hd_len(vrrp);
+       if (vrrp->auth_type == VRRP_AUTH_AH)
+               vrrp->send_buffer_size += vrrp_ipsecah_len();
+       vrrp->send_buffer = MALLOC(VRRP_SEND_BUFFER_SIZE(vrrp));
 }
 
 /* send VRRP advertissement */
 int
 vrrp_send_adv(vrrp_rt * vrrp, int prio)
 {
-       int buflen, ret;
-       char *buffer;
-
-       /* alloc the memory */
-       buflen = vrrp_iphdr_len(vrrp) + vrrp_hd_len(vrrp);
-       if (vrrp->auth_type == VRRP_AUTH_AH)
-               buflen += vrrp_ipsecah_len();
-
-       buffer = MALLOC(buflen);
+       /* alloc send buffer */
+       if (!vrrp->send_buffer)
+               vrrp_alloc_send_buffer(vrrp);
+       else
+               memset(vrrp->send_buffer, 0, VRRP_SEND_BUFFER_SIZE(vrrp));
 
-       /* build the packet  */
-       vrrp_build_pkt(vrrp, prio, buffer, buflen);
+       /* build the packet */
+       vrrp_build_pkt(vrrp, prio);
 
        /* send it */
-       ret = vrrp_send_pkt(vrrp, buffer, buflen);
-
-       /* free the memory */
-       FREE(buffer);
-       return ret;
+       return vrrp_send_pkt(vrrp);
 }
 
 /* Received packet processing */
@@ -609,19 +616,20 @@ vrrp_send_gratuitous_arp(vrrp_rt * vrrp)
                return;
 
        /* send gratuitous arp for each virtual ip */
-       syslog(LOG_INFO, "VRRP_Instance(%s) Sending gratuitous ARP on %s",
-              vrrp->iname, IF_NAME(vrrp->ifp));
+       if (debug & 32)
+               syslog(LOG_INFO, "VRRP_Instance(%s) Sending gratuitous ARP on %s",
+                      vrrp->iname, IF_NAME(vrrp->ifp));
 
        for (j = 0; j < 5; j++) {
                if (!LIST_ISEMPTY(vrrp->vip))
                        for (e = LIST_HEAD(vrrp->vip); e; ELEMENT_NEXT(e)) {
                                ipaddress = ELEMENT_DATA(e);
-                               send_gratuitous_arp(vrrp, ipaddress->addr);
+                               send_gratuitous_arp(ipaddress);
                        }
                if (!LIST_ISEMPTY(vrrp->evip))
                        for (e = LIST_HEAD(vrrp->evip); e; ELEMENT_NEXT(e)) {
                                ipaddress = ELEMENT_DATA(e);
-                               send_gratuitous_arp(vrrp, ipaddress->addr);
+                               send_gratuitous_arp(ipaddress);
                        }
        }
 }
@@ -918,7 +926,34 @@ chk_min_cfg(vrrp_rt * vrrp)
        return 1;
 }
 
-/* open the socket and join the multicast group. */
+/* open a VRRP sending socket */
+int
+open_vrrp_send_socket(const int proto, const int index)
+{
+       interface *ifp;
+       int fd = -1;
+
+       /* Retreive interface */
+       ifp = if_get_by_ifindex(index);
+
+       /* Create and init socket descriptor */
+       fd = socket(AF_INET, SOCK_RAW, proto);
+       if (fd < 0) {
+               int err = errno;
+               syslog(LOG_INFO, "cant open raw socket. errno=%d",
+                      err);
+               return -1;
+       }
+
+       /* Set fd */
+       if_setsockopt_hdrincl(fd);
+       if_setsockopt_bindtodevice(fd, ifp);
+       if_setsockopt_mcast_loop(fd);
+
+       return fd;
+}
+
+/* open a VRRP socket and join the multicast group. */
 int
 open_vrrp_socket(const int proto, const int index)
 {
@@ -936,8 +971,7 @@ open_vrrp_socket(const int proto, const int index)
        fd = socket(AF_INET, SOCK_RAW, proto);
        if (fd < 0) {
                int err = errno;
-               syslog(LOG_INFO,
-                      "cant open raw socket. errno=%d. (try to run it as root)",
+               syslog(LOG_INFO, "cant open raw socket. errno=%d",
                       err);
                return -1;
        }
@@ -954,33 +988,28 @@ open_vrrp_socket(const int proto, const int index)
 void
 close_vrrp_socket(vrrp_rt * vrrp)
 {
-       if_leave_vrrp_group(vrrp->fd, vrrp->ifp);
+       if_leave_vrrp_group(vrrp->fd_in, vrrp->ifp);
+       close(vrrp->fd_out);
 }
 
 int
 new_vrrp_socket(vrrp_rt * vrrp)
 {
-       int old_fd = vrrp->fd;
-       list p = vrrp_data->vrrp;
-       vrrp_rt *vrrp_ptr;
-       element e;
+       int old_fd = vrrp->fd_in;
+       int proto;
 
        /* 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));
+       remove_vrrp_fd_bucket(vrrp);
+       proto = (vrrp->auth_type == VRRP_AUTH_AH) ? IPPROTO_IPSEC_AH : IPPROTO_VRRP;
+       vrrp->fd_in = open_vrrp_socket(proto, IF_INDEX(vrrp->ifp));
+       vrrp->fd_out = open_vrrp_send_socket(proto, IF_INDEX(vrrp->ifp));
+       alloc_vrrp_fd_bucket(vrrp);
 
        /* 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;
-       }
+       set_vrrp_fd_bucket(old_fd, vrrp);
 
-       return vrrp->fd;
+       return vrrp->fd_in;
 }
 
 /* handle terminate state */
@@ -1024,15 +1053,26 @@ vrrp_complete_instance(vrrp_rt * vrrp)
 int
 vrrp_complete_init(void)
 {
-       list l = vrrp_data->vrrp;
+       list l;
        element e;
        vrrp_rt *vrrp;
+       vrrp_sgroup *sgroup;
 
+       /* Complete VRRP instance initialization */
+       l = vrrp_data->vrrp;
        for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
                vrrp = ELEMENT_DATA(e);
                if (!vrrp_complete_instance(vrrp))
                        return 0;
        }
+
+       /* Build synchronization group index */
+       l = vrrp_data->vrrp_sync_group;
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               sgroup = ELEMENT_DATA(e);
+               vrrp_sync_set_group(sgroup);
+       }
+
        return 1;
 }
 
index c183322..2100ce5 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ARP primitives.
  *
- * Version:     $Id: vrrp_arp.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_arp.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include "memory.h"
 #include "utils.h"
 
-/* Send the gratuitous ARP message */
-static int send_arp(vrrp_rt *vrrp, char *buffer, int buflen)
+/* Make shared socket */
+void gratuitous_arp_init(void)
 {
-       int fd;
-       int len;
-       struct sockaddr_ll sll;
+       /* Initalize shared buffer */
+       garp_buffer = (char *)MALLOC(sizeof(m_arphdr) + ETHER_HDR_LEN);
 
        /* Create the socket descriptor */
-       fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_RARP));
+       garp_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_RARP));
+
+       if (garp_fd > 0)
+               syslog(LOG_INFO, "Registering gratutious ARP shared channel");
+       else
+               syslog(LOG_INFO, "Error while registering gratutious ARP shared channel");
+}
+void gratuitous_arp_close(void)
+{
+       FREE(garp_buffer);
+       close(garp_fd);
+}
+
+/* Send the gratuitous ARP message */
+static int send_arp(ip_address *ipaddress)
+{
+       struct sockaddr_ll sll;
+       int len;
 
        /* Build the dst device */
        memset(&sll, 0, sizeof(sll));
        sll.sll_family = AF_PACKET;
-       strncpy(sll.sll_addr, IF_HWADDR(vrrp->ifp), sizeof(sll.sll_addr));
+       strncpy(sll.sll_addr, IF_HWADDR(ipaddress->ifp), sizeof(sll.sll_addr));
        sll.sll_halen = ETHERNET_HW_LEN;
-       sll.sll_ifindex = IF_INDEX(vrrp->ifp);
+       sll.sll_ifindex = IF_INDEX(ipaddress->ifp);
 
        /* Send packet */
-       len = sendto(fd, buffer, buflen, 0,(struct sockaddr *)&sll, sizeof(sll));
-
-       close(fd);
+       len = sendto(garp_fd, garp_buffer, sizeof(m_arphdr) + ETHER_HDR_LEN
+                    , 0, (struct sockaddr *)&sll, sizeof(sll));
+       if (len < 0)
+               syslog(LOG_INFO, "Error sending gratutious ARP on %s for %s"
+                      , IF_NAME(ipaddress->ifp), inet_ntop2(ipaddress->addr));
        return len;
 }
 
 /* Build a gratuitous ARP message over a specific interface */
-int send_gratuitous_arp(vrrp_rt * vrrp, int addr)
+int send_gratuitous_arp(ip_address *ipaddress)
 {
-       char buflen                     = sizeof(m_arphdr) + ETHER_HDR_LEN;
-       char *buf                       = (char *)MALLOC(buflen);
-       struct ether_header *eth        = (struct ether_header *) buf;
-       m_arphdr *arph                  = (m_arphdr *) (buf + ETHER_HDR_LEN);
-       char *hwaddr                    = IF_HWADDR(vrrp->ifp);
+       struct ether_header *eth = (struct ether_header *) garp_buffer;
+       m_arphdr *arph           = (m_arphdr *) (garp_buffer + ETHER_HDR_LEN);
+       char *hwaddr             = IF_HWADDR(ipaddress->ifp);
        int len;
 
        /* Ethernet header */
@@ -74,12 +90,13 @@ int send_gratuitous_arp(vrrp_rt * vrrp, int addr)
        arph->ar_pln = IPPROTO_ADDR_LEN;
        arph->ar_op = htons(ARPOP_REQUEST);
        memcpy(arph->__ar_sha, hwaddr, ETH_ALEN);
-       memcpy(arph->__ar_sip, &addr, sizeof (addr));
-       memcpy(arph->__ar_tip, &addr, sizeof (addr));
+       memcpy(arph->__ar_sip, &ipaddress->addr, sizeof (ipaddress->addr));
+       memcpy(arph->__ar_tip, &ipaddress->addr, sizeof (ipaddress->addr));
 
        /* Send the ARP message */
-       len = send_arp(vrrp, buf, buflen);
+       len = send_arp(ipaddress);
 
-       FREE(buf);
+       /* Cleanup room for next round */
+       memset(garp_buffer, 0, sizeof(m_arphdr) + ETHER_HDR_LEN);
        return len;
 }
index eb832a3..e07779b 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        VRRP child process handling.
  *
- * Version:     $Id: vrrp_daemon.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_daemon.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -23,7 +23,9 @@
 #include "vrrp_daemon.h"
 #include "vrrp_scheduler.h"
 #include "vrrp_if.h"
+#include "vrrp_arp.h"
 #include "vrrp_netlink.h"
+#include "vrrp_ipaddress.h"
 #include "vrrp_iproute.h"
 #include "vrrp_parser.h"
 #include "vrrp_data.h"
@@ -57,6 +59,7 @@ extern unsigned int debug;
 extern int reload;
 extern pid_t vrrp_child;
 extern char *conf_file;
+extern int wdog_delay_vrrp;
 
 /* Daemon stop sequence */
 static void
@@ -65,12 +68,14 @@ stop_vrrp(void)
        /* Destroy master thread */
        thread_destroy_master(master);
 
-       /* Clear static routes */
+       /* Clear static entries */
+       netlink_iplist_ipv4(vrrp_data->static_addresses, IPADDRESS_DEL);
        netlink_rtlist_ipv4(vrrp_data->static_routes, IPROUTE_DEL);
 
        if (!(debug & 8))
                shutdown_vrrp_instances();
        free_interface_queue();
+       gratuitous_arp_close();
 
        /* Stop daemon */
        pidfile_rm(VRRP_PID_FILE);
@@ -102,6 +107,7 @@ start_vrrp(void)
        init_interface_queue();
        kernel_netlink_init();
        if_mii_poller_init();
+       gratuitous_arp_init();
 
        /* Parse configuration file */
        data = alloc_global_data();
@@ -112,23 +118,25 @@ start_vrrp(void)
                return;
        }
 
-       /* Post initializations */
-       syslog(LOG_INFO, "Configuration is using : %lu Bytes", mem_allocated);
-
        if (reload) {
+               clear_diff_saddresses();
                clear_diff_sroutes();
                clear_diff_vrrp();
        }
 
-       /* Set static routes */
-       netlink_rtlist_ipv4(vrrp_data->static_routes, IPROUTE_ADD);
-
        /* Complete VRRP initialization */
        if (!vrrp_complete_init()) {
                stop_vrrp();
                return;
        }
 
+       /* Post initializations */
+       syslog(LOG_INFO, "Configuration is using : %lu Bytes", mem_allocated);
+
+       /* Set static entries */
+       netlink_iplist_ipv4(vrrp_data->static_addresses, IPADDRESS_ADD);
+       netlink_rtlist_ipv4(vrrp_data->static_routes, IPROUTE_ADD);
+
        /* Dump configuration */
        if (debug & 4) {
                dump_global_data(data);
@@ -152,6 +160,7 @@ reload_vrrp_thread(thread * thread)
        master = thread_make_master();
        free_global_data(data);
        free_interface_queue();
+       gratuitous_arp_close();
 
        /* Save previous conf data */
        old_vrrp_data = vrrp_data;
@@ -192,7 +201,7 @@ vrrp_signal_init(void)
        signal_set(SIGINT, sigend_vrrp);
        signal_set(SIGTERM, sigend_vrrp);
        signal_set(SIGKILL, sigend_vrrp);
-       signal_set(SIGCHLD, sigchld);
+       signal_noignore_sigchld();
 }
 
 /* Register VRRP thread */
@@ -215,13 +224,14 @@ start_vrrp_child(void)
                               , strerror(errno));
                return -1;
        } else if (pid) {
+               int poll_delay = (wdog_delay_vrrp) ? wdog_delay_vrrp : WATCHDOG_DELAY;
                vrrp_child = pid;
                syslog(LOG_INFO, "Starting VRRP child process, pid=%d"
                               , pid);
                /* Connect child watchdog */
                vrrp_wdog_data.wdog_pid = pid;
                thread_add_timer(master, wdog_boot_thread, &vrrp_wdog_data,
-                                WATCHDOG_DELAY);
+                                poll_delay);
                return 0;
        }
 
index d1ad92b..454d1e9 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Dynamic data structure definition.
  *
- * Version:     $Id: vrrp_data.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_data.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -21,6 +21,7 @@
  */
 
 #include "vrrp_data.h"
+#include "vrrp_index.h"
 #include "vrrp_sync.h"
 #include "vrrp.h"
 #include "memory.h"
 /* Externals vars */
 extern vrrp_conf_data *vrrp_data;
 
-/* Static routes facility functions */
+/* Static addresses facility function */
+void
+alloc_saddress(vector strvec)
+{
+       if (LIST_ISEMPTY(vrrp_data->static_addresses))
+               vrrp_data->static_addresses = alloc_list(free_ipaddress, dump_ipaddress);
+       alloc_ipaddress(vrrp_data->static_addresses, strvec, NULL);
+}
+
+/* Static routes facility function */
 void
 alloc_sroute(vector strvec)
 {
        if (LIST_ISEMPTY(vrrp_data->static_routes))
-               vrrp_data->static_routes = alloc_list(free_route, dump_route);
+               vrrp_data->static_routes = alloc_list(free_iproute, dump_iproute);
        alloc_route(vrrp_data->static_routes, strvec);
 }
 
@@ -46,6 +56,7 @@ free_vgroup(void *data)
 
        FREE(vgroup->gname);
        free_strvec(vgroup->iname);
+       free_list(vgroup->index);
        FREE_PTR(vgroup->script_backup);
        FREE_PTR(vgroup->script_master);
        FREE_PTR(vgroup->script_fault);
@@ -83,17 +94,16 @@ free_vrrp(void *data)
        vrrp_rt *vrrp = data;
 
        FREE(vrrp->iname);
+       FREE_PTR(vrrp->send_buffer);
        FREE_PTR(vrrp->lvs_syncd_if);
        FREE_PTR(vrrp->script_backup);
        FREE_PTR(vrrp->script_master);
        FREE_PTR(vrrp->script_fault);
        FREE(vrrp->ipsecah_counter);
-       if (!LIST_ISEMPTY(vrrp->vip))
-               free_list(vrrp->vip);
-       if (!LIST_ISEMPTY(vrrp->evip))
-               free_list(vrrp->evip);
-       if (!LIST_ISEMPTY(vrrp->vroutes))
-               free_list(vrrp->vroutes);
+       free_list(vrrp->track_ifp);
+       free_list(vrrp->vip);
+       free_list(vrrp->evip);
+       free_list(vrrp->vroutes);
        FREE(vrrp);
 }
 static void
@@ -107,9 +117,6 @@ dump_vrrp(void *data)
        else
                syslog(LOG_INFO, "   Want State = MASTER");
        syslog(LOG_INFO, "   Runing on device = %s", IF_NAME(vrrp->ifp));
-       if (vrrp->track_ifp)
-               syslog(LOG_INFO, "   Track interface = %s",
-                      IF_NAME(vrrp->track_ifp));
        if (vrrp->mcast_saddr)
                syslog(LOG_INFO, "   Using mcast src_ip = %s",
                       inet_ntop2(vrrp->mcast_saddr));
@@ -130,6 +137,10 @@ dump_vrrp(void *data)
                        VRRP_AUTH_AH) ? "IPSEC_AH" : "SIMPLE_PASSWORD");
                syslog(LOG_INFO, "   Password = %s", vrrp->auth_data);
        }
+       if (!LIST_ISEMPTY(vrrp->track_ifp)) {
+               syslog(LOG_INFO, "   Tracked interfaces = %d", LIST_SIZE(vrrp->track_ifp));
+               dump_list(vrrp->track_ifp);
+       }
        if (!LIST_ISEMPTY(vrrp->vip)) {
                syslog(LOG_INFO, "   Virtual IP = %d", LIST_SIZE(vrrp->vip));
                dump_list(vrrp->vip);
@@ -190,19 +201,28 @@ alloc_vrrp(char *iname)
        new->adver_int = TIMER_HZ;
        new->iname = (char *) MALLOC(size + 1);
        memcpy(new->iname, iname, size);
-       new->sync = vrrp_get_sync_group(iname);
 
        list_add(vrrp_data->vrrp, new);
 }
 
 void
+alloc_vrrp_track(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
+
+       if (LIST_ISEMPTY(vrrp->track_ifp))
+               vrrp->track_ifp = alloc_list(NULL, dump_track);
+       alloc_track(vrrp->track_ifp, strvec);
+}
+
+void
 alloc_vrrp_vip(vector strvec)
 {
        vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
 
        if (LIST_ISEMPTY(vrrp->vip))
                vrrp->vip = alloc_list(free_ipaddress, dump_ipaddress);
-       alloc_ipaddress(vrrp->vip, strvec, IF_INDEX(vrrp->ifp));
+       alloc_ipaddress(vrrp->vip, strvec, vrrp->ifp);
 }
 void
 alloc_vrrp_evip(vector strvec)
@@ -211,7 +231,7 @@ alloc_vrrp_evip(vector strvec)
 
        if (LIST_ISEMPTY(vrrp->evip))
                vrrp->evip = alloc_list(free_ipaddress, dump_ipaddress);
-       alloc_ipaddress(vrrp->evip, strvec, IF_INDEX(vrrp->ifp));
+       alloc_ipaddress(vrrp->evip, strvec, vrrp->ifp);
 }
 
 void
@@ -220,7 +240,7 @@ alloc_vrrp_vroute(vector strvec)
        vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
 
        if (LIST_ISEMPTY(vrrp->vroutes))
-               vrrp->vroutes = alloc_list(free_route, dump_route);
+               vrrp->vroutes = alloc_list(free_iproute, dump_iproute);
        alloc_route(vrrp->vroutes, strvec);
 }
 
@@ -232,7 +252,10 @@ alloc_vrrp_data(void)
 
        new = (vrrp_conf_data *) MALLOC(sizeof (vrrp_conf_data));
        new->vrrp = alloc_list(free_vrrp, dump_vrrp);
+       new->vrrp_index = alloc_mlist(NULL, NULL, 255);
+       new->vrrp_index_fd = alloc_mlist(NULL, NULL, 1024+1);
        new->vrrp_sync_group = alloc_list(free_vgroup, dump_vgroup);
+       vrrp_buffer = (char *) MALLOC(VRRP_PACKET_TEMP_LEN);
 
        return new;
 }
@@ -240,14 +263,23 @@ alloc_vrrp_data(void)
 void
 free_vrrp_data(vrrp_conf_data * vrrp_data)
 {
+       free_list(vrrp_data->static_addresses);
+       free_list(vrrp_data->static_routes);
+       free_mlist(vrrp_data->vrrp_index, 255);
+       free_mlist(vrrp_data->vrrp_index_fd, 1024+1);
        free_list(vrrp_data->vrrp);
        free_list(vrrp_data->vrrp_sync_group);
        FREE(vrrp_data);
+       FREE(vrrp_buffer);
 }
 
 void
 dump_vrrp_data(vrrp_conf_data * vrrp_data)
 {
+       if (!LIST_ISEMPTY(vrrp_data->static_addresses)) {
+               syslog(LOG_INFO, "------< Static Addresses >------");
+               dump_list(vrrp_data->static_addresses);
+       }
        if (!LIST_ISEMPTY(vrrp_data->static_routes)) {
                syslog(LOG_INFO, "------< Static Routes >------");
                dump_list(vrrp_data->static_routes);
index 08c6ba0..3ae18f4 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Interfaces manipulation.
  *
- * Version:     $Id: vrrp_if.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_if.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -365,6 +365,7 @@ free_interface_queue(void)
        if (!LIST_ISEMPTY(if_queue))
                free_list(if_queue);
        netlink_close(&nl_kernel);
+       netlink_close(&nl_cmd);
 }
 
 void
diff --git a/keepalived/vrrp/vrrp_index.c b/keepalived/vrrp/vrrp_index.c
new file mode 100644 (file)
index 0000000..b539786
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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 instance index table.
+ *
+ * Version:     $Id: vrrp_index.c,v 1.1.0 2003/07/20 23:41:34 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.
+ */
+
+/* local include */
+#include "vrrp_index.h"
+#include "vrrp_data.h"
+#include "vrrp.h"
+#include "memory.h"
+#include "list.h"
+
+/* Externals vars */
+extern vrrp_conf_data *vrrp_data;
+
+/* VRID hash table */
+void
+alloc_vrrp_bucket(vrrp_rt *vrrp)
+{
+       list_add(&vrrp_data->vrrp_index[vrrp->vrid], vrrp);
+}
+
+vrrp_rt *
+vrrp_index_lookup(const int vrid, const int fd)
+{
+       vrrp_rt *vrrp;
+       element e;
+       list l = &vrrp_data->vrrp_index[vrid];
+
+       /* return if list is empty */
+       if (LIST_ISEMPTY(l))
+               return NULL;
+
+       /*
+        * If list size's is 1 then no collisions. So
+        * Test and return the singleton.
+        */
+       if (LIST_SIZE(l) == 1) {
+               vrrp = ELEMENT_DATA(LIST_HEAD(l));
+               return (vrrp->fd_in == fd) ? vrrp : NULL;
+       }
+
+       /*
+        * List collision on the vrid bucket. The same
+        * vrid is used on a different interface. We perform
+        * a fd lookup as collisions solver.
+        */ 
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               vrrp =  ELEMENT_DATA(e);
+               if (vrrp->fd_in == fd)
+                       return vrrp;
+       }
+
+       /* No match */
+       return NULL;
+}
+
+/* FD hash table */
+void
+alloc_vrrp_fd_bucket(vrrp_rt *vrrp)
+{
+       /* We use a mod key plus 1 */
+       list_add(&vrrp_data->vrrp_index_fd[vrrp->fd_in%1024 + 1], vrrp);
+}
+
+void
+remove_vrrp_fd_bucket(vrrp_rt *vrrp)
+{
+       list l = &vrrp_data->vrrp_index_fd[vrrp->fd_in%1024 + 1];
+       list_del(l, vrrp);
+}
+
+void set_vrrp_fd_bucket(int old_fd, vrrp_rt *vrrp)
+{
+       vrrp_rt *vrrp_ptr;
+       element e;
+       list l = &vrrp_data->vrrp_index_fd[old_fd%1024 + 1];
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               vrrp_ptr =  ELEMENT_DATA(e);
+               if (IF_INDEX(vrrp_ptr->ifp) == IF_INDEX(vrrp->ifp)) {
+                       vrrp_ptr->fd_in = vrrp->fd_in;
+                       vrrp_ptr->fd_out = vrrp->fd_out;
+               }
+       }
+}
index d1e72d2..c701d30 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        NETLINK IPv4 address manipulation.
  *
- * Version:     $Id: vrrp_ipaddress.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_ipaddress.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 /* local include */
 #include "vrrp_ipaddress.h"
 #include "vrrp_netlink.h"
-#include "vrrp_if.h"
+#include "vrrp_data.h"
 #include "memory.h"
 #include "utils.h"
 
+/* extern global vars */
+extern vrrp_conf_data *vrrp_data;
+extern vrrp_conf_data *old_vrrp_data;
+
 /* Add/Delete IP address to a specific interface */
 int
 netlink_address_ipv4(ip_address *ipaddr, int cmd)
 {
-       struct nl_handle nlh;
        int status = 1;
        struct {
                struct nlmsghdr n;
@@ -45,19 +48,13 @@ netlink_address_ipv4(ip_address *ipaddr, int cmd)
        req.n.nlmsg_flags = NLM_F_REQUEST;
        req.n.nlmsg_type = cmd ? RTM_NEWADDR : RTM_DELADDR;
        req.ifa.ifa_family = AF_INET;
-       req.ifa.ifa_index = ipaddr->ifindex;
+       req.ifa.ifa_index = IF_INDEX(ipaddr->ifp);
        req.ifa.ifa_scope = ipaddr->scope;
        req.ifa.ifa_prefixlen = ipaddr->mask;
        addattr_l(&req.n, sizeof (req), IFA_LOCAL, &ipaddr->addr, sizeof (ipaddr->addr));
 
-       if (netlink_socket(&nlh, 0) < 0)
-               return -1;
-
-       if (netlink_talk(&nlh, &req.n) < 0)
+       if (netlink_talk(&nl_cmd, &req.n) < 0)
                status = -1;
-
-       /* to close the socket */
-       netlink_close(&nlh);
        return status;
 }
 
@@ -97,11 +94,11 @@ dump_ipaddress(void *data)
        syslog(LOG_INFO, "     %s/%d dev %s scope %s"
               , inet_ntop2(ip_addr->addr)
               , ip_addr->mask
-              , IF_NAME(if_get_by_ifindex(ip_addr->ifindex))
+              , IF_NAME(ip_addr->ifp)
               , netlink_scope_n2a(ip_addr->scope));
 }
 void
-alloc_ipaddress(list ip_list, vector strvec, int ifindex)
+alloc_ipaddress(list ip_list, vector strvec, interface *ifp)
 {
        ip_address *new;
        uint32_t ipaddr = 0;
@@ -109,7 +106,7 @@ alloc_ipaddress(list ip_list, vector strvec, int ifindex)
        int i = 0;
 
        new = (ip_address *) MALLOC(sizeof(ip_address));
-       new->ifindex = ifindex;
+       new->ifp = ifp;
 
        /* FMT parse */
        while (i < VECTOR_SIZE(strvec)) {
@@ -117,7 +114,7 @@ alloc_ipaddress(list ip_list, vector strvec, int ifindex)
 
                /* cmd parsing */
                if (!strcmp(str, "dev")) {
-                       new->ifindex = IF_INDEX(if_get_by_ifname(VECTOR_SLOT(strvec, ++i)));
+                       new->ifp = if_get_by_ifname(VECTOR_SLOT(strvec, ++i));
                } else if (!strcmp(str, "scope")) {
                        new->scope = netlink_scope_a2n(VECTOR_SLOT(strvec, ++i));
                } else {
@@ -129,6 +126,10 @@ alloc_ipaddress(list ip_list, vector strvec, int ifindex)
                i++;
        }
 
+       /* If index not set then use default interface index */
+       if (!ifp)
+               new->ifp = if_get_by_ifname(DFLT_INT);
+
        list_add(ip_list, new);
 }
 
@@ -174,8 +175,15 @@ clear_diff_address(list l, list n)
                        syslog(LOG_INFO, "ip address %s/%d dev %s, no longer exist"
                               , inet_ntop2(ipaddress->addr)
                               , ipaddress->mask
-                              , IF_NAME(if_get_by_ifindex(ipaddress->ifindex)));
+                              , IF_NAME(ipaddress->ifp));
                        netlink_address_ipv4(ipaddress, IPADDRESS_DEL);
                }
        }
 }
+
+/* Clear static ip address */
+void
+clear_diff_saddresses(void)
+{
+       clear_diff_address(old_vrrp_data->static_addresses, vrrp_data->static_addresses);
+}
index bf2a11c..5810b65 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        NETLINK IPv4 routes manipulation.
  *
- * Version:     $Id: vrrp_iproute.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_iproute.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -36,7 +36,6 @@ extern vrrp_conf_data *old_vrrp_data;
 int
 netlink_route_ipv4(ip_route *iproute, int cmd)
 {
-       struct nl_handle nlh;
        int status = 1;
        struct {
                struct nlmsghdr n;
@@ -68,15 +67,8 @@ netlink_route_ipv4(ip_route *iproute, int cmd)
        if (iproute->src)
                addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &iproute->src, 4);
 
-       /* Send to netlink channel */
-       if (netlink_socket(&nlh, 0) < 0)
-               return -1;
-
-       if (netlink_talk(&nlh, &req.n) < 0)
+       if (netlink_talk(&nl_cmd, &req.n) < 0)
                status = -1;
-
-       /* to close the clocket */
-       netlink_close(&nlh);
        return status;
 }
 
@@ -105,12 +97,12 @@ netlink_rtlist_ipv4(list rt_list, int cmd)
 
 /* Route dump/allocation */
 void
-free_route(void *data)
+free_iproute(void *data)
 {
        FREE(data);
 }
 void
-dump_route(void *data)
+dump_iproute(void *data)
 {
        ip_route *route = data;
        char *log_msg = MALLOC(100);
index ec2ebc5..22b3201 100644 (file)
@@ -7,7 +7,7 @@
  *              authentication data encryption using HMAC MD5 according to
  *              RFCs 2085 & 2104.
  *
- * Version:     $Id: vrrp_ipsecah.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_ipsecah.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index ffe227f..acd9049 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        NETLINK kernel command channel.
  *
- * Version:     $Id: vrrp_netlink.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_netlink.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -601,5 +601,13 @@ kernel_netlink_init(void)
                syslog(LOG_INFO, "Registering Kernel netlink reflector");
                thread_add_read(master, kernel_netlink, NULL, nl_kernel.fd,
                                NETLINK_TIMER);
-       }
+       } else
+               syslog(LOG_INFO, "Error while registering Kernel netlink reflector channel");
+
+       /* Prepare netlink command channel. */
+       netlink_socket(&nl_cmd, 0);
+       if (nl_cmd.fd > 0)
+               syslog(LOG_INFO, "Registering Kernel netlink comand channel");
+       else
+               syslog(LOG_INFO, "Error while registering Kernel netlink cmd channel");
 }
index a896602..3ff9928 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        VRRP state transition notification scripts handling.
  *
- * Version:     $Id: vrrp_notify.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_notify.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 2456021..ab094d5 100644 (file)
@@ -7,7 +7,7 @@
  *              data structure representation the conf file representing
  *              the loadbalanced server pool.
  *  
- * Version:     $Id: vrrp_parser.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_parser.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
@@ -25,6 +25,7 @@
 #include "vrrp_parser.h"
 #include "vrrp_data.h"
 #include "vrrp_sync.h"
+#include "vrrp_index.h"
 #include "vrrp_if.h"
 #include "vrrp.h"
 #include "global_data.h"
 extern vrrp_conf_data *vrrp_data;
 extern unsigned long mem_allocated;
 
+/* Static addresses handler */
+static void
+static_addresses_handler(vector strvec)
+{
+       alloc_value_block(strvec, alloc_saddress);
+}
+
 /* Static routes handler */
 static void
 static_routes_handler(vector strvec)
@@ -54,7 +62,6 @@ vrrp_group_handler(vector strvec)
 {
        vrrp_sgroup *vgroup = LIST_TAIL_DATA(vrrp_data->vrrp_sync_group);
        vgroup->iname = read_value_block();
-       vrrp_sync_set_group(vgroup);
 }
 static void
 vrrp_gnotify_backup_handler(vector strvec)
@@ -114,9 +121,7 @@ vrrp_int_handler(vector strvec)
 static void
 vrrp_track_int_handler(vector strvec)
 {
-       vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
-       char *name = VECTOR_SLOT(strvec, 1);
-       vrrp->track_ifp = if_get_by_ifname(name);
+       alloc_value_block(strvec, alloc_vrrp_track);
 }
 static void
 vrrp_mcastip_handler(vector strvec)
@@ -134,7 +139,8 @@ vrrp_vrid_handler(vector strvec)
                syslog(LOG_INFO, "VRRP Error : VRID not valid !\n");
                syslog(LOG_INFO,
                       "             must be between 1 & 255. reconfigure !\n");
-       }
+       } else
+               alloc_vrrp_bucket(vrrp);
 }
 static void
 vrrp_prio_handler(vector strvec)
@@ -303,6 +309,7 @@ vrrp_init_keywords(void)
        global_init_keywords();
 
        /* Static routes mapping */
+       install_keyword_root("static_ipaddress", &static_addresses_handler);
        install_keyword_root("static_routes", &static_routes_handler);
 
        /* VRRP Instance mapping */
index 82dea8c..dc2b761 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Sheduling framework for vrrp code.
  *
- * Version:     $Id: vrrp_scheduler.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_scheduler.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -28,6 +28,7 @@
 #include "vrrp_notify.h"
 #include "vrrp_netlink.h"
 #include "vrrp_data.h"
+#include "vrrp_index.h"
 #include "ipvswrapper.h"
 #include "memory.h"
 #include "list.h"
@@ -36,6 +37,7 @@
 /* Externals vars */
 extern thread_master *master;
 extern vrrp_conf_data *vrrp_data;
+extern unsigned int debug;
 
 /* VRRP FSM (Finite State Machine) design.
  *
@@ -153,10 +155,8 @@ static void vrrp_log_int_down(vrrp_rt *vrrp)
        if (!IF_ISUP(vrrp->ifp))
                syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN",
                       IF_NAME(vrrp->ifp));
-       if (vrrp->track_ifp)
-               if (!IF_ISUP(vrrp->track_ifp))
-                       syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN",
-                              IF_NAME(vrrp->track_ifp));
+       if (!LIST_ISEMPTY(vrrp->track_ifp))
+               vrrp_log_tracked_down(vrrp->track_ifp);
 }
 
 static void vrrp_log_int_up(vrrp_rt *vrrp)
@@ -164,10 +164,8 @@ static void vrrp_log_int_up(vrrp_rt *vrrp)
        if (IF_ISUP(vrrp->ifp))
                syslog(LOG_INFO, "Kernel is reporting: interface %s UP",
                       IF_NAME(vrrp->ifp));
-       if (vrrp->track_ifp)
-               if (IF_ISUP(vrrp->track_ifp))
-                       syslog(LOG_INFO, "Kernel is reporting: interface %s UP",
-                              IF_NAME(vrrp->track_ifp));
+       if (!LIST_ISEMPTY(vrrp->track_ifp))
+               syslog(LOG_INFO, "Kernel is reporting: tracked interface are UP");
 }
 
 /*
@@ -225,20 +223,17 @@ static TIMEVAL
 vrrp_compute_timer(const int fd)
 {
        vrrp_rt *vrrp;
-       TIMEVAL timer;
        element e;
-       list l = vrrp_data->vrrp;
+       list l = &vrrp_data->vrrp_index_fd[fd%1024 + 1];
+       TIMEVAL timer;
 
-       /* clean the memory */
+       /* Multiple instances on the same interface */
        TIMER_RESET(timer);
-
        for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
                vrrp = ELEMENT_DATA(e);
-               if (vrrp->fd == fd) {
-                       if (timer_cmp(vrrp->sands, timer) < 0 ||
-                           TIMER_ISNULL(timer))
-                               timer = timer_dup(vrrp->sands);
-               }
+               if (timer_cmp(vrrp->sands, timer) < 0 ||
+                   TIMER_ISNULL(timer))
+                       timer = timer_dup(vrrp->sands);
        }
 
        return timer;
@@ -260,19 +255,20 @@ static int
 vrrp_timer_vrid_timeout(const int fd)
 {
        vrrp_rt *vrrp;
-       list l = vrrp_data->vrrp;
        element e;
-       TIMEVAL vrrp_timer;
+       list l = &vrrp_data->vrrp_index_fd[fd%1024 + 1];
+       TIMEVAL timer;
        int vrid = 0;
 
-       /* clean the memory */
-       memset(&vrrp_timer, 0, sizeof (struct timeval));
-       vrrp_timer = vrrp_compute_timer(fd);
-
+       /* Multiple instances on the same interface */
+       TIMER_RESET(timer);
        for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
                vrrp = ELEMENT_DATA(e);
-               if (timer_cmp(vrrp->sands, vrrp_timer) == 0)
+               if (timer_cmp(vrrp->sands, timer) < 0 ||
+                   TIMER_ISNULL(timer)) {
+                       timer = timer_dup(vrrp->sands);
                        vrid = vrrp->vrid;
+               }
        }
        return vrid;
 }
@@ -299,15 +295,15 @@ vrrp_register_workers(list l)
        for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
                sock = ELEMENT_DATA(e);
                /* jump to asynchronous handling */
-               vrrp_timer = vrrp_timer_fd(sock->fd);
+               vrrp_timer = vrrp_timer_fd(sock->fd_in);
 
                /* Register a timer thread if interface is shut */
-               if (sock->fd == -1)
+               if (sock->fd_in == -1)
                        thread_add_timer(master, vrrp_read_dispatcher_thread,
                                         (int *)THREAD_TIMER, vrrp_timer);
                else
                        thread_add_read(master, vrrp_read_dispatcher_thread,
-                                       NULL, sock->fd, vrrp_timer);
+                                       NULL, sock->fd_in, vrrp_timer);
        }
 }
 
@@ -337,10 +333,11 @@ void
 dump_sock(void *data)
 {
        sock *sock = data;
-       syslog(LOG_INFO, "VRRP sockpool: [ifindex(%d), proto(%d), fd(%d)]",
+       syslog(LOG_INFO, "VRRP sockpool: [ifindex(%d), proto(%d), fd(%d,%d)]",
               sock->ifindex
               , sock->proto
-              , sock->fd);
+              , sock->fd_in
+              , sock->fd_out);
 }
 
 void
@@ -386,7 +383,12 @@ vrrp_open_sockpool(list l)
 
        for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
                sock = ELEMENT_DATA(e);
-               sock->fd = open_vrrp_socket(sock->proto, sock->ifindex);
+               sock->fd_in = open_vrrp_socket(sock->proto, sock->ifindex);
+               if (sock->fd_in == -1)
+                       sock->fd_out = -1;
+               else
+                       sock->fd_out = open_vrrp_send_socket(sock->proto,
+                                                            sock->ifindex);
        }
 }
 
@@ -410,8 +412,13 @@ vrrp_set_fds(list l)
                                proto = IPPROTO_VRRP;
 
                        if ((sock->ifindex == IF_INDEX(vrrp->ifp)) &&
-                           (sock->proto == proto))
-                               vrrp->fd = sock->fd;
+                           (sock->proto == proto)) {
+                               vrrp->fd_in = sock->fd_in;
+                               vrrp->fd_out = sock->fd_out;
+
+                               /* append to hash index */
+                               alloc_vrrp_fd_bucket(vrrp);
+                       }
                }
        }
 }
@@ -451,27 +458,13 @@ vrrp_dispatcher_init(thread * thread)
        vrrp_register_workers(pool);
 
        /* cleanup the temp socket pool */
-       dump_list(pool);
+       if (debug & 32)
+               dump_list(pool);
        free_list(pool);
 
        return 1;
 }
 
-static vrrp_rt *
-vrrp_search_instance(const int vrid)
-{
-       vrrp_rt *vrrp;
-       list l = vrrp_data->vrrp;
-       element e;
-
-       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-               vrrp = ELEMENT_DATA(e);
-               if (vrrp->vrid == vrid)
-                       return vrrp;
-       }
-       return NULL;
-}
-
 static void
 vrrp_backup(vrrp_rt * vrrp, char *vrrp_buffer, int len)
 {
@@ -703,7 +696,7 @@ vrrp_dispatcher_read_to(int fd)
 
        /* Searching for matching instance */
        vrid = vrrp_timer_vrid_timeout(fd);
-       vrrp = vrrp_search_instance(vrid);
+       vrrp = vrrp_index_lookup(vrid, fd);
 
        /* Run the FSM handler */
        prev_state = vrrp->state;
@@ -722,7 +715,7 @@ vrrp_dispatcher_read_to(int fd)
         * compute new sands timer safely.
         */
        vrrp_init_instance_sands(vrrp);
-       return vrrp->fd;
+       return vrrp->fd_in;
 }
 
 /* Handle dispatcher read packet */
@@ -730,14 +723,13 @@ static int
 vrrp_dispatcher_read(int fd)
 {
        vrrp_rt *vrrp;
-       char *vrrp_buffer;
        struct iphdr *iph;
        vrrp_pkt *hd;
        int len = 0;
        int prev_state = 0;
 
-       /* allocate & clean the read buffer */
-       vrrp_buffer = (char *) MALLOC(VRRP_PACKET_TEMP_LEN);
+       /* Clean the read buffer */
+       memset(vrrp_buffer, 0, VRRP_PACKET_TEMP_LEN);
 
        /* read & affect received buffer */
        len = read(fd, vrrp_buffer, VRRP_PACKET_TEMP_LEN);
@@ -750,13 +742,11 @@ vrrp_dispatcher_read(int fd)
        /* GCC bug : end */
 
        /* Searching for matching instance */
-       vrrp = vrrp_search_instance(hd->vrid);
+       vrrp = vrrp_index_lookup(hd->vrid, fd);
 
        /* If no instance found => ignore the advert */
-       if (!vrrp) {
-               FREE(vrrp_buffer);
+       if (!vrrp)
                return fd;
-       }
 
        /* Run the FSM handler */
        prev_state = vrrp->state;
@@ -776,8 +766,6 @@ vrrp_dispatcher_read(int fd)
         */
        vrrp_init_instance_sands(vrrp);
 
-       /* cleanup the room */
-       FREE(vrrp_buffer);
        return fd;
 }
 
index ddbc5fa..9b1e0b0 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        VRRP synchronization framework.
  *
- * Version:     $Id: vrrp_sync.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version:     $Id: vrrp_sync.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -34,45 +34,40 @@ extern vrrp_conf_data *vrrp_data;
 void
 vrrp_init_instance_sands(vrrp_rt * vrrp)
 {
-       TIMEVAL timer;
-
-       timer = timer_now();
-
-       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;
+       TIMEVAL timer = timer_now();
+
+       /*
+        * We only make timer auto-recalibration while being in
+        * master state. Other state are transtions so recalibration
+        * is not needed. Here we estimate the VRRP advert time
+        * handling and substract it to new computed timer.
+        * We just take care to the usec sub timer and not sec one
+        * to not conflict scheduling decision.
+        */
+       if (vrrp->state == VRRP_STATE_MAST) {
+               long usec;
+               usec = timer.tv_usec - vrrp->sands.tv_usec;
+               vrrp->sands.tv_sec = timer.tv_sec + vrrp->adver_int / TIMER_HZ;
+               vrrp->sands.tv_usec = timer.tv_usec;
+               if (usec > 0)
+                       vrrp->sands.tv_usec -= usec;
+               return;
        }
+
        if (vrrp->state == VRRP_STATE_GOTO_MASTER ||
-           vrrp->state == VRRP_STATE_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;
+               return;
        }
-}
 
-/* return the first group found for a specific instance */
-vrrp_sgroup *
-vrrp_get_sync_group(char *iname)
-{
-       int i;
-       char *str;
-       element e;
-       vrrp_sgroup *vgroup;
-       list l = vrrp_data->vrrp_sync_group;
-
-       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-               vgroup = ELEMENT_DATA(e);
-               if (vgroup->iname)
-                       for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
-                               str = VECTOR_SLOT(vgroup->iname, i);
-                               if (strcmp(str, iname) == 0)
-                                       return vgroup;
-                       }
+       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;
        }
-       return NULL;
 }
 
-/* jointure between instance and group => iname */
+/* Instance name lookup */
 vrrp_rt *
 vrrp_get_instance(char *iname)
 {
@@ -99,8 +94,12 @@ vrrp_sync_set_group(vrrp_sgroup *vgroup)
        for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
                str = VECTOR_SLOT(vgroup->iname, i);
                vrrp = vrrp_get_instance(str);
-               if (vrrp)
+               if (vrrp) {
+                       if (LIST_ISEMPTY(vgroup->index))
+                               vgroup->index = alloc_list(NULL, NULL);
+                       list_add(vgroup->index, vrrp);
                        vrrp->sync = vgroup;
+               }
        }
 }
 
@@ -108,20 +107,18 @@ vrrp_sync_set_group(vrrp_sgroup *vgroup)
 int
 vrrp_sync_group_up(vrrp_sgroup * vgroup)
 {
-       vrrp_rt *isync;
-       char *str;
+       vrrp_rt *vrrp;
+       element e;
+       list l = vgroup->index;
        int is_up = 0;
-       int i;
 
-       for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
-               str = VECTOR_SLOT(vgroup->iname, i);
-               isync = vrrp_get_instance(str);
-               if (isync)
-                       if (VRRP_ISUP(isync))
-                               is_up++;
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               vrrp = ELEMENT_DATA(e);
+               if (VRRP_ISUP(vrrp))
+                       is_up++;
        }
 
-       if (is_up == VECTOR_SIZE(vgroup->iname)) {
+       if (is_up == LIST_SIZE(vgroup->index)) {
                syslog(LOG_INFO, "Kernel is reporting: Group(%s) UP"
                               , GROUP_NAME(vgroup));
                return 1;
@@ -162,10 +159,10 @@ vrrp_sync_leave_fault(vrrp_rt * vrrp)
 void
 vrrp_sync_master_election(vrrp_rt * vrrp)
 {
-       int i;
-       char *str;
        vrrp_rt *isync;
        vrrp_sgroup *vgroup = vrrp->sync;
+       list l = vgroup->index;
+       element e;
 
        if (vrrp->wantstate != VRRP_STATE_GOTO_MASTER)
                return;
@@ -175,41 +172,39 @@ vrrp_sync_master_election(vrrp_rt * vrrp)
        syslog(LOG_INFO, "VRRP_Group(%s) Transition to MASTER state",
               GROUP_NAME(vrrp->sync));
 
-       for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
-               str = VECTOR_SLOT(vgroup->iname, i);
-               isync = vrrp_get_instance(str);
-               if (isync)
-                       if (isync != vrrp) {
-                               /* Force a new protocol master election */
-                               isync->wantstate = VRRP_STATE_GOTO_MASTER;
-                               syslog(LOG_INFO,
-                                      "VRRP_Instance(%s) forcing a new MASTER election",
-                                      isync->iname);
-                               vrrp_send_adv(isync, isync->priority);
-                       }
+       /* Perform sync index */
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               isync = ELEMENT_DATA(e);
+               if (isync != vrrp) {
+                       /* Force a new protocol master election */
+                       isync->wantstate = VRRP_STATE_GOTO_MASTER;
+                       syslog(LOG_INFO,
+                              "VRRP_Instance(%s) forcing a new MASTER election",
+                              isync->iname);
+                       vrrp_send_adv(isync, isync->priority);
+               }
        }
 }
 
 void
 vrrp_sync_backup(vrrp_rt * vrrp)
 {
-       int i;
-       char *str;
        vrrp_rt *isync;
        vrrp_sgroup *vgroup = vrrp->sync;
+       list l = vgroup->index;
+       element e;
 
        syslog(LOG_INFO, "VRRP_Group(%s) Syncing instances to BACKUP state",
               GROUP_NAME(vgroup));
 
-       for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
-               str = VECTOR_SLOT(vgroup->iname, i);
-               isync = vrrp_get_instance(str);
-               if (isync)
-                       if (isync != vrrp) {
-                               isync->wantstate = VRRP_STATE_BACK;
-                               vrrp_state_leave_master(isync);
-                               vrrp_init_instance_sands(isync);
-                       }
+       /* Perform sync index */
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               isync = ELEMENT_DATA(e);
+               if (isync != vrrp) {
+                       isync->wantstate = VRRP_STATE_BACK;
+                       vrrp_state_leave_master(isync);
+                       vrrp_init_instance_sands(isync);
+               }
        }
        vgroup->state = VRRP_STATE_BACK;
        vrrp_sync_smtp_notifier(vgroup);
@@ -219,10 +214,10 @@ vrrp_sync_backup(vrrp_rt * vrrp)
 void
 vrrp_sync_master(vrrp_rt * vrrp)
 {
-       int i;
-       char *str;
        vrrp_rt *isync;
        vrrp_sgroup *vgroup = vrrp->sync;
+       list l = vgroup->index;
+       element e;
 
        if (GROUP_STATE(vrrp->sync) == VRRP_STATE_MAST)
                return;
@@ -230,17 +225,16 @@ vrrp_sync_master(vrrp_rt * vrrp)
        syslog(LOG_INFO, "VRRP_Group(%s) Syncing instances to MASTER state",
               GROUP_NAME(vrrp->sync));
 
-       for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
-               str = VECTOR_SLOT(vgroup->iname, i);
-               isync = vrrp_get_instance(str);
+       /* Perform sync index */
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               isync = ELEMENT_DATA(e);
 
                /* Send the higher priority advert on all synced instances */
-               if (isync)
-                       if (isync != vrrp) {
-                               isync->wantstate = VRRP_STATE_MAST;
-                               vrrp_state_goto_master(isync);
-                               vrrp_init_instance_sands(isync);
-                       }
+               if (isync != vrrp) {
+                       isync->wantstate = VRRP_STATE_MAST;
+                       vrrp_state_goto_master(isync);
+                       vrrp_init_instance_sands(isync);
+               }
        }
        vgroup->state = VRRP_STATE_MAST;
        vrrp_sync_smtp_notifier(vgroup);
@@ -250,10 +244,10 @@ vrrp_sync_master(vrrp_rt * vrrp)
 void
 vrrp_sync_fault(vrrp_rt * vrrp)
 {
-       int i;
-       char *str;
        vrrp_rt *isync;
        vrrp_sgroup *vgroup = vrrp->sync;
+       list l = vgroup->index;
+       element e;
 
        if (GROUP_STATE(vrrp->sync) == VRRP_STATE_FAULT)
                return;
@@ -261,9 +255,9 @@ vrrp_sync_fault(vrrp_rt * vrrp)
        syslog(LOG_INFO, "VRRP_Group(%s) Syncing instances to FAULT state",
               GROUP_NAME(vrrp->sync));
 
-       for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
-               str = VECTOR_SLOT(vgroup->iname, i);
-               isync = vrrp_get_instance(str);
+       /* Perform sync index */
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               isync = ELEMENT_DATA(e);
 
                /*
                 * We force sync instance to backup mode.
@@ -271,13 +265,12 @@ vrrp_sync_fault(vrrp_rt * vrrp)
                 * => by default ms_down_timer is set to 3secs.
                 * => Takeover will be less than 3secs !
                 */
-               if (isync)
-                       if (isync != vrrp) {
-                               if (isync->state == VRRP_STATE_MAST)
-                                       isync->wantstate = VRRP_STATE_GOTO_FAULT;
-                               if (isync->state == VRRP_STATE_BACK)
-                                       isync->state = VRRP_STATE_FAULT;
-                       }
+               if (isync != vrrp) {
+                       if (isync->state == VRRP_STATE_MAST)
+                               isync->wantstate = VRRP_STATE_GOTO_FAULT;
+                       if (isync->state == VRRP_STATE_BACK)
+                               isync->state = VRRP_STATE_FAULT;
+               }
        }
        vgroup->state = VRRP_STATE_FAULT;
        notify_group_exec(vgroup, VRRP_STATE_FAULT);
diff --git a/keepalived/vrrp/vrrp_track.c b/keepalived/vrrp/vrrp_track.c
new file mode 100644 (file)
index 0000000..4088a56
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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:        Interface tracking framework.
+ *
+ * Version:     $Id: vrrp_track.c,v 1.1.0 2003/07/20 23:41:34 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.
+ */
+
+/* local include */
+#include "vrrp_track.h"
+#include "vrrp_if.h"
+#include "vrrp_data.h"
+#include "memory.h"
+
+/* Track interface dump */
+void
+dump_track(void *data)
+{
+       interface *ifp = data;
+       syslog(LOG_INFO, "     %s", IF_NAME(ifp));
+}
+void
+alloc_track(list track_list, vector strvec)
+{
+       interface *ifp = NULL;
+       char *tracked = VECTOR_SLOT(strvec, 0);
+
+       ifp = if_get_by_ifname(tracked);
+
+       /* Ignoring if no interface found */
+       if (!ifp) {
+               syslog(LOG_INFO, "     %s no match, ignoring...", tracked);
+               return;
+       }
+
+       list_add(track_list, ifp);
+}
+
+/* Test if all tracked interfaces are UP */
+int
+vrrp_tracked_up(list l)
+{
+       element e;
+       interface *ifp;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               ifp = ELEMENT_DATA(e);
+               if (!IF_ISUP(ifp))
+                       return 0;
+       }
+
+       return 1;
+}
+
+/* Log tracked interface down */
+void
+vrrp_log_tracked_down(list l)
+{
+       element e;
+       interface *ifp;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               ifp = ELEMENT_DATA(e);
+               if (!IF_ISUP(ifp))
+                       syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN",
+                              IF_NAME(ifp));
+       }
+}
index f134008..3ed2b25 100644 (file)
 #include "list.h"
 #include "memory.h"
 
+/* Simple list helpers functions */
 list
 alloc_list(void (*free_func) (void *), void (*dump_func) (void *))
 {
-       list new = (list) MALLOC(sizeof (struct _list));
-       new->free = free_func;
-       new->dump = dump_func;
-       return new;
+       return alloc_mlist(free_func, dump_func, 1);
 }
 
 static element
@@ -55,14 +53,36 @@ list_add(list l, void *data)
        l->count++;
 }
 
+void
+list_del(list l, void *data)
+{
+       element e;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               if (ELEMENT_DATA(e) == data) {
+                       if (e->prev)
+                               e->prev->next = e->next;
+                       else
+                               l->head = e->next;
+
+                       if (e->next)
+                               e->next->prev = e->prev;
+                       else
+                               l->tail = e->prev;
+
+                       l->count--;
+                       FREE(e);
+                       return;
+               }
+       }
+}
+
 void *
 list_element(list l, int num)
 {
-       element e;
+       element e = LIST_HEAD(l);
        int i = 0;
 
-       e = LIST_HEAD(l);
-
        /* fetch element number num */
        for (i = 0; i < num; i++)
                if (e)
@@ -83,8 +103,8 @@ dump_list(list l)
                        (*l->dump) (e->data);
 }
 
-void
-free_list(list l)
+static void
+free_element(list l)
 {
        element e;
        element next;
@@ -95,5 +115,46 @@ free_list(list l)
                        (*l->free) (e->data);
                FREE(e);
        }
+}
+
+void
+free_list(list l)
+{
+       if (!l)
+               return;
+       free_element(l);
+       FREE(l);
+}
+
+
+/* Multiple list helpers functions */
+list
+alloc_mlist(void (*free_func) (void *), void (*dump_func) (void *), int size)
+{
+       list new = (list) MALLOC(size * sizeof (struct _list));
+       new->free = free_func;
+       new->dump = dump_func;
+       return new;
+}
+
+void
+dump_mlist(list l, int size)
+{
+       int i;
+
+       for (i = 0; i < size; i++)
+               dump_list(&l[i]);
+}
+
+void
+free_mlist(list l, int size)
+{
+       int i;
+
+       if (!l)
+               return;
+
+       for (i = 0; i < size; i++)
+               free_element(&l[i]);
        FREE(l);
 }
index 41956df..e49f911 100644 (file)
@@ -55,5 +55,9 @@ extern void free_list(list l);
 extern void *list_element(list l, int num);
 extern void dump_list(list l);
 extern void list_add(list l, void *data);
+extern void list_del(list l, void *data);
+extern list alloc_mlist(void (*free_func) (void *), void (*dump_func) (void *), int size);
+extern void dump_mlist(list l, int size);
+extern void free_mlist(list l, int size);
 
 #endif
index 40b045f..7708dd6 100644 (file)
@@ -22,6 +22,9 @@
  *              2 of the License, or (at your option) any later version.
  */
 
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/select.h>
 #include "scheduler.h"
 #include "memory.h"
 #include "utils.h"
@@ -318,6 +321,41 @@ thread_add_timer(thread_master * m, int (*func) (thread *)
        return thread;
 }
 
+/* Add a child thread. */
+thread *
+thread_add_child(thread_master * m, int (*func) (thread *)
+                , void * arg, pid_t pid, long timer)
+{
+       thread *thread;
+       TIMEVAL time_now;
+
+       assert(m != NULL);
+
+       thread = thread_new(m);
+       thread->type = THREAD_CHILD;
+       thread->id = 0;
+       thread->master = m;
+       thread->func = func;
+       thread->arg = arg;
+       thread->u.c.pid = pid;
+       thread->u.c.status = 0;
+
+       /* Compute write timeout value */
+       time_now = timer_now();
+       if (timer >= TIMER_MAX_SEC) {
+               time_now.tv_sec += timer / TIMER_HZ;
+               time_now.tv_usec += timer % TIMER_HZ;
+       } else
+               time_now.tv_sec += timer;
+
+       thread->sands = time_now;
+
+       /* Sort by timeval. */
+       thread_list_add_timeval(&m->child, thread);
+
+       return thread;
+}
+
 /* Add simple event thread. */
 thread *
 thread_add_event(thread_master * m, int (*func) (thread *)
@@ -377,6 +415,13 @@ thread_cancel(thread * thread)
        case THREAD_TIMER:
                thread_list_delete(&thread->master->timer, thread);
                break;
+       case THREAD_CHILD:
+               /* Does this need to kill the child, or is that the
+                * caller's job?
+                * This function is currently unused, so leave it for now.
+                */
+               thread_list_delete(&thread->master->child, thread);
+               break;
        case THREAD_EVENT:
                thread_list_delete(&thread->master->event, thread);
                break;
@@ -466,9 +511,22 @@ thread_fetch(thread_master * m, thread * fetch)
        fd_set exceptfd;
        TIMEVAL time_now;
        TIMEVAL *timer_wait;
+       int status;
+       sigset_t sigset, dummy_sigset, block_sigset, pending;
 
        assert(m != NULL);
 
+       /*
+        * Set up the signal mask for select, by removing
+        * SIGCHLD from the set of blocked signals.
+        */
+       sigemptyset(&dummy_sigset);
+       sigprocmask(SIG_BLOCK, &dummy_sigset, &sigset);
+       sigdelset(&sigset, SIGCHLD);
+
+       sigemptyset(&block_sigset);
+       sigaddset(&block_sigset, SIGCHLD);
+
        /* Timer allocation */
        timer_wait = (TIMEVAL *) MALLOC(sizeof (TIMEVAL));
 
@@ -507,17 +565,86 @@ retry:    /* When thread can't fetch try to find next thread again. */
        writefd = m->writefd;
        exceptfd = m->exceptfd;
 
-       ret = select(FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
+       /*
+        * Linux doesn't have a pselect syscall. Need to manually
+        * check if we have a signal waiting for us, else we lose the SIGCHLD
+        * when the pselect emulation changes the procmask.
+        * Theres still a small race between the procmask change and the select
+        * call, but it'll be picked up in the next iteration.
+        * Note that we don't use pselect here for portability between glibc
+        * versions. Until/unless linux gets a pselect syscall, this is
+        * equivalent to what glibc does, anyway.
+        */
+
+       sigpending(&pending);
+       if (sigismember(&pending, SIGCHLD)) {
+               /* Clear the pending signal */
+               int sig;
+               sigwait(&block_sigset, &sig);
+
+               ret = -1;
+               errno = EINTR;
+       } else {
+               /* Emulate pselect */
+               sigset_t saveset;
+               sigprocmask(SIG_SETMASK, &sigset, &saveset);
+               ret = select(FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
+               sigprocmask(SIG_SETMASK, &saveset, NULL);
+       }
+
        if (ret < 0) {
                if (errno != EINTR) {
                        /* Real error. */
                        DBG("select error: %s", strerror(errno));
                        assert(0);
+               } else {
+                       /*
+                        * This is O(n^2), but there will only be a few entries on
+                        * this list.
+                        */
+                       pid_t pid;
+                       while ((pid = waitpid(-1, &status, WNOHANG))) {
+                               if (pid == -1) {
+                                       if (errno == ECHILD)
+                                               goto retry;
+                                       DBG("waitpid error: %s", strerror(errno));
+                                       assert(0);
+                               } else {
+                                       thread = m->child.head;
+                                       while (thread) {
+                                               struct _thread *t;
+                                               t = thread;
+                                               thread = t->next;
+                                               if (pid == t->u.c.pid) {
+                                                       thread_list_delete(&m->child, t);
+                                                       thread_list_add(&m->ready, t);
+                                                       t->u.c.status = status;
+                                                       t->type = THREAD_READY;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
                }
-               /* Signal is coming. */
                goto retry;
        }
 
+       /* Timeout children */
+       time_now = timer_now();
+       thread = m->child.head;
+       while (thread) {
+               struct _thread *t;
+
+               t = thread;
+               thread = t->next;
+
+               if (timer_cmp(time_now, t->sands) >= 0) {
+                       thread_list_delete(&m->child, t);
+                       thread_list_add(&m->ready, t);
+                       t->type = THREAD_CHILD_TIMEOUT;
+               }
+       }
+
        /* Read thead. */
        time_now = timer_now();
        thread = m->read.head;
@@ -622,6 +749,7 @@ thread_call(thread * thread)
 
 /* Our infinite scheduling loop */
 extern thread_master *master;
+extern unsigned int debug;
 void
 launch_scheduler(void)
 {
index 28e3758..721770f 100644 (file)
@@ -25,6 +25,8 @@
 
 /* system includes */
 #include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <assert.h>
 #include <fcntl.h>
 #include <errno.h>
@@ -44,6 +46,10 @@ typedef struct _thread {
        union {
                int val;                /* second argument of the event. */
                int fd;                 /* file descriptor in case of read/write. */
+               struct {
+                       pid_t pid;      /* process id a child thread is wanting. */
+                       int status;     /* return status of the process */
+               } c;
        } u;
 } thread;
 
@@ -59,6 +65,7 @@ typedef struct _thread_master {
        thread_list read;
        thread_list write;
        thread_list timer;
+       thread_list child;
        thread_list event;
        thread_list ready;
        thread_list unuse;
@@ -69,15 +76,18 @@ typedef struct _thread_master {
 } thread_master;
 
 /* Thread types. */
-#define THREAD_READ           0
-#define THREAD_WRITE          1
-#define THREAD_TIMER          2
-#define THREAD_EVENT          3
-#define THREAD_READY          4
-#define THREAD_UNUSED         5
-#define THREAD_WRITE_TIMEOUT  6
-#define THREAD_READ_TIMEOUT   7
-#define THREAD_TERMINATE      8
+#define THREAD_READ            0
+#define THREAD_WRITE           1
+#define THREAD_TIMER           2
+#define THREAD_EVENT           3
+#define THREAD_CHILD           4
+#define THREAD_READY           5
+#define THREAD_UNUSED          6
+#define THREAD_WRITE_TIMEOUT   7
+#define THREAD_READ_TIMEOUT    8
+#define THREAD_CHILD_TIMEOUT   9
+#define THREAD_TERMINATE       10
+
 
 /* MICRO SEC def */
 #define BOOTSTRAP_DELAY 1
@@ -86,6 +96,8 @@ typedef struct _thread_master {
 #define THREAD_ARG(X) ((X)->arg)
 #define THREAD_FD(X)  ((X)->u.fd)
 #define THREAD_VAL(X) ((X)->u.val)
+#define THREAD_CHILD_PID(X) ((X)->u.c.pid)
+#define THREAD_CHILD_STATUS(X) ((X)->u.c.status)
 
 /* Prototypes. */
 extern thread_master *thread_make_master(void);
@@ -97,6 +109,8 @@ extern thread *thread_add_write(thread_master * m, int (*func) (thread *)
                                , void *arg, int fd, long timeout);
 extern thread *thread_add_timer(thread_master * m, int (*func) (thread *)
                                , void *arg, long timer);
+extern thread *thread_add_child(thread_master * m, int (*func) (thread *)
+                               , void *arg, pid_t pid, long timeout);
 extern thread *thread_add_event(thread_master * m, int (*func) (thread *)
                                , void *arg, int val);
 extern void thread_cancel(thread * thread);