keepalived-0.6.6 v0.6.6
authorAlexandre Cassen <acassen@freebox.fr>
Sat, 6 Jul 2002 09:17:50 +0000 (11:17 +0200)
committerAlexandre Cassen <acassen@freebox.fr>
Mon, 28 Sep 2009 08:58:56 +0000 (10:58 +0200)
* keepalived-0.6.6 released.
* added indentation style .indent.pro
* Review the previous source tree. Splitted the code into functional subdirs.
  Added multi-level automake scripts. The source tree looks like :
.
|-- bin
|-- genhash
|-- keepalived
|   |-- core
|   |-- etc
|   |   |-- init.d
|   |   `-- keepalived
|   |-- healthcheck
|   |-- include
|   |-- libipfwc
|   |-- libipvs
|   |-- samples
|   `-- vrrp
`-- lib
* Refine autoconf/automake scripts. Added automake support to libipvs and
  libipfwc. Added code selection compilation for libipvs and libipfwc.
* Review Makefile(s) to use more convenient facilities like distclean, ...
* Added support to modprobe_ipvs if the ip_vs.o module is not loaded.
  If modprobe fails then IPVS is assumed unavailable.
* Refine the IPVS wrapper to be more tolerant. When a VS or RS is already
  configured don t stop the daemon. The daemon is stopped only on critical
  IPVS errors.
* VRRP : Review the bootstrap sequence to start daemon even if one of the
  instance want to run on an interface administratively shut. Added extension
  to FSM to force transition to FAULT state during bootstrap if the interface
  is shut.
* Some cosmetics patches.
* keepalived-0.6.5 released.
* Fixed a NULL pointer exception while releasing IPVS entries.
* Review the Makefile.in to fixe some conventional issue. Fixed a libipvs
  dependance code selection.
* Christophe Varoqui, <Christophe.Varoqui@free.fr> created the rpm spec file.
* Roberto Nibali, <ratz@linux-vs.org> helped during OLS with code cleanup.
  Review the whole code coding style to use more conventional indentation. The
  one used into LVS and Kernel code. Coding style provided by the following
  command :
    find . -name "*.[chS]" -exec indent -kr -i8 -ts8 -sob -l80 -ss -bs -psl \
    {} \; && find . -name "*~" -exec rm  {} \;
* Roberto Nibali and I review the DEBUG logging facility adding global DBG()
  func declaration.
* Roberto Nibali fixed two potential buffer overflow (strcpy).
* Richard  L. Allbery, <rla@prideindustries.com> pointed out a fwmark issue.
  Healthcheckers is enabled if virtual service is a fwmark.
* Some cosmetics patches.
* Alex Kramarov, <alex@incredimail.com> fine the keepalived.init script

135 files changed:
.indent.pro [new file with mode: 0644]
ChangeLog
Makefile.in
TODO
VERSION
check_api.c [deleted file]
check_ci.c [deleted file]
check_http.c [deleted file]
check_misc.c [deleted file]
check_ssl.c [deleted file]
check_tcp.c [deleted file]
configure
configure.in
data.c [deleted file]
genhash/Makefile.in
genhash/client.c
genhash/client.h
genhash/client.o [new file with mode: 0644]
genhash/common.c
genhash/common.h
genhash/common.o [new file with mode: 0644]
genhash/main.c
genhash/main.h
genhash/main.o [new file with mode: 0644]
ipfwwrapper.c [deleted file]
ipvswrapper.c [deleted file]
ipwrapper.c [deleted file]
keepalived.spec [new file with mode: 0644]
keepalived/Makefile.in [new file with mode: 0644]
keepalived/core/Makefile.in [new file with mode: 0644]
keepalived/core/daemon.c [moved from daemon.c with 55% similarity]
keepalived/core/data.c [new file with mode: 0644]
keepalived/core/layer4.c [new file with mode: 0644]
keepalived/core/list.c [new file with mode: 0644]
keepalived/core/main.c [new file with mode: 0644]
keepalived/core/memory.c [new file with mode: 0644]
keepalived/core/parser.c [new file with mode: 0644]
keepalived/core/pidfile.c [moved from pidfile.c with 59% similarity]
keepalived/core/scheduler.c [new file with mode: 0644]
keepalived/core/smtp.c [new file with mode: 0644]
keepalived/core/timer.c [moved from timer.c with 57% similarity]
keepalived/core/utils.c [new file with mode: 0644]
keepalived/core/vector.c [moved from vector.c with 51% similarity]
keepalived/etc/init.d/keepalived.init [moved from etc/init.d/keepalived.init with 95% similarity]
keepalived/etc/keepalived/keepalived.conf [moved from etc/keepalived/keepalived.conf with 94% similarity]
keepalived/healthcheck/Makefile.in [new file with mode: 0644]
keepalived/healthcheck/check_api.c [new file with mode: 0644]
keepalived/healthcheck/check_ci.c [new file with mode: 0644]
keepalived/healthcheck/check_http.c [new file with mode: 0644]
keepalived/healthcheck/check_misc.c [new file with mode: 0644]
keepalived/healthcheck/check_ssl.c [new file with mode: 0644]
keepalived/healthcheck/check_tcp.c [new file with mode: 0644]
keepalived/healthcheck/ipfwwrapper.c [new file with mode: 0644]
keepalived/healthcheck/ipvswrapper.c [new file with mode: 0644]
keepalived/healthcheck/ipwrapper.c [new file with mode: 0644]
keepalived/include/check_api.h [moved from check_api.h with 82% similarity]
keepalived/include/check_ci.h [moved from check_ci.h with 86% similarity]
keepalived/include/check_http.h [moved from check_http.h with 70% similarity]
keepalived/include/check_misc.h [moved from check_misc.h with 94% similarity]
keepalived/include/check_ssl.h [moved from check_ssl.h with 81% similarity]
keepalived/include/check_tcp.h [moved from check_tcp.h with 91% similarity]
keepalived/include/daemon.h [moved from daemon.h with 95% similarity]
keepalived/include/data.h [moved from data.h with 71% similarity]
keepalived/include/ipfwwrapper.h [moved from ipfwwrapper.h with 88% similarity]
keepalived/include/ipvswrapper.h [moved from ipvswrapper.h with 77% similarity]
keepalived/include/ipwrapper.h [moved from ipwrapper.h with 68% similarity]
keepalived/include/layer4.h [moved from layer4.h with 77% similarity]
keepalived/include/list.h [moved from list.h with 83% similarity]
keepalived/include/main.h [moved from main.h with 90% similarity]
keepalived/include/memory.h [moved from memory.h with 94% similarity]
keepalived/include/parser.h [moved from parser.h with 88% similarity]
keepalived/include/pidfile.h [moved from pidfile.h with 95% similarity]
keepalived/include/scheduler.h [moved from scheduler.h with 54% similarity]
keepalived/include/smtp.h [moved from smtp.h with 81% similarity]
keepalived/include/timer.h [moved from timer.h with 96% similarity]
keepalived/include/utils.h [moved from utils.h with 82% similarity]
keepalived/include/vector.h [moved from vector.h with 93% similarity]
keepalived/include/vrrp.h [moved from vrrp.h with 53% similarity]
keepalived/include/vrrp_if.h [moved from vrrp_if.h with 65% similarity]
keepalived/include/vrrp_ipaddress.h [moved from vrrp_ipaddress.h with 82% similarity]
keepalived/include/vrrp_ipsecah.h [moved from vrrp_ipsecah.h with 50% similarity]
keepalived/include/vrrp_netlink.h [moved from vrrp_netlink.h with 87% similarity]
keepalived/include/vrrp_notify.h [moved from vrrp_notify.h with 85% similarity]
keepalived/include/vrrp_scheduler.h [moved from vrrp_scheduler.h with 76% similarity]
keepalived/include/vrrp_sync.h [moved from vrrp_sync.h with 82% similarity]
keepalived/libipfwc/Makefile.in [moved from libipfwc/Makefile with 53% similarity]
keepalived/libipfwc/ipfwc_kernel_headers.h [new file with mode: 0644]
keepalived/libipfwc/libipfwc.c [moved from libipfwc/libipfwc.c with 55% similarity]
keepalived/libipfwc/libipfwc.h [moved from libipfwc/libipfwc.h with 85% similarity]
keepalived/libipvs/Makefile.in [new file with mode: 0644]
keepalived/libipvs/libipvs.c [moved from libipvs/libipvs.c with 100% similarity]
keepalived/libipvs/libipvs.h [moved from libipvs/libipvs.h with 100% similarity]
keepalived/samples/client.pem [moved from samples/client.pem with 100% similarity]
keepalived/samples/dh1024.pem [moved from samples/dh1024.pem with 100% similarity]
keepalived/samples/keepalived.conf.HTTP_GET.port [moved from samples/keepalived.conf.HTTP_GET.port with 100% similarity]
keepalived/samples/keepalived.conf.SSL_GET [moved from samples/keepalived.conf.SSL_GET with 100% similarity]
keepalived/samples/keepalived.conf.ci-linux [moved from samples/keepalived.conf.ci-linux with 100% similarity]
keepalived/samples/keepalived.conf.fwmark [moved from samples/keepalived.conf.fwmark with 100% similarity]
keepalived/samples/keepalived.conf.misc_check [moved from samples/keepalived.conf.misc_check with 100% similarity]
keepalived/samples/keepalived.conf.misc_check_arg [moved from samples/keepalived.conf.misc_check_arg with 100% similarity]
keepalived/samples/keepalived.conf.real_server_group [moved from samples/keepalived.conf.real_server_group with 100% similarity]
keepalived/samples/keepalived.conf.sample [moved from samples/keepalived.conf.sample with 100% similarity]
keepalived/samples/keepalived.conf.virtualhost [moved from samples/keepalived.conf.virtualhost with 100% similarity]
keepalived/samples/keepalived.conf.vrrp [moved from samples/keepalived.conf.vrrp with 100% similarity]
keepalived/samples/keepalived.conf.vrrp.lvs_syncd [moved from samples/keepalived.conf.vrrp.lvs_syncd with 100% similarity]
keepalived/samples/keepalived.conf.vrrp.scripts [moved from samples/keepalived.conf.vrrp.scripts with 100% similarity]
keepalived/samples/keepalived.conf.vrrp.sync [moved from samples/keepalived.conf.vrrp.sync with 100% similarity]
keepalived/samples/root.pem [moved from samples/root.pem with 100% similarity]
keepalived/samples/sample.misccheck.smbcheck.sh [moved from samples/sample.misccheck.smbcheck.sh with 100% similarity]
keepalived/vrrp/Makefile.in [new file with mode: 0644]
keepalived/vrrp/vrrp.c [new file with mode: 0644]
keepalived/vrrp/vrrp_if.c [new file with mode: 0644]
keepalived/vrrp/vrrp_ipaddress.c [moved from vrrp_ipaddress.c with 57% similarity]
keepalived/vrrp/vrrp_ipsecah.c [new file with mode: 0644]
keepalived/vrrp/vrrp_netlink.c [new file with mode: 0644]
keepalived/vrrp/vrrp_notify.c [new file with mode: 0644]
keepalived/vrrp/vrrp_scheduler.c [new file with mode: 0644]
keepalived/vrrp/vrrp_sync.c [new file with mode: 0644]
layer4.c [deleted file]
libipfwc/ipfwc_kernel_headers.h [deleted file]
libipvs/Makefile [deleted file]
list.c [deleted file]
main.c [deleted file]
memory.c [deleted file]
parser.c [deleted file]
scheduler.c [deleted file]
smtp.c [deleted file]
utils.c [deleted file]
vrrp.c [deleted file]
vrrp_if.c [deleted file]
vrrp_ipsecah.c [deleted file]
vrrp_netlink.c [deleted file]
vrrp_notify.c [deleted file]
vrrp_scheduler.c [deleted file]
vrrp_sync.c [deleted file]

diff --git a/.indent.pro b/.indent.pro
new file mode 100644 (file)
index 0000000..9864f41
--- /dev/null
@@ -0,0 +1,8 @@
+-kr
+-i8
+-ts8
+-sob
+-l80
+-ss
+-bs
+-psl
index f885e90..eeeb39e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,56 @@
+2002-07-05  Alexandre Cassen  <acassen@linux-vs.org>
+       * keepalived-0.6.6 released.
+       * added indentation style .indent.pro
+       * Review the previous source tree. Splitted the code into functional subdirs.
+         Added multi-level automake scripts. The source tree looks like :
+               .
+               |-- bin
+               |-- genhash
+               |-- keepalived
+               |   |-- core
+               |   |-- etc
+               |   |   |-- init.d
+               |   |   `-- keepalived
+               |   |-- healthcheck
+               |   |-- include
+               |   |-- libipfwc
+               |   |-- libipvs
+               |   |-- samples
+               |   `-- vrrp
+               `-- lib
+       * Refine autoconf/automake scripts. Added automake support to libipvs and
+         libipfwc. Added code selection compilation for libipvs and libipfwc.
+       * Review Makefile(s) to use more convenient facilities like distclean, ...
+       * Added support to modprobe_ipvs if the ip_vs.o module is not loaded.
+         If modprobe fails then IPVS is assumed unavailable.
+       * Refine the IPVS wrapper to be more tolerant. When a VS or RS is already
+         configured don t stop the daemon. The daemon is stopped only on critical
+         IPVS errors.
+       * VRRP : Review the bootstrap sequence to start daemon even if one of the
+         instance want to run on an interface administratively shut. Added extension
+         to FSM to force transition to FAULT state during bootstrap if the interface
+         is shut.
+       * Some cosmetics patches.
+
+2002-07-01  Alexandre Cassen  <acassen@linux-vs.org>
+       * keepalived-0.6.5 released.
+       * Fixed a NULL pointer exception while releasing IPVS entries.
+       * Review the Makefile.in to fixe some conventional issue. Fixed a libipvs
+         dependance code selection.
+       * Christophe Varoqui, <Christophe.Varoqui@free.fr> created the rpm spec file.
+       * Roberto Nibali, <ratz@linux-vs.org> helped during OLS with code cleanup.
+         Review the whole code coding style to use more conventional indentation. The
+         one used into LVS and Kernel code. Coding style provided by the following
+         command :
+           find . -name "*.[chS]" -exec indent -kr -i8 -ts8 -sob -l80 -ss -bs -psl \
+           {} \; && find . -name "*~" -exec rm  {} \;
+       * Roberto Nibali and I review the DEBUG logging facility adding global DBG()
+         func declaration.
+       * Roberto Nibali fixed two potential buffer overflow (strcpy).
+       * Richard  L. Allbery, <rla@prideindustries.com> pointed out a fwmark issue.
+         Healthcheckers is enabled if virtual service is a fwmark.
+       * Some cosmetics patches.
+
 2002-06-25  Alexandre Cassen  <acassen@linux-vs.org>
        * keepalived-0.6.4 released.
        * Rewrote the previous ip address utilities functions. Review the string
@@ -12,7 +65,7 @@
        * Fixed a Kernel 2.2 code selection issue (ETHTOOL).
        * Added support to wensong libipvs.
        * Fixed a sorry_server cleanup side effect.
-       * Alex Karamasov, <alex@incredimail.com> fine the keepalived.init script
+       * Alex Kramarov, <alex@incredimail.com> fine the keepalived.init script
          to be compatible with redhat chkconfig.
 
 2002-06-18  Alexandre Cassen  <acassen@linux-vs.org>
index 5a0d829..089a99f 100644 (file)
 #
 # Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
 
-EXEC = keepalived
-KERNEL    := @KERN@
-IPVS_FLAG := @IPVS_SUPPORT@
-VRRP_FLAG := @VRRP_SUPPORT@
-CI_LINUX  := @CI_LINUX@
-
-prefix      = @prefix@
-exec_prefix = @exec_prefix@
-sbindir     = @sbindir@
-
-init_script = etc/init.d/keepalived.init
-conf_file   = etc/keepalived/keepalived.conf
-
-CC = @CC@
-CFLAGS = @CFLAGS@ \
-       -Wall -Wunused -Wstrict-prototypes \
-       -D$(KERNEL) -D$(VRRP_FLAG) @DFLAGS@
-LDFLAGS = @LIBS@ @LDFLAGS@
-IPVSFLAGS = -D$(IPVS_FLAG) -D@IPVS_SYNCD@
-
-CORE_OBJS = \
-       main.o \
-       memory.o \
-       daemon.o \
-       pidfile.o \
-       utils.o \
-       timer.o \
-       scheduler.o \
-       vector.o \
-       list.o \
-       data.o \
-       parser.o \
-       layer4.o \
-       smtp.o
-
-ifeq ($(IPVS_FLAG),_WITH_LVS_)
-IPVS_OBJS = \
-       check_api.o \
-       check_tcp.o \
-       check_http.o \
-       check_ssl.o \
-       check_misc.o \
-       ipwrapper.o \
-       ipvswrapper.o
-endif
-        
-ifeq ($(VRRP_FLAG),_WITH_VRRP_)
-VRRP_OBJS = \
-       vrrp.o \
-       vrrp_notify.o \
-       vrrp_scheduler.o \
-       vrrp_sync.o \
-       vrrp_netlink.o \
-       vrrp_if.o \
-       vrrp_ipaddress.o \
-       vrrp_ipsecah.o
-endif
-
-ifeq ($(CI_LINUX),_WITH_CI_LINUX_)
-CI_LINUX_OBJ = check_ci.o
-CIFLAGS = -D$(CI_LINUX)
-endif
-
-ifeq ($(KERNEL),_KRNL_2_2_)
-IPVS_OBJS := $(IPVS_OBJS) ipfwwrapper.o
-LIBIPFW = libipfwc/libipfwc.a
-else
-LIBIPVS = libipvs/libipvs.a
-endif
-
-
-OBJS = $(CORE_OBJS) $(IPVS_OBJS) $(VRRP_OBJS) $(CI_LINUX_OBJ) $(LIBIPVS) $(LIBIPFW)
-
-.c.o:
-       $(CC) -o $@ $(CFLAGS) $(IPVSFLAGS) $(CIFLAGS) $(INCLUDE) -c $*.c
-
-all:    $(EXEC)
-       strip $(EXEC)
-       @echo ""
-       cd genhash && $(MAKE)
+all:
+       $(MAKE) -C keepalived
+       $(MAKE) -C genhash
        @echo ""
        @echo "Make complete"
 
-debug:  $(EXEC)
+debug:
+       $(MAKE) -C keepalived debug
        @echo ""
        @echo "Make complete"
 
-$(EXEC): $(OBJS) $(LDFLAGS)
-       $(CC) -o $(EXEC) $(CFLAGS) $(OBJS) $(LDFLAGS)
-
-libipfwc/libipfwc.a:
-       cd libipfwc/ && $(MAKE) libipfwc.a
-libipvs/libipvs.a:
-       cd libipvs/ && $(MAKE) libipvs.a
-
-subclean:
-ifeq ($(KERNEL),_KRNL_2_2_)
-       cd libipfwc/ && $(MAKE) clean
-else
-       cd libipvs/ && $(MAKE) clean
-endif
-       cd genhash/ && $(MAKE) clean
+clean:
+       $(MAKE) -C keepalived clean
+       $(MAKE) -C genhash clean
 
-clean: subclean
-       rm -f core *.o $(EXEC)
-
-subclean-dist:
-       cd genhash/ && $(MAKE) clean-dist
-
-clean-dist: subclean-dist
-       rm -f $(sbindir)/$(EXEC)
-       rm -rf $(keepalived_conf_dir)
-       rm -f $(init_dir)/$(init_script)
+distclean:
+       $(MAKE) -C keepalived distclean
+       $(MAKE) -C genhash distclean
+       rm -f Makefile
 
-mrproper: clean clean-dist
+mrproper: distclean
+       rm -f bin/*
        rm -f config.*
-       rm -f Makefile
-       rm -f genhash/Makefile
 
-subinstall:
-       cd genhash/ && $(MAKE) install
+uninstall:
+       $(MAKE) -C keepalived uninstall
+       $(MAKE) -C genhash uninstall
 
-install: subinstall
-       install -d $(sbindir)
-       install -m 700 $(EXEC) $(sbindir)/
-       install -d $(sysconfdir)/init.d
-       install -m 755 $(init_script) $(sysconfdir)/init.d/
-       install -d $(sysconfdir)/keepalived/samples
-       install -m 644 $(conf_file) $(sysconfdir)/keepalived/
-       install -m 644 samples/* $(sysconfdir)/keepalived/samples/
+install:
+       $(MAKE) -C keepalived install
+       $(MAKE) -C genhash install
diff --git a/TODO b/TODO
index eb73ee4..c143803 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,6 +1,19 @@
 * Insert LDAP, FTP, SSH, IMAP, POP, RADIUS checkers.
 * Add minimum configuration verification (realserver must have
   a checker defined, ...)
-* Add system verification (must have LVS support in kernel, 
-                           must have netlink support in kernel,
-                           must have routing messages in kernel).
+* documentation:
+       - hackers guide
+       - code documentation
+       - users guide
+* code cleanup:
+       - name space cleanup
+       - function returnval check
+       - maybe put *.h files into a ../include directory
+       - maybe add a ../healthcheck directory for the checks
+* more choice with parameters, less hardcoded values:
+       - a general.conf could help, stuff like timeouts and so on
+* functionality:
+       - better startup check mechanism to prevent long debugging sessions
+       - hooks for external checktools. For node-failover
+       - a VTYSH to administrate keepalived on the fly
+       - something I forgot right now :)
diff --git a/VERSION b/VERSION
index d2b13eb..05e8a45 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.6.4
+0.6.6
diff --git a/check_api.c b/check_api.c
deleted file mode 100644 (file)
index a7e28bb..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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:        Checkers registration.
- *
- * Version:     $Id: check_api.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "check_api.h"
-#include "parser.h"
-#include "memory.h"
-#include "utils.h"
-#include "check_misc.h"
-#include "check_tcp.h"
-#include "check_http.h"
-#include "check_ssl.h"
-#ifdef _WITH_CI_LINUX_
-  #include "check_ci.h"
-#endif
-
-extern thread_master *master;
-extern data *conf_data;
-
-/* free checker data */
-static void free_checker(void *data)
-{
-  checker *checker = data;
-  (*checker->free) (checker);
-}
-
-/* dump checker data */
-static void dump_checker(void *data)
-{
-  checker *checker = data;
-  syslog(LOG_INFO, " %s:%d"
-                 , inet_ntop2(CHECKER_RIP(checker))
-                 , ntohs(CHECKER_RPORT(checker)));
-  (*checker->dump) (checker);
-}
-
-/* init the global checkers queue */
-void init_checkers_queue(void)
-{
-  checkers_queue = alloc_list(free_checker, dump_checker);
-}
-
-/* Queue a checker to the checkers_queue */
-void queue_checker(void (*free) (void *), void (*dump) (void *)
-                                        , int (*launch) (struct _thread *)
-                                        , void *data)
-{
-  virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
-  real_server *rs    = LIST_TAIL_DATA(vs->rs);
-  checker *chk       = (checker *)MALLOC(sizeof(checker));
-
-  chk->free    = free;
-  chk->dump    = dump;
-  chk->launch  = launch;
-  chk->vs      = vs;
-  chk->rs      = rs;
-  chk->data    = data;
-
-  /* queue the checker */
-  list_add(checkers_queue, chk);
-}
-
-/* dump the checkers_queue */
-void dump_checkers_queue(void)
-{
-  if (!LIST_ISEMPTY(checkers_queue)) {
-    syslog(LOG_INFO, "------< Health checkers >------");
-    dump_list(checkers_queue);
-  }
-}
-
-/* release the checkers_queue */
-void free_checkers_queue(void)
-{
-  free_list(checkers_queue);
-}
-
-/* register the checker to the global I/O scheduler */
-void register_checkers_thread(void)
-{
-  checker *checker;
-  element e;
-
-  for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) {
-    checker = ELEMENT_DATA(e);
-    thread_add_timer(master, checker->launch
-                           , checker
-                           , BOOTSTRAP_DELAY);
-  }
-}
-
-/* Sync checkers activity with netlink kernel reflection */
-void update_checker_activity(uint32_t address, int enable)
-{
-  checker *checker;
-  element e;
-
-  /* Processing Healthcheckers queue */
-  if (!LIST_ISEMPTY(checkers_queue))
-    for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) {
-      checker = ELEMENT_DATA(e);
-      if (CHECKER_VIP(checker) == address) {
-        if (!CHECKER_ENABLED(checker) && enable) {
-          syslog(LOG_INFO, "Netlink reflector reports IP %s added"
-                         , inet_ntop2(address));
-          syslog(LOG_INFO, "Activating healtchecker for VIP %s"
-                         , inet_ntop2(address));
-        }
-        if (CHECKER_ENABLED(checker) && !enable) {
-          syslog(LOG_INFO, "Netlink reflector reports IP %s removed"
-                         , inet_ntop2(address));
-          syslog(LOG_INFO, "Suspending healtchecker for VIP %s"
-                         , inet_ntop2(address));
-        }
-        checker->enabled = enable;
-      }
-    }
-}
-
-/* Install checkers keywords */
-void install_checkers_keyword(void)
-{
-  install_misc_check_keyword();
-  install_tcp_check_keyword();
-  install_http_check_keyword();
-  install_ssl_check_keyword();
-#ifdef _WITH_CI_LINUX_
-  install_ci_check_keyword();
-#endif
-}
diff --git a/check_ci.c b/check_ci.c
deleted file mode 100644 (file)
index 18c1d6e..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * 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:        CI-LINUX checker. Integration to Compaq Cluster Infrastructure.
- *
- * Version:     $Id: check_ci.c,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
- *
- * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
- *              Aneesh Kumar K.V, <aneesh.kumar@digital.com>
- *
- *              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.
- */
-
-#include "check_ci.h"
-#include "check_api.h"
-#include "memory.h"
-#include "parser.h"
-#include "smtp.h"
-#include "ipwrapper.h"
-
-/* CI nodemap declaration */
-static nodenum_ip_map_t *nodemap;
-
-/* Configuration stream handling */
-void free_ci_check(void *data)
-{
-  if (nodemap) {
-    FREE(nodemap);
-    nodemap = NULL;
-  }
-}
-void dump_ci_check(void *data)
-{
-  syslog(LOG_INFO, "   Keepalive method = CI-LINUX");
-}
-void ci_get_handler(vector strvec)
-{
-  int size = sizeof(nodenum_ip_map_t)*cluster_maxnodes()+1;
-  nodemap = (nodenum_ip_map_t *)ALLOC(size);
-
-  /*
-   * If we can not initialize node map we don t queue a new checker.
-   * The default action if so is:
-   *   The realserver activity will not be monitored by the CI-LINUX
-   *   Healchecker. This mean that this realserver will be present into
-   *   LVS topology even if it is failing.
-   */
-  if (initialize_nodemap(nodemap) < 0) {
-    syslog(LOG_ERR, "[CI-LINUX] Failed to initialize the node map from %s"
-                  , CLUSTERTAB);
-  } else
-    queue_checker(free_ci_check, dump_ci_check
-                               , ci_check_thread
-                               , NULL);
-}
-void install_ci_check_keyword(void)
-{
-  install_keyword("CI-LINUX",  &ci_get_handler);
-}
-
-int initialize_nodemap(nodenum_ip_map_t *nodemap)
-{
-  FILE *fp;
-  char buf[BUFFSIZE];
-  int node_number ;
-
-  if ((fp = fopen(CLUSTERTAB,"r")) == NULL)
-    return -1;
-
-  while (fscanf(fp,"%s",buf) != EOF) {
-    if (buf[0] == '#') {
-      if (fscanf(fp, "%[^\n]", buf) == EOF) {
-        syslog(LOG_ERR, "[CI-LINUX] %s File Format Error", CLUSTERTAB);
-        return -1;
-      }
-      bzero(buf,BUFFSIZE);
-      continue;
-    }
-    node_number = atoi(buf);
-    if (node_number > cluster_maxnodes()) {
-      syslog(LOG_ERR, "[CI-LINUX] Node number greater than MAX node num\n");
-      return -1;
-    }
-    if (fscanf(fp, "%s",buf) == EOF) {
-      syslog(LOG_ERR, "[CI-LINUX] %s File Format Error", CLUSTERTAB);
-      return -1;
-    }
-    inet_ston(buf, &nodemap[node_number].addr_ip);
-    if (fscanf(fp, "%[^\n]", buf) == EOF) {
-      syslog(LOG_ERR, "[CI-LINUX] %s File Format Error", CLUSTERTAB);
-      return -1;
-    }
-    bzero(buf, BUFFSIZE);
-  }
-  return 1;
-}
-
-clusternode_t address_to_nodenum(uint32_t addr_ip)
-{
-  int i ;
-  int max_nodes = cluster_maxnodes();
-
-  for (i = 1; i<= max_nodes; i++) {
-    if (nodemap[i].addr_ip == addr_ip)
-    return i;
-  }
-  return 0; /* Not a valid node */
-}
-
-int nodestatus(uint32_t addr_ip)
-{
-  int node_num;
-  clusternode_info_t ni;
-
-  if ((node_num = address_to_nodenum(addr_ip)) == 0)
-    return UNKNOWN_NODE;
-
-  if (clusternode_info(node_num, sizeof(ni), &ni) >= 0)
-    /*
-     * I am insterested only in two state
-     * either fully up or down.
-     */
-    return (ni.node_state == CLUSTERNODE_UP)?UP:DOWN;
-  else
-    syslog(LOG_ERR, "[CI-LINUX] Error in getting the cluster information");
-
-  return UNKNOWN_NODE;
-}
-
-/* Cluster Infrastructure checker thread */
-int ci_check_thread(thread *thread)
-{
-  checker *checker = THREAD_ARG(thread);
-  int status ;
-
-  /*
-   * Register a new checker thread & return
-   * if checker is disabled
-   */
-  if (!CHECKER_ENABLED(checker)) {
-    thread_add_timer(thread->master, ci_check_thread
-                                   , checker
-                                   , checker->vs->delay_loop);
-    return 0;
-  }
-
-
-  /* Check the CI node status */
-  status = nodestatus(CHECKER_RIP(checker));
-
-  switch(status) {
-    case UP:
-      if (!ISALIVE(checker->rs)) {
-        smtp_alert(thread->master, checker->rs
-                                 , NULL
-                                 , "UP"
-                                 , "=> CI-Linux  CHECK succeed on service <=\n\n");
-        perform_svr_state(UP, checker->vs, checker->rs);
-      }
-      break;
-    case DOWN:
-      if (ISALIVE(checker->rs)) {
-        smtp_alert(thread->master, checker->rs
-                                 , NULL
-                                 , "DOWN"
-                                 , "=> CI-Linux CHECK failed on service <=\n\n");
-        perform_svr_state(DOWN, checker->vs, checker->rs);
-      }
-      break;
-    default:
-      syslog(LOG_ERR,"[CI-LINUX] Unknown node status");
-  }
-
-  /* Register the next check */
-  thread_add_timer(thread->master, ci_check_thread
-                                 , checker
-                                 , checker->vs->delay_loop);
-  return 0;
-}
diff --git a/check_http.c b/check_http.c
deleted file mode 100644 (file)
index 14e9c7c..0000000
+++ /dev/null
@@ -1,746 +0,0 @@
-/*
- * 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:        WEB CHECK. Common HTTP/SSL checker primitives.
- *
- * Version:     $Id: check_http.c,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
- *
- * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
- *              Jan Holmberg, <jan@artech.net>
- *
- *              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.
- */
-
-#include <openssl/err.h>
-#include "check_http.h"
-#include "check_ssl.h"
-#include "check_api.h"
-#include "memory.h"
-#include "parser.h"
-#include "utils.h"
-
-int http_connect_thread(thread *);
-
-/* Configuration stream handling */
-void free_url(void *data)
-{
-  url *url = data;
-  FREE(url->path);
-  FREE(url->digest);
-  FREE(url);
-}
-void dump_url(void *data)
-{
-  url *url = data;
-  syslog(LOG_INFO, "   Checked url = %s, digest = %s"
-                 , url->path
-                 , url->digest);
-}
-void free_http_get_check(void *data)
-{
-  http_get_checker *http_get_chk = CHECKER_DATA(data);
-
-  free_list(http_get_chk->url);
-  FREE(http_get_chk->arg);
-  FREE(http_get_chk);
-  FREE(data);
-}
-void dump_http_get_check(void *data)
-{
-  http_get_checker *http_get_chk = CHECKER_DATA(data);
-
-  if (http_get_chk->proto == PROTO_HTTP)
-    syslog(LOG_INFO, "   Keepalive method = HTTP_GET");
-  else
-    syslog(LOG_INFO, "   Keepalive method = SSL_GET");
-  if (http_get_chk->connection_port)
-    syslog(LOG_INFO, "   Connection port = %d"
-                   , ntohs(http_get_chk->connection_port));
-  syslog(LOG_INFO, "   Connection timeout = %d" , http_get_chk->connection_to);
-  syslog(LOG_INFO, "   Nb get retry = %d" , http_get_chk->nb_get_retry);
-  syslog(LOG_INFO, "   Delay before retry = %d" 
-                 , http_get_chk->delay_before_retry);
-  dump_list(http_get_chk->url);
-}
-static http_get_checker *alloc_http_get(char *proto)
-{
-  http_get_checker *http_get_chk;
-
-  http_get_chk        = (http_get_checker *)MALLOC(sizeof(http_get_checker));
-  http_get_chk->arg   = (http_arg *)MALLOC(sizeof(http_arg));
-  http_get_chk->proto = (!strcmp(proto, "HTTP_GET"))?PROTO_HTTP:PROTO_SSL;
-  http_get_chk->url   = alloc_list(free_url, dump_url);
-
-  return http_get_chk;
-}
-
-void http_get_handler(vector strvec)
-{
-  http_get_checker *http_get_chk;
-  char *str = VECTOR_SLOT(strvec, 0);
-
-  /* queue new checker */
-  http_get_chk = alloc_http_get(str);
-  queue_checker(free_http_get_check, dump_http_get_check
-                                   , http_connect_thread
-                                   , http_get_chk);
-}
-void connect_p_handler(vector strvec)
-{
-  http_get_checker *http_get_chk = CHECKER_GET();
-  http_get_chk->connection_port = htons(CHECKER_VALUE_INT(strvec));
-}
-void connect_to_handler(vector strvec)
-{
-  http_get_checker *http_get_chk = CHECKER_GET();
-  http_get_chk->connection_to = CHECKER_VALUE_INT(strvec);
-}
-void nb_get_retry_handler(vector strvec)
-{
-  http_get_checker *http_get_chk = CHECKER_GET();
-  http_get_chk->nb_get_retry = CHECKER_VALUE_INT(strvec);
-}
-void delay_before_retry_handler(vector strvec)
-{
-  http_get_checker *http_get_chk = CHECKER_GET();
-  http_get_chk->delay_before_retry = CHECKER_VALUE_INT(strvec);
-}
-void url_handler(vector strvec)
-{
-  http_get_checker *http_get_chk = CHECKER_GET();
-  url *new;
-
-  /* allocate the new URL */
-  new = (url *)MALLOC(sizeof(url));
-
-  list_add(http_get_chk->url, new);
-}
-void path_handler(vector strvec)
-{
-  http_get_checker *http_get_chk = CHECKER_GET();
-  url *url = LIST_TAIL_DATA(http_get_chk->url);
-
-  url->path = CHECKER_VALUE_STRING(strvec);
-}
-void digest_handler(vector strvec)
-{
-  http_get_checker *http_get_chk = CHECKER_GET();
-  url *url = LIST_TAIL_DATA(http_get_chk->url);
-
-  url->digest = CHECKER_VALUE_STRING(strvec);
-}
-void install_http_check_keyword(void)
-{
-  install_keyword("HTTP_GET",                  &http_get_handler);
-  install_sublevel();
-    install_keyword("connect_port",            &connect_p_handler);
-    install_keyword("connect_timeout",         &connect_to_handler);
-    install_keyword("nb_get_retry",            &nb_get_retry_handler);
-    install_keyword("delay_before_retry",      &delay_before_retry_handler);
-    install_keyword("url",                     &url_handler);
-    install_sublevel();
-      install_keyword("path",                  &path_handler);
-      install_keyword("digest",                        &digest_handler);
-    install_sublevel_end();
-  install_sublevel_end();
-}
-/* a little code duplication :/ */
-void install_ssl_check_keyword(void)
-{
-  install_keyword("SSL_GET",                   &http_get_handler);
-  install_sublevel();
-    install_keyword("connect_port",            &connect_p_handler);
-    install_keyword("connect_timeout",         &connect_to_handler);
-    install_keyword("nb_get_retry",            &nb_get_retry_handler);
-    install_keyword("delay_before_retry",      &delay_before_retry_handler);
-    install_keyword("url",                     &url_handler);
-    install_sublevel();
-      install_keyword("path",                  &path_handler);
-      install_keyword("digest",                        &digest_handler);
-    install_sublevel_end();
-  install_sublevel_end();
-}
-
-/* 
- * The global design of this checker is the following :
- * 
- * - All the actions are done asynchronously.
- * - All the actions handle timeout connection.
- * - All the actions handle error from low layer to upper
- *   layers.
- * 
- * The global synopsis of the inter-thread-call is :
- *     
- *     http_connect_thread (handle layer4 connect)
- *            v
- *     http_check_thread (handle SSL connect)
- *            v
- *     http_request_thread (send SSL GET request)
- *            v
- *     http_response_thread (initialize read stream step)
- *         /             \
- *        /               \
- *       v                 v
- *  http_read_thread   ssl_read_thread (perform HTTP|SSL stream)
- *       v              v
- *     http_handle_response (next checker thread registration)
- */
-
-uint16_t get_service_port(checker *checker)
-{
-  http_get_checker *http_get_check = CHECKER_ARG(checker);
-  uint16_t addr_port;
-
-  /*
-   *  Set the remote connection port.
-   *  If a specific checker port is specified, we used this.
-   *  If we are balancing all services (host rather than service),
-   *  then assume we want to use default ports for HTTP or HTTPS.
-   *  Known as 'Layer3 stickyness'.
-   */
-  addr_port = CHECKER_RPORT(checker);
-  if (!addr_port)
-    addr_port = htons((http_get_check->proto == PROTO_SSL)?443:80);
-  if (http_get_check->connection_port)
-    addr_port = http_get_check->connection_port;
-  return addr_port;
-}
-
-/*
- * Simple epilog functions. Handling event timeout.
- * Finish the checker with memory managment or url rety check.
- *
- * c == 0 => reset to 0 retry_it counter
- * t == 0 => reset to 0 url_it counter
- * method == 1 => register a new checker thread
- * method == 2 => register a retry on url checker thread
- */
-int epilog(thread *thread, int metod, int t, int c)
-{
-  checker *checker                 = THREAD_ARG(thread);
-  http_get_checker *http_get_check = CHECKER_ARG(checker);
-  http_arg *http_arg               = HTTP_ARG(http_get_check);
-  REQ *req                         = HTTP_REQ(http_arg);
-  int delay = 0;
-  if (metod) {
-    http_arg->url_it   += t ? t : -http_arg->url_it;
-    http_arg->retry_it += c ? c : -http_arg->retry_it;
-  }
-
-  /* register next timer thread */
-  switch (metod) {
-    case 1:
-      if (req)
-        delay = checker->vs->delay_loop;
-      else
-        delay = checker->vs->delay_loop - http_get_check->delay_before_retry;
-      break; 
-    case 2:
-      delay = http_get_check->delay_before_retry;
-      break;
-  }
-
-  /* If req == NULL, fd is not created */
-  if (req) {
-    if (req->ssl)
-      SSL_free(req->ssl);
-    if (req->buffer)
-      FREE(req->buffer);
-    FREE(req);
-    close(thread->u.fd);
-  }
-
-  /* Register next checker thread */
-  thread_add_timer(thread->master, http_connect_thread
-                                 , checker
-                                 , delay);
-  return 0;
-}
-
-int timeout_epilog(thread *thread, char *smtp_msg, char *debug_msg)
-{
-  checker *checker                 = THREAD_ARG(thread);
-  http_get_checker *http_get_check = CHECKER_ARG(checker);
-  http_arg *http_arg               = HTTP_ARG(http_get_check);
-#ifdef _DEBUG_
-  uint16_t addr_port               = get_service_port(checker);
-#endif
-
-  /*
-   * The get retry implementation mean that we retry performing
-   * a GET on the same url until the remote web server return 
-   * html buffer. This is sometime needed with some applications
-   * servers.
-   */
-  if (++http_arg->retry_it <= http_get_check->nb_get_retry) {
-
-#ifdef _DEBUG_
-    syslog(LOG_DEBUG, "Retry %s server [%s:%d] after %d retry."
-                    , debug_msg
-                    , inet_ntop2(CHECKER_RIP(checker))
-                    , ntohs(addr_port)
-                    , http_arg->retry_it - 1);
-#endif
-    return epilog(thread,2,0,1);
-
-  } else {
-
-#ifdef _DEBUG_
-    if (checker->rs)
-      syslog(LOG_DEBUG, "Timeout %s server [%s:%d]."
-                      , debug_msg
-                      , inet_ntop2(CHECKER_RIP(checker))
-                      , ntohs(addr_port));
-#endif
-    /* check if server is currently alive */
-    if (ISALIVE(checker->rs)) {
-      smtp_alert(thread->master, checker->rs
-                               , NULL
-                               , "DOWN"
-                               , smtp_msg);
-      perform_svr_state(DOWN, checker->vs, checker->rs);
-    }
-
-    return epilog(thread,1,0,0);
-  }
-
-  return 0;
-}
-
-/* HTML stream parser primitives */
-/* simple function returning a pointer to the html buffer begin */
-char *extract_html(char *buffer, int size_buffer)
-{
-  char *end = buffer + size_buffer;
-
-  while ( buffer < end &&
-          !(*buffer++ == '\n' &&
-            (*buffer == '\n' || (*buffer ++ == '\r' && *buffer =='\n'))));
-
-  if (*buffer == '\n') return buffer+1;
-  return NULL;
-}
-
-/* return the url pointer of the current url iterator  */
-url *fetch_next_url(http_get_checker *http_get_check)
-{
-  http_arg *http_arg = HTTP_ARG(http_get_check);
-
-  return list_element(http_get_check->url, http_arg->url_it);
-}
-
-/* Handle response */
-int http_handle_response(thread *thread, unsigned char digest[16]
-                                       , int empty_buffer)
-{
-  checker *checker                 = THREAD_ARG(thread);
-  http_get_checker *http_get_check = CHECKER_ARG(checker);
-#ifdef _DEBUG_
-  uint16_t addr_port               = get_service_port(checker);
-  http_arg *http_arg               = HTTP_ARG(http_get_check);
-#endif
-  int r, di = 0;
-  unsigned char *digest_tmp;
-  url *fetched_url;
-  if (empty_buffer) {
-    return timeout_epilog(thread, "=> CHECK failed on service"
-                                  " : empty buffer received <=\n\n"
-                                , "Read, no data received from ");
-  } else {
-    /* Compute MD5SUM */
-    digest_tmp = (char *)MALLOC(MD5_BUFFER_LENGTH+1);
-    for (di=0; di < 16; di++)
-      sprintf(digest_tmp+2*di, "%02x", digest[di]);
-
-    fetched_url = fetch_next_url(http_get_check);
-
-#ifdef _DEBUG_
-    syslog(LOG_DEBUG, "MD5SUM to [%s:%d] url(%d) = [%s]."
-                    , inet_ntop2(CHECKER_RIP(checker))
-                    , ntohs(addr_port)
-                    , http_arg->url_it + 1
-                    , digest_tmp);
-#endif
-
-    r = strcmp(fetched_url->digest, digest_tmp);
-    FREE(digest_tmp);
-
-    if (r) {
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "MD5 digest error to [%s:%d] url(%d)"
-                        ", expecting MD5SUM [%s]."
-                      , inet_ntop2(CHECKER_RIP(checker))
-                      , ntohs(addr_port)
-                      , http_arg->url_it + 1
-                      , fetched_url->digest);
-#endif
-
-      /* check if server is currently alive */
-      if (ISALIVE(checker->rs)) {
-        smtp_alert(thread->master, checker->rs
-                                 , NULL
-                                 , "DOWN"
-                                 , "=> CHECK failed on service"
-                                   " : MD5 digest mismatch <=\n\n");
-        perform_svr_state(DOWN, checker->vs, checker->rs);
-      }
-      return epilog(thread,1,0,0);
-    } else {
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "MD5 digest success to [%s:%d] url(%d)."
-                      , inet_ntop2(CHECKER_RIP(checker))
-                      , ntohs(addr_port)
-                      , http_arg->url_it + 1);
-#endif
-      return epilog(thread,1,1,0)+1;
-    }
-  }
-  return epilog(thread,0,0,0)+1;
-}
-
-/* Asynchronous HTTP stream reader */
-int http_read_thread(thread *thread)
-{
-  checker *checker                 = THREAD_ARG(thread);
-  http_get_checker *http_get_check = CHECKER_ARG(checker);
-  http_arg *http_arg               = HTTP_ARG(http_get_check);
-  REQ *req                         = HTTP_REQ(http_arg);
-#ifdef _DEBUG_
-  uint16_t addr_port               = get_service_port(checker);
-#endif
-  unsigned char digest[16];
-  int r = 0;
-
-  /* Handle read timeout */
-  if (thread->type == THREAD_READ_TIMEOUT)
-    return timeout_epilog(thread, "=> HTTP CHECK failed on service"
-                                  " : recevice data <=\n\n"
-                                , "HTTP read");
-
-  /* read the HTTP stream */
-  r = read(thread->u.fd, req->buffer + req->len
-                       , MAX_BUFFER_LENGTH - req->len);
-
-  if (r == -1 || r == 0) { /* -1:error , 0:EOF */
-
-    /* All the HTTP stream has been parsed */
-    MD5_Final(digest, &req->context);
-
-    if (r == -1) {
-      /* We have encourred a real read error */
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "Read error with server [%s:%d]: %s"
-                      , inet_ntop2(CHECKER_RIP(checker))
-                      , ntohs(addr_port)
-                      , strerror(errno));
-#endif
-      if (ISALIVE(checker->rs)) {
-        smtp_alert(thread->master, checker->rs
-                                 , NULL
-                                 , "DOWN"
-                                 , "=> HTTP CHECK failed on service"
-                                   " : cannot receive data <=\n\n");
-        perform_svr_state(DOWN, checker->vs, checker->rs);
-      }
-      return epilog(thread,1,0,0);
-    }
-
-    /* Handle response stream */
-    http_handle_response(thread, digest, (!req->extracted)?1:0);
-
-  } else {
-
-    req->len += r;
-    if (!req->extracted) {
-      if ((req->extracted = extract_html(req->buffer, req->len))) {
-        r = req->len - (req->extracted-req->buffer);
-        if (r) {
-          memcpy(req->buffer, req->extracted, r);
-          MD5_Update(&req->context, req->buffer, r);
-          r=0;
-        }
-        req->len = r;
-      } else {
-        /* minimize buffer using no 2*CR/LF found yet */
-        if (req->len > 3) {
-          memcpy(req->buffer, req->buffer + req->len - 3, 3);
-          req->len = 3;
-        }
-      }
-    } else {
-      if (req->len) {
-        MD5_Update(&req->context, req->buffer, req->len);
-        req->len = 0;
-      }
-    }
-
-    /*
-     * Register next http stream reader.
-     * Register itself to not perturbe global I/O multiplexer.
-     */
-    thread_add_read(thread->master, http_read_thread
-                                  , checker
-                                  , thread->u.fd
-                                  , http_get_check->connection_to);
-  }
-
-  return 0;
-}
-
-/*
- * Read get result from the remote web server.
- * Apply trigger check to this result.
- */
-int http_response_thread(thread *thread)
-{
-  checker *checker                 = THREAD_ARG(thread);
-  http_get_checker *http_get_check = CHECKER_ARG(checker);
-  http_arg *http_arg               = HTTP_ARG(http_get_check);
-  REQ *req                         = HTTP_REQ(http_arg);
-
-  /* Handle read timeout */
-  if (thread->type == THREAD_READ_TIMEOUT)
-    return timeout_epilog(thread, "=> CHECK failed on service"
-                                  " : recevice data <=\n\n"
-                                , "WEB read");
-
-  /* Allocate & clean the get buffer */
-  req->buffer    = (char *)MALLOC(MAX_BUFFER_LENGTH);
-  req->extracted = NULL;
-  req->len       = 0;
-  req->error     = 0;
-  MD5_Init(&req->context);
-
-  /* Register asynchronous http/ssl read thread */
-  if (http_get_check->proto == PROTO_SSL)
-    thread_add_read(thread->master, ssl_read_thread
-                                  , checker
-                                  , thread->u.fd
-                                  , http_get_check->connection_to);
-  else
-    thread_add_read(thread->master, http_read_thread
-                                  , checker
-                                  , thread->u.fd
-                                  , http_get_check->connection_to);
-  return 0;
-}
-
-/* remote Web server is connected, send it the get url query.  */
-int http_request_thread(thread *thread)
-{
-  checker *checker                 = THREAD_ARG(thread);
-  http_get_checker *http_get_check = CHECKER_ARG(checker);
-  http_arg *http_arg               = HTTP_ARG(http_get_check);
-  REQ *req                         = HTTP_REQ(http_arg);
-  uint16_t addr_port               = get_service_port(checker);
-  char *vhost                      = CHECKER_VHOST(checker);
-  char *str_request;
-  url *fetched_url;
-  int ret = 0;
-
-  /* Handle read timeout */
-  if(thread->type == THREAD_WRITE_TIMEOUT)
-    return timeout_epilog(thread, "=> CHECK failed on service"
-                                  " : read timeout <=\n\n"
-                                , "Web read, timeout");
-
-  /* Allocate & clean the GET string */
-  str_request = (char *)MALLOC(GET_REQUEST_BUFFER_LENGTH);
-
-  fetched_url = fetch_next_url(http_get_check);
-  snprintf(str_request, GET_REQUEST_BUFFER_LENGTH
-                      , REQUEST_TEMPLATE
-                      , fetched_url->path
-                      , (vhost)?vhost:inet_ntop2(CHECKER_RIP(checker))
-                      , ntohs(addr_port));
-#ifdef _DEBUG_
-  syslog(LOG_DEBUG, "Processing url(%d) of [%s:%d]."
-                  , http_arg->url_it + 1
-                  , inet_ntop2(CHECKER_RIP(checker))
-                  , ntohs(addr_port));
-#endif
-
-  /* Send the GET request to remote Web server */
-  if (http_get_check->proto == PROTO_SSL)
-    ret = ssl_send_request(req->ssl, str_request, strlen(str_request));
-  else
-    ret = (send(thread->u.fd, str_request, strlen(str_request), 0) != -1)?1:0;
-
-  FREE(str_request);
-
-  if (!ret) {
-    syslog(LOG_INFO, "Cannot send get request to [%s:%d]."
-                   , inet_ntop2(CHECKER_RIP(checker))
-                   , ntohs(addr_port));
-
-    /* check if server is currently alive */
-    if (ISALIVE(checker->rs)) {
-      smtp_alert(thread->master, checker->rs
-                               , NULL
-                               , "DOWN"
-                               , "=> CHECK failed on service"
-                                 " : cannot send data <=\n\n");
-      perform_svr_state(DOWN, checker->vs, checker->rs);
-    }
-    return epilog(thread,1,0,0);
-  }
-
-  /* Register read timeouted thread */
-  thread_add_read(thread->master, http_response_thread
-                                , checker
-                                , thread->u.fd
-                                , http_get_check->connection_to);
-  return 1;
-}
-
-/* WEB checkers threads */
-int http_check_thread(thread *thread)
-{
-  checker *checker                 = THREAD_ARG(thread);
-  http_get_checker *http_get_check = CHECKER_ARG(checker);
-  uint16_t addr_port               = get_service_port(checker);
-#ifdef _DEBUG_
-  http_arg *http_arg               = HTTP_ARG(http_get_check);
-  REQ *req                         = HTTP_REQ(http_arg);
-#endif
-  int ret = 1;
-  int status;
-
-  status = tcp_socket_state(thread->u.fd, thread
-                                        , CHECKER_RIP(checker)
-                                        , addr_port
-                                        , http_check_thread);
-  switch (status) {
-    case connect_error:
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "Error connecting server [%s:%d]."
-                      , inet_ntop2(CHECKER_RIP(checker))
-                      , ntohs(addr_port));
-#endif
-      /* check if server is currently alive */
-      if (ISALIVE(checker->rs)) {
-        smtp_alert(thread->master, checker->rs
-                                 , NULL
-                                 , "DOWN"
-                                 , "=> CHECK failed on service"
-                                   " : connection error <=\n\n");
-        perform_svr_state(DOWN, checker->vs, checker->rs);
-      }
-      return epilog(thread,1,0,0);
-      break;
-
-    case connect_timeout:
-      return timeout_epilog(thread, "==> CHECK failed on service"
-                                    " : connection timeout <=\n\n"
-                                  , "connect, timeout");
-      break;
-
-    case connect_success: {
-      if (http_get_check->proto == PROTO_SSL)
-        ret = ssl_connect(thread);
-
-      if (ret) {
-        /* Remote WEB server is connected.
-         * Register the next step thread ssl_request_thread.
-         */
-#ifdef _DEBUG_
-        syslog(LOG_DEBUG, "Remote Web server [%s:%d] connected."
-                        , inet_ntop2(CHECKER_RIP(checker))
-                        , ntohs(addr_port));
-#endif
-        thread_add_write(thread->master, http_request_thread
-                                       , checker
-                                       , thread->u.fd
-                                       , http_get_check->connection_to);
-      } else {
-#ifdef _DEBUG_
-        syslog(LOG_DEBUG, "Connection trouble to: [%s:%d]."
-                        , inet_ntop2(CHECKER_RIP(checker))
-                        , ntohs(addr_port));
-        if (http_get_check->proto == PROTO_SSL)
-          ssl_printerr(SSL_get_error(req->ssl, ret));
-#endif
-        return epilog(thread,1,0,0);
-      }
-    }
-    break;
-  }
-
-  return 0;
-}
-
-int http_connect_thread(thread *thread)
-{
-  checker *checker                 = THREAD_ARG(thread);
-  http_get_checker *http_get_check = CHECKER_ARG(checker);
-  http_arg *http_arg               = HTTP_ARG(http_get_check);
-  uint16_t addr_port               = get_service_port(checker);
-  url *fetched_url;
-  enum connect_result status;
-  int fd;
-
-  /*
-   * Register a new checker thread & return
-   * if checker is disabled
-   */
-  if (!CHECKER_ENABLED(checker)) {
-    thread_add_timer(thread->master, http_connect_thread
-                                   , checker
-                                   , checker->vs->delay_loop);
-    return 0;
-  }
-
-  /* Find eventual url end */
-  fetched_url = fetch_next_url(http_get_check);
-
-  if (!fetched_url) {
-    /* All the url have been successfully checked.
-     * Check completed.
-     * check if server is currently alive.
-     */
-    if (!ISALIVE(checker->rs)) {
-      smtp_alert(thread->master, checker->rs
-                               , NULL
-                               , "UP"
-                               , "=> CHECK succeed on service <=\n\n");
-      perform_svr_state(UP, checker->vs, checker->rs);
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "Remote Web server [%s:%d] succeed on service."
-                      , inet_ntop2(CHECKER_RIP(checker))
-                      , ntohs(addr_port));
-#endif
-    }
-    http_arg->req = NULL;
-    return epilog(thread,1,0,0)+1;
-  }
-
-  /* Allocate & clean request struct */
-  http_arg->req = (REQ *)MALLOC(sizeof(REQ));
-
-  if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
-#ifdef _DEBUG_
-    syslog(LOG_DEBUG, "WEB connection fail to create socket.");
-#endif
-    return 0;
-  }
-
-  status = tcp_connect(fd, CHECKER_RIP(checker), addr_port);
-
-  /* handle tcp connection status & register check worker thread */
-  tcp_connection_state(fd, status, thread
-                                 , http_check_thread
-                                 , http_get_check->connection_to);
-  return 0;
-}
diff --git a/check_misc.c b/check_misc.c
deleted file mode 100644 (file)
index f720a46..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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:        MISC CHECK. Perform a system call to run an extra
- *              system prog or script.
- *
- * Version:     $Id: check_misc.c,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
- *
- * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
- *              Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
- *
- *              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.
- */
-
-#include "check_misc.h"
-#include "check_api.h"
-#include "memory.h"
-#include "ipwrapper.h"
-#include "smtp.h"
-#include "utils.h"
-#include "parser.h"
-#include "daemon.h"
-
-int misc_check_thread(thread *);
-
-/* Configuration stream handling */
-void free_misc_check(void *data)
-{
-  misc_checker *misc_chk = CHECKER_DATA(data);
-
-  FREE(misc_chk->path);
-  FREE(misc_chk);
-  FREE(data);
-}
-void dump_misc_check(void *data)
-{
-  misc_checker *misc_chk = CHECKER_DATA(data);
-
-  syslog(LOG_INFO, "   Keepalive method = MISC_CHECK");
-  syslog(LOG_INFO, "   script = %s"
-                 , misc_chk->path);
-}
-void misc_check_handler(vector strvec)
-{
-  misc_checker *misc_chk = (misc_checker *)MALLOC(sizeof(misc_checker));
-
-  /* queue new checker */
-  queue_checker(free_misc_check, dump_misc_check
-                               , misc_check_thread
-                               , misc_chk);
-}
-void misc_path_handler(vector strvec)
-{
-  misc_checker *misc_chk = CHECKER_GET();
-
-  misc_chk->path = CHECKER_VALUE_STRING(strvec);
-}
-void install_misc_check_keyword(void)
-{
-  install_keyword("MISC_CHECK", &misc_check_handler);
-  install_sublevel();
-    install_keyword("misc_path", &misc_path_handler);
-  install_sublevel_end();
-}
-
-int misc_check_call(char* cmdline)
-{
-  int retval;
-
-  retval = system(cmdline);
-
-  if (retval == 127) {
-    /* couldn't exec command */
-    syslog(LOG_DEBUG, "Couldn't exec command: %s", cmdline);
-  } else if (retval == -1) {
-    /* other error */
-    syslog(LOG_DEBUG, "Error exec-ing command: %s", cmdline);
-  } else {
-    /* everything is good */
-    syslog(LOG_DEBUG, "Successfully exec command: %s retval is %d"
-                    , cmdline, retval);
-  }
-
-  return retval;
-}
-
-int misc_check_thread(thread *thread)
-{
-  checker *checker;
-  misc_checker *misc_chk;
-  int status;
-
-  checker  = THREAD_ARG(thread);
-  misc_chk = CHECKER_ARG(checker);
-
-  /* Register next timer checker */
-  thread_add_timer(thread->master, misc_check_thread
-                                 , checker
-                                 , checker->vs->delay_loop);
-  /*
-   * Register a new checker thread & return
-   * if checker is disabled
-   */
-  if (!CHECKER_ENABLED(checker))
-    return 0;
-
-  /* Daemonization to not degrade our scheduling timer */
-  if (xdaemon(0, 0, 1))
-    return 0x80000000;
-
-  status = misc_check_call(misc_chk->path);
-
-  if (status >= 0) { /* script error assumed  not an svr error */
-    if (status == 0) {
-      /* everything is good */
-      if (!checker->rs->alive) {
-        smtp_alert(thread->master, checker->rs
-                                 , NULL
-                                 , "UP"
-                                 , "=> MISC CHECK succeed on service <=\n\n");
-        perform_svr_state(UP, checker->vs, checker->rs);
-      }
-    } else {
-      if (checker->rs->alive) {
-        smtp_alert(thread->master, checker->rs
-                                 , NULL
-                                 , "DOWN"
-                                 , "=> MISC CHECK failed on service <=\n\n");
-        perform_svr_state(DOWN, checker->vs, checker->rs);
-      }
-    }
-  }
-
-  exit(0);
-}
diff --git a/check_ssl.c b/check_ssl.c
deleted file mode 100644 (file)
index 17803a9..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * 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:        SSL GET CHECK. Perform an ssl get query to a specified
- *              url, compute a MD5 over this result and match it to the
- *              expected value.
- *
- * Version:     $Id: check_ssl.c,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
- *
- * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
- *              Jan Holmberg, <jan@artech.net>
- *
- *              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.
- */
-
-#include <openssl/err.h>
-#include "check_ssl.h"
-#include "check_api.h"
-#include "memory.h"
-#include "parser.h"
-#include "smtp.h"
-#include "utils.h"
-
-extern data *conf_data;
-
-/* SSL primitives */
-/* Free an SSL context */
-void clear_ssl(SSL_DATA *ssl)
-{
-  if (ssl)
-    if (ssl->ctx)
-      SSL_CTX_free(ssl->ctx);
-}
-
-/* PEM password callback function */
-static int password_cb(char *buf, int num, int rwflag, void *userdata)
-{
-  SSL_DATA *ssl = (SSL_DATA *)userdata;
-
-  if (num < strlen(ssl->password)+1)
-    return(0);
-
-  strcpy(buf, ssl->password);
-  return(strlen(ssl->password));
-}
-
-/* Inititalize global SSL context */
-static BIO *bio_err = 0;
-static int build_ssl_ctx(void)
-{
-  SSL_DATA *ssl;
-
-  /* Library initialization */
-  SSL_library_init();
-
-  SSL_load_error_strings();
-  bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
-
-  if (!conf_data->ssl)
-    ssl = (SSL_DATA *)MALLOC(sizeof(ssl_data));
-  else
-    ssl = conf_data->ssl;
-
-  /* Initialize SSL context for SSL v2/3 */
-  ssl->meth = SSLv23_method();
-  ssl->ctx  = SSL_CTX_new(ssl->meth);
-
-  /* return for autogen context */
-  if (!conf_data->ssl) {
-    conf_data->ssl = ssl;
-    goto end;
-  }
-
-  /* Load our keys and certificates */
-  if (conf_data->ssl->keyfile)
-    if (!(SSL_CTX_use_certificate_chain_file(ssl->ctx, conf_data->ssl->keyfile))) {
-      syslog(LOG_INFO, "SSL error : Cant load certificate file...");
-      return 0;
-    }
-
-  /* Handle password callback using userdata ssl */
-  if (conf_data->ssl->password) {
-    SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, conf_data->ssl);
-    SSL_CTX_set_default_passwd_cb(ssl->ctx, password_cb);
-  }
-
-  if (conf_data->ssl->keyfile)
-    if (!(SSL_CTX_use_PrivateKey_file(ssl->ctx, conf_data->ssl->keyfile
-                                              , SSL_FILETYPE_PEM))) {
-      syslog(LOG_INFO, "SSL error : Cant load key file...");
-      return 0;
-    }
-
-  /* Load the CAs we trust */
-  if (conf_data->ssl->cafile)
-    if (!(SSL_CTX_load_verify_locations(ssl->ctx, conf_data->ssl->cafile, 0))) {
-      syslog(LOG_INFO, "SSL error : Cant load CA file...");
-      return 0;
-    }
-
-end:
-#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
-  SSL_CTX_set_verify_depth(ssl->ctx, 1);
-#endif
-
-  return 1;
-}
-
-/*
- * Initialize the SSL context, with or without specific
- * configuration files.
- */
-int init_ssl_ctx(void)
-{
-  SSL_DATA *ssl = conf_data->ssl;
-
-  if (!build_ssl_ctx()) {
-    syslog(LOG_INFO, "Error Initialize SSL, ctx Instance");
-    syslog(LOG_INFO, "  SSL  keyfile:%s", ssl->keyfile);
-    syslog(LOG_INFO, "  SSL password:%s", ssl->password);
-    syslog(LOG_INFO, "  SSL   cafile:%s", ssl->cafile);
-    syslog(LOG_INFO, "Terminate...\n");
-    clear_ssl(ssl);
-    return 0;
-  }
-  return 1;
-}
-
-/* Display SSL error to readable string */
-int ssl_printerr(int err)
-{
-  unsigned long extended_error = 0;
-  char *ssl_strerr;
-
-  switch (err) {
-    case SSL_ERROR_ZERO_RETURN:
-      syslog(LOG_DEBUG, "  SSL error: (zero return)");
-      break;
-    case SSL_ERROR_WANT_READ:
-      syslog(LOG_DEBUG, "  SSL error: (read error)");
-      break;
-    case SSL_ERROR_WANT_WRITE:
-      syslog(LOG_DEBUG, "  SSL error: (write error)");
-      break;
-    case SSL_ERROR_WANT_CONNECT:
-      syslog(LOG_DEBUG, "  SSL error: (connect error)");
-      break;
-    case SSL_ERROR_WANT_X509_LOOKUP:
-      syslog(LOG_DEBUG, "  SSL error: (X509 lookup error)");
-      break;
-    case SSL_ERROR_SYSCALL:
-      syslog(LOG_DEBUG, "  SSL error: (syscall error)");
-      break;
-    case SSL_ERROR_SSL: {
-      ssl_strerr = (char *)MALLOC(500);
-
-      extended_error = ERR_get_error();
-      ERR_error_string(extended_error, ssl_strerr);
-      syslog(LOG_DEBUG, "  SSL error: (%s)", ssl_strerr);
-      FREE(ssl_strerr);
-      break;
-    }
-  }
-  return 0;
-}
-
-int ssl_connect(thread *thread)
-{
-  checker *checker                 = THREAD_ARG(thread);
-  http_get_checker *http_get_check = CHECKER_ARG(checker);
-  http_arg *http_arg               = HTTP_ARG(http_get_check);
-  REQ *req                         = HTTP_REQ(http_arg);
-
-  req->ssl = SSL_new(conf_data->ssl->ctx);
-  req->bio = BIO_new_socket(thread->u.fd, BIO_NOCLOSE);
-  SSL_set_bio(req->ssl, req->bio, req->bio);
-
-  return (SSL_connect(req->ssl) > 0)?1:0;
-}
-
-int ssl_send_request(SSL *ssl, char *str_request, int request_len)
-{
-  int err, r = 0;
-
-  while (1) {
-    err = 1;
-    r = SSL_write(ssl, str_request, request_len);
-    if (SSL_ERROR_NONE != SSL_get_error(ssl, r))
-      break;
-    err++;
-    if (request_len != r)
-      break;
-    err++;
-    break;
-  }
-
-  return (err == 3)?1:0;
-}
-
-/* Asynchronous SSL stream reader */
-int ssl_read_thread(thread *thread)
-{
-  checker *checker                 = THREAD_ARG(thread);
-  http_get_checker *http_get_check = CHECKER_ARG(checker);
-  http_arg *http_arg               = HTTP_ARG(http_get_check);
-  REQ *req                         = HTTP_REQ(http_arg);
-  unsigned char digest[16];
-  int r = 0;
-
-  /* Handle read timeout */
-  if (thread->type == THREAD_READ_TIMEOUT &&
-      !req->extracted)
-    return timeout_epilog(thread, "=> SSL CHECK failed on service"
-                                  " : recevice data <=\n\n"
-                                , "SSL read");
-
-  /* read the SSL stream */
-  r = SSL_read(req->ssl, req->buffer + req->len
-                       , MAX_BUFFER_LENGTH - req->len);
-  req->error = SSL_get_error(req->ssl, r);
-
-  if (req->error) {
-
-    /* All the SSL streal has been parsed */
-    MD5_Final(digest, &req->context);
-    SSL_set_quiet_shutdown(req->ssl, 1); 
-
-    r = (req->error == SSL_ERROR_ZERO_RETURN) ? SSL_shutdown(req->ssl) : 0;
-
-    if (r && !req->extracted) {
-      /* check if server is currently alive */
-      if (ISALIVE(checker->rs)) {
-        smtp_alert(thread->master, checker->rs
-                                 , NULL
-                                 , "DOWN"
-                                 , "=> SSL CHECK failed on service"
-                                   " : cannot receive data <=\n\n");
-        perform_svr_state(DOWN, checker->vs, checker->rs);
-      }
-      return epilog(thread,1,0,0);
-    }
-
-    /* Handle response stream */
-    http_handle_response(thread, digest, (!req->extracted)?1:0);
-
-  } else if (r > 0 && req->error == 0) {
-
-    req->len += r;
-    if (!req->extracted) {
-       if ((req->extracted = extract_html(req->buffer, req->len))) { 
-         r = req->len-(req->extracted-req->buffer);
-         if (r) {
-           memcpy(req->buffer, req->extracted, r);
-           MD5_Update(&req->context, req->buffer, r);
-           r=0;
-         }
-         req->len = r;
-       } else {
-         /* minimize buffer using no 2*CR/LF found yet */
-         if (req->len > 3) {
-           memcpy(req->buffer, req->buffer + req->len - 3, 3);
-           req->len = 3;
-         }
-       }
-    } else {
-      if (req->len) {
-        MD5_Update(&req->context, req->buffer, req->len);
-        req->len = 0;
-      }
-    }
-
-    /*
-     * Register next ssl stream reader.
-     * Register itself to not perturbe global I/O multiplexer.
-     */
-    thread_add_read(thread->master, ssl_read_thread
-                                  , checker
-                                  , thread->u.fd
-                                  , http_get_check->connection_to);
-  }
-
-  return 0;
-}
diff --git a/check_tcp.c b/check_tcp.c
deleted file mode 100644 (file)
index 98b8bde..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * 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:        TCP checker.
- *
- * Version:     $Id: check_tcp.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "check_tcp.h"
-#include "check_api.h"
-#include "memory.h"
-#include "ipwrapper.h"
-#include "layer4.h"
-#include "smtp.h"
-#include "utils.h"
-#include "parser.h"
-
-int tcp_connect_thread(thread *);
-
-/* Configuration stream handling */
-void free_tcp_check(void *data)
-{
-  tcp_checker *tcp_chk = CHECKER_DATA(data);
-
-  FREE(tcp_chk);
-  FREE(data);
-}
-void dump_tcp_check(void *data)
-{
-  tcp_checker *tcp_chk = CHECKER_DATA(data);
-
-  syslog(LOG_INFO, "   Keepalive method = TCP_CHECK");
-  if (tcp_chk->connection_port)
-    syslog(LOG_INFO, "   Connection port = %d"
-                   , ntohs(tcp_chk->connection_port));
-  syslog(LOG_INFO, "   Connection timeout = %d"
-                 , tcp_chk->connection_to);
-}
-void tcp_check_handler(vector strvec)
-{
-  tcp_checker *tcp_chk = (tcp_checker *)MALLOC(sizeof(tcp_checker));
-
-  /* queue new checker */
-  queue_checker(free_tcp_check, dump_tcp_check
-                              , tcp_connect_thread
-                              , tcp_chk);
-}
-void connect_port_handler(vector strvec)
-{
-  tcp_checker *tcp_chk = CHECKER_GET();
-  tcp_chk->connection_port = htons(CHECKER_VALUE_INT(strvec));
-}
-void connect_timeout_handler(vector strvec)
-{
-  tcp_checker *tcp_chk = CHECKER_GET();
-  tcp_chk->connection_to = CHECKER_VALUE_INT(strvec);
-}
-void install_tcp_check_keyword(void)
-{
-  install_keyword("TCP_CHECK",         &tcp_check_handler);
-  install_sublevel();
-    install_keyword("connect_port",    &connect_port_handler);
-    install_keyword("connect_timeout", &connect_timeout_handler);
-  install_sublevel_end();
-}
-
-int tcp_check_thread(thread *thread)
-{
-  checker *checker;
-  tcp_checker *tcp_check;
-  uint16_t addr_port;
-  int status;
-
-  checker = THREAD_ARG(thread);
-  tcp_check = CHECKER_ARG(checker);
-
-  addr_port = CHECKER_RPORT(checker);
-  if (tcp_check->connection_port)
-    addr_port = tcp_check->connection_port;
-  status = tcp_socket_state(thread->u.fd, thread
-                                        , CHECKER_RIP(checker)
-                                        , addr_port
-                                        , tcp_check_thread);
-
-  /* If status = connect_success, TCP connection to remote host is established.
-   * Otherwise we have a real connection error or connection timeout.
-   */
-  if (status == connect_success) {
-
-#ifdef _DEBUG_
-    syslog(LOG_DEBUG, "TCP connection to [%s:%d] success."
-                    ,  inet_ntop2(CHECKER_RIP(checker))
-                    ,  ntohs(addr_port));
-#endif
-    close(thread->u.fd);
-
-    if (!ISALIVE(checker->rs)) {
-      smtp_alert(thread->master, checker->rs
-                               , NULL
-                               , "UP"
-                               , "=> TCP CHECK succeed on service <=\n\n");
-      perform_svr_state(UP, checker->vs, checker->rs);
-    }
-
-  } else {
-#ifdef _DEBUG_
-    syslog(LOG_DEBUG, "TCP connection to [%s:%d] failed !!!"
-                    ,  inet_ntop2(CHECKER_RIP(checker))
-                    ,  ntohs(addr_port));
-#endif
-
-    if (ISALIVE(checker->rs)) {
-      smtp_alert(thread->master, checker->rs
-                               , NULL
-                               , "DOWN"
-                               , "=> TCP CHECK failed on service <=\n\n");
-      perform_svr_state(DOWN, checker->vs, checker->rs);
-    }
-
-  }
-
-  /* Register next timer checker */
-  if (status != connect_in_progress)
-    thread_add_timer(thread->master, tcp_connect_thread
-                                   , checker
-                                   , checker->vs->delay_loop);
-  return 0;
-}
-
-int tcp_connect_thread(thread *thread)
-{
-  checker *checker;
-  tcp_checker *tcp_check;
-  int fd;
-  uint16_t addr_port;
-  int status;
-
-  checker   = THREAD_ARG(thread);
-  tcp_check = CHECKER_ARG(checker);
-
-  /*
-   * Register a new checker thread & return
-   * if checker is disabled
-   */
-  if (!CHECKER_ENABLED(checker)) {
-    thread_add_timer(thread->master, tcp_connect_thread
-                                   , checker
-                                   , checker->vs->delay_loop);
-    return 0;
-  }
-
-  if ( (fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
-#ifdef _DEBUG_
-    syslog(LOG_DEBUG, "TCP connect fail to create socket.");
-#endif
-    return 0;
-  }
-
-  addr_port = CHECKER_RPORT(checker);
-  if (tcp_check->connection_port)
-    addr_port = tcp_check->connection_port;
-  status = tcp_connect(fd, CHECKER_RIP(checker), addr_port);
-
-  /* handle tcp connection status & register check worker thread */
-  tcp_connection_state(fd, status, thread
-                                 , tcp_check_thread
-                                 , tcp_check->connection_to);
-  return 0;
-}
index a6fd48f..4195116 100755 (executable)
--- a/configure
+++ b/configure
@@ -463,7 +463,7 @@ echo > confdefs.h
 
 # A filename unique to this package, relative to the directory that
 # configure is in, which we can look for to find out if srcdir is correct.
-ac_unique_file=scheduler.c
+ac_unique_file=keepalived/core/main.c
 
 # Find the source files, if location was not specified.
 if test -z "$srcdir"; then
@@ -534,11 +534,12 @@ fi
 
 
 VERSION=`cat VERSION`
+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:542: checking for $ac_word" >&5
+echo "configure:543: 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
@@ -568,7 +569,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:572: checking for $ac_word" >&5
+echo "configure:573: 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
@@ -619,7 +620,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:623: checking for $ac_word" >&5
+echo "configure:624: 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
@@ -651,7 +652,7 @@ fi
 fi
 
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:655: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:656: 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.
@@ -662,12 +663,12 @@ cross_compiling=$ac_cv_prog_cc_cross
 
 cat > conftest.$ac_ext << EOF
 
-#line 666 "configure"
+#line 667 "configure"
 #include "confdefs.h"
 
 main(){return(0);}
 EOF
-if { (eval echo configure:671: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:672: \"$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
@@ -693,12 +694,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:697: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:698: 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:702: checking whether we are using GNU C" >&5
+echo "configure:703: 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
@@ -707,7 +708,7 @@ else
   yes;
 #endif
 EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:711: \"$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:712: \"$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
@@ -726,7 +727,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:730: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:731: 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
@@ -788,7 +789,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:792: checking for a BSD compatible install" >&5
+echo "configure:793: 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
@@ -883,7 +884,7 @@ fi
 
 
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:887: checking how to run the C preprocessor" >&5
+echo "configure:888: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -898,13 +899,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 902 "configure"
+#line 903 "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:908: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:909: \"$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
   :
@@ -915,13 +916,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 919 "configure"
+#line 920 "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:925: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:926: \"$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
   :
@@ -932,13 +933,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -nologo -E"
   cat > conftest.$ac_ext <<EOF
-#line 936 "configure"
+#line 937 "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:942: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:943: \"$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
   :
@@ -963,12 +964,12 @@ fi
 echo "$ac_t""$CPP" 1>&6
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:967: checking for ANSI C header files" >&5
+echo "configure:968: 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 972 "configure"
+#line 973 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -976,7 +977,7 @@ else
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:980: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:981: \"$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*
@@ -993,7 +994,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 997 "configure"
+#line 998 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -1011,7 +1012,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 1015 "configure"
+#line 1016 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -1032,7 +1033,7 @@ if test "$cross_compiling" = yes; then
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 1036 "configure"
+#line 1037 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1043,7 +1044,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
 exit (0); }
 
 EOF
-if { (eval echo configure:1047: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1048: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -1067,12 +1068,12 @@ EOF
 fi
 
 echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
-echo "configure:1071: checking for sys/wait.h that is POSIX.1 compatible" >&5
+echo "configure:1072: 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 1076 "configure"
+#line 1077 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -1088,7 +1089,7 @@ wait (&s);
 s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
 ; return 0; }
 EOF
-if { (eval echo configure:1092: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1093: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_header_sys_wait_h=yes
 else
@@ -1112,17 +1113,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:1116: checking for $ac_hdr" >&5
+echo "configure:1117: 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 1121 "configure"
+#line 1122 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1126: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1127: \"$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*
@@ -1152,17 +1153,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:1156: checking for $ac_hdr" >&5
+echo "configure:1157: 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 1161 "configure"
+#line 1162 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1166: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1167: \"$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*
@@ -1196,17 +1197,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:1200: checking for $ac_hdr" >&5
+echo "configure:1201: 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 1205 "configure"
+#line 1206 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1210: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1211: \"$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*
@@ -1236,7 +1237,7 @@ done
 fi
 
 echo $ac_n "checking for MD5_Init in -lcrypto""... $ac_c" 1>&6
-echo "configure:1240: checking for MD5_Init in -lcrypto" >&5
+echo "configure:1241: 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
@@ -1244,7 +1245,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lcrypto  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1248 "configure"
+#line 1249 "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
@@ -1255,7 +1256,7 @@ int main() {
 MD5_Init()
 ; return 0; }
 EOF
-if { (eval echo configure:1259: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1260: \"$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
@@ -1284,7 +1285,7 @@ else
 fi
 
 echo $ac_n "checking for SSL_CTX_new in -lssl""... $ac_c" 1>&6
-echo "configure:1288: checking for SSL_CTX_new in -lssl" >&5
+echo "configure:1289: 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
@@ -1292,7 +1293,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lssl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1296 "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
@@ -1303,7 +1304,7 @@ int main() {
 SSL_CTX_new()
 ; return 0; }
 EOF
-if { (eval echo configure:1307: \"$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
@@ -1332,7 +1333,7 @@ else
 fi
 
 echo $ac_n "checking for poptGetContext in -lpopt""... $ac_c" 1>&6
-echo "configure:1336: checking for poptGetContext in -lpopt" >&5
+echo "configure:1337: 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
@@ -1340,7 +1341,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lpopt  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1344 "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
@@ -1351,7 +1352,7 @@ int main() {
 poptGetContext()
 ; return 0; }
 EOF
-if { (eval echo configure:1355: \"$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
@@ -1381,7 +1382,7 @@ fi
 
 if test "${ci_linux}" = "yes"; then
   echo $ac_n "checking for cluster_maxnodes in -lcluster""... $ac_c" 1>&6
-echo "configure:1385: checking for cluster_maxnodes in -lcluster" >&5
+echo "configure:1386: 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
@@ -1389,7 +1390,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lcluster  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1393 "configure"
+#line 1394 "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
@@ -1400,7 +1401,7 @@ int main() {
 cluster_maxnodes()
 ; return 0; }
 EOF
-if { (eval echo configure:1404: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1405: \"$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
@@ -1433,7 +1434,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:1437: checking for kernel >= 2.4.0" >&5
+echo "configure:1438: checking for kernel >= 2.4.0" >&5
 if test "$cross_compiling" = yes; then
   
     KERN="_KRNL_2_2_"
@@ -1441,7 +1442,7 @@ if test "$cross_compiling" = yes; then
   
 else
   cat > conftest.$ac_ext <<EOF
-#line 1445 "configure"
+#line 1446 "configure"
 #include "confdefs.h"
 
   #include <stdlib.h>
@@ -1454,7 +1455,7 @@ else
   #endif
   }
 EOF
-if { (eval echo configure:1458: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1459: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   
     KERN="_KRNL_2_4_"
@@ -1478,17 +1479,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:1482: checking for net/ip_vs.h" >&5
+echo "configure:1483: 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 1487 "configure"
+#line 1488 "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:1492: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1493: \"$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*
@@ -1520,7 +1521,7 @@ fi
 
 if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
   echo $ac_n "checking for IPVS version""... $ac_c" 1>&6
-echo "configure:1524: checking for IPVS version" >&5
+echo "configure:1525: checking for IPVS version" >&5
   if test "$cross_compiling" = yes; then
   
     IPVS_MAJOR="0"
@@ -1529,7 +1530,7 @@ echo "configure:1524: checking for IPVS version" >&5
   
 else
   cat > conftest.$ac_ext <<EOF
-#line 1533 "configure"
+#line 1534 "configure"
 #include "confdefs.h"
  
     #include <stdlib.h>
@@ -1544,7 +1545,7 @@ else
     } 
   
 EOF
-if { (eval echo configure:1548: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1549: \"$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`
@@ -1603,7 +1604,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:1607: checking for LVS syncd support" >&5
+echo "configure:1608: 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
@@ -1626,12 +1627,12 @@ fi
 
 
 echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:1630: checking for working const" >&5
+echo "configure:1631: 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 1635 "configure"
+#line 1636 "configure"
 #include "confdefs.h"
 
 int main() {
@@ -1680,7 +1681,7 @@ ccp = (char const *const *) p;
 
 ; return 0; }
 EOF
-if { (eval echo configure:1684: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1685: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_const=yes
 else
@@ -1701,12 +1702,12 @@ EOF
 fi
 
 echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:1705: checking for pid_t" >&5
+echo "configure:1706: 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 1710 "configure"
+#line 1711 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -1734,12 +1735,12 @@ EOF
 fi
 
 echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:1738: checking whether time.h and sys/time.h may both be included" >&5
+echo "configure:1739: 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 1743 "configure"
+#line 1744 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/time.h>
@@ -1748,7 +1749,7 @@ int main() {
 struct tm *tp;
 ; return 0; }
 EOF
-if { (eval echo configure:1752: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1753: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_header_time=yes
 else
@@ -1771,13 +1772,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:1775: checking whether ${CC-cc} needs -traditional" >&5
+echo "configure:1776: 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 1781 "configure"
+#line 1782 "configure"
 #include "confdefs.h"
 #include <sgtty.h>
 Autoconf TIOCGETP
@@ -1795,7 +1796,7 @@ rm -f conftest*
 
   if test $ac_cv_prog_gcc_traditional = no; then
     cat > conftest.$ac_ext <<EOF
-#line 1799 "configure"
+#line 1800 "configure"
 #include "confdefs.h"
 #include <termio.h>
 Autoconf TCGETA
@@ -1817,12 +1818,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:1821: checking return type of signal handlers" >&5
+echo "configure:1822: 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 1826 "configure"
+#line 1827 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -1839,7 +1840,7 @@ int main() {
 int i;
 ; return 0; }
 EOF
-if { (eval echo configure:1843: \"$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_type_signal=void
 else
@@ -1860,12 +1861,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:1864: checking for $ac_func" >&5
+echo "configure:1865: 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 1869 "configure"
+#line 1870 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -1888,7 +1889,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:1892: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1893: \"$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
@@ -1913,6 +1914,14 @@ fi
 done
 
 
+OUTPUT_TARGET="$OUTPUT_TARGET keepalived/Makefile keepalived/healthcheck/Makefile keepalived/vrrp/Makefile"
+if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
+  if test "$KERN" = "_KRNL_2_4_"; then
+    OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipvs/Makefile"
+  else
+    OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipfwc/Makefile"
+  fi
+fi
 trap '' 1 2 15
 cat > confcache <<\EOF
 # This file is a shell script that caches the results of configure
@@ -2026,7 +2035,7 @@ done
 ac_given_srcdir=$srcdir
 ac_given_INSTALL="$INSTALL"
 
-trap 'rm -fr `echo "Makefile genhash/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+trap 'rm -fr `echo "$OUTPUT_TARGET" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
 EOF
 cat >> $CONFIG_STATUS <<EOF
 
@@ -2110,7 +2119,7 @@ EOF
 
 cat >> $CONFIG_STATUS <<EOF
 
-CONFIG_FILES=\${CONFIG_FILES-"Makefile genhash/Makefile"}
+CONFIG_FILES=\${CONFIG_FILES-"$OUTPUT_TARGET"}
 EOF
 cat >> $CONFIG_STATUS <<\EOF
 for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
@@ -2182,6 +2191,7 @@ rm -fr confdefs* $ac_clean_files
 test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
 
 
+
 cat <<EOF;
 
 Keepalived configuration
index be838c0..38b346b 100644 (file)
@@ -7,8 +7,9 @@
 # Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
 
 dnl ----[ Process this file with autoconf to produce a configure script ]----
-AC_INIT(scheduler.c)
+AC_INIT(keepalived/core/main.c)
 VERSION=`cat VERSION`
+OUTPUT_TARGET="Makefile genhash/Makefile keepalived/core/Makefile"
 
 dnl ----[ Checks for programs ]----
 AC_PROG_CC
@@ -189,8 +190,19 @@ dnl AC_FUNC_MEMCMP
 AC_TYPE_SIGNAL
 AC_CHECK_FUNCS(gettimeofday select socket strerror strtol uname)
 
-AC_OUTPUT(Makefile genhash/Makefile)
+dnl ----[ Process output target ]----
+OUTPUT_TARGET="$OUTPUT_TARGET keepalived/Makefile keepalived/healthcheck/Makefile keepalived/vrrp/Makefile"
+if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
+  if test "$KERN" = "_KRNL_2_4_"; then
+    OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipvs/Makefile"
+  else
+    OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipfwc/Makefile"
+  fi
+fi
+AC_OUTPUT($OUTPUT_TARGET)
+
 
+dnl ----[ Display current configuration ]----
 cat <<EOF;
 
 Keepalived configuration
diff --git a/data.c b/data.c
deleted file mode 100644 (file)
index 8a85dbe..0000000
--- a/data.c
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * 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:        Dynamic data structure definition.
- *
- * Version:     $Id: data.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "data.h"
-#include "memory.h"
-#include "utils.h"
-#include "check_api.h"
-#include "vrrp.h"
-#include "vrrp_sync.h"
-
-extern data *conf_data;
-
-/* email facility functions */
-static void free_email(void *data)
-{
-  FREE(data);
-}
-static void dump_email(void *data)
-{
-  char *addr = data;
-  syslog(LOG_INFO, " Email notification = %s", addr);
-}
-void alloc_email(char *addr)
-{
-  int size = strlen(addr);
-  char *new;
-
-  new = (char *)MALLOC(size+1);
-  memcpy(new, addr, size);
-
-  list_add(conf_data->email, new);
-}
-
-/* SSL facility functions */
-SSL_DATA *alloc_ssl(void)
-{
-  SSL_DATA *ssl = (SSL_DATA *)MALLOC(sizeof(SSL_DATA));
-  return ssl;
-}
-static void free_ssl(void)
-{
-  SSL_DATA *ssl = conf_data->ssl;
-
-  if (!ssl) return;
-  FREE_PTR(ssl->password);
-  FREE_PTR(ssl->cafile);
-  FREE_PTR(ssl->certfile);
-  FREE_PTR(ssl->keyfile);
-  FREE(ssl);
-}
-static void dump_ssl(void)
-{
-  SSL_DATA *ssl = conf_data->ssl;
-  
-  if (ssl->password)
-    syslog(LOG_INFO, " Password : %s", ssl->password);
-  if (ssl->cafile)
-    syslog(LOG_INFO, " CA-file : %s", ssl->cafile);
-  if (ssl->certfile)
-    syslog(LOG_INFO, " Certificate file : %s", ssl->certfile);
-  if (ssl->keyfile)
-    syslog(LOG_INFO, " Key file : %s", ssl->keyfile);
-  if (!ssl->password && !ssl->cafile && !ssl->certfile && !ssl->keyfile)
-    syslog(LOG_INFO, " Using autogen SSL context");
-}
-
-/* VRRP facility functions */
-static void free_vgroup(void *data)
-{
-  vrrp_sgroup *vgroup = data;
-
-  FREE(vgroup->gname);
-  free_strvec(vgroup->iname);
-  FREE_PTR(vgroup->script_backup);
-  FREE_PTR(vgroup->script_master);
-  FREE_PTR(vgroup->script_fault);
-  FREE(vgroup);
-}
-static void dump_vgroup(void *data)
-{
-  vrrp_sgroup *vgroup = data;
-  int i;
-  char *str;
-
-  syslog(LOG_INFO, " VRRP Sync Group = %s, %s"
-                 , vgroup->gname
-                 , (vgroup->state == VRRP_STATE_MAST)?"MASTER":"BACKUP");
-  for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
-    str = VECTOR_SLOT(vgroup->iname, i);
-    syslog(LOG_INFO, "   monitor = %s", str);
-  }
-  if (vgroup->script_backup)
-    syslog(LOG_INFO, "   Backup state transition script = %s"
-                   , vgroup->script_backup);
-  if (vgroup->script_master)
-    syslog(LOG_INFO, "   Master state transition script = %s"
-                   , vgroup->script_master);
-  if (vgroup->script_fault)
-    syslog(LOG_INFO, "   Fault state transition script = %s"
-                   , vgroup->script_fault);
-}
-
-static void free_vrrp(void *data)
-{
-  vrrp_rt *vrrp = data;
-
-  FREE(vrrp->iname);
-  FREE_PTR(vrrp->lvs_syncd_if);
-  FREE_PTR(vrrp->vaddr);
-  FREE_PTR(vrrp->evaddr);
-  FREE_PTR(vrrp->script_backup);
-  FREE_PTR(vrrp->script_master);
-  FREE_PTR(vrrp->script_fault);
-  FREE(vrrp->ipsecah_counter);
-  FREE(vrrp);
-}
-static void dump_vrrp(void *data)
-{
-  vrrp_rt *vrrp = data;
-  int i;
-
-  syslog(LOG_INFO, " VRRP Instance = %s", vrrp->iname);
-  if (vrrp->init_state == VRRP_STATE_BACK)
-    syslog(LOG_INFO, "   Want State = BACKUP");
-  else
-    syslog(LOG_INFO, "   Want State = MASTER");
-  syslog(LOG_INFO, "   Runing on device = %s", IF_NAME(vrrp->ifp));
-  if (vrrp->mcast_saddr)
-    syslog(LOG_INFO, "   Using mcast src_ip = %s"
-                   , inet_ntop2(vrrp->mcast_saddr));
-  if (vrrp->lvs_syncd_if)
-    syslog(LOG_INFO, "   Runing LVS sync daemon on interface = %s"
-                   , vrrp->lvs_syncd_if);
-  syslog(LOG_INFO, "   Virtual Router ID = %d", vrrp->vrid);
-  syslog(LOG_INFO, "   Priority = %d", vrrp->priority);
-  syslog(LOG_INFO, "   Advert interval = %dsec", vrrp->adver_int/TIMER_HZ);
-  if (vrrp->preempt)
-    syslog(LOG_INFO, "   Preempt Active");
-  if (vrrp->auth_type) {
-    syslog(LOG_INFO, "   Authentication type = %s",
-               (vrrp->auth_type == VRRP_AUTH_AH)?"IPSEC_AH":"SIMPLE_PASSWORD" );
-    syslog(LOG_INFO, "   Password = %s", vrrp->auth_data);
-  }
-  syslog(LOG_INFO, "   VIP count = %d", vrrp->naddr);
-  for (i = 0; i < vrrp->naddr; i++)
-    syslog(LOG_INFO, "     VIP%d = %s/%d", i+1, inet_ntop2(vrrp->vaddr[i].addr)
-                                              , vrrp->vaddr[i].mask);
-  if (vrrp->neaddr) {
-    syslog(LOG_INFO, "   Excluded VIP count = %d", vrrp->neaddr);
-    for (i = 0; i < vrrp->neaddr; i++)
-      syslog(LOG_INFO, "     E-VIP%d = %s/%d", i+1, inet_ntop2(vrrp->evaddr[i].addr)
-                                                  , vrrp->evaddr[i].mask);
-  }
-  if (vrrp->script_backup)
-    syslog(LOG_INFO, "   Backup state transition script = %s"
-                   , vrrp->script_backup);
-  if (vrrp->script_master)
-    syslog(LOG_INFO, "   Master state transition script = %s"
-                   , vrrp->script_master);
-  if (vrrp->script_fault)
-    syslog(LOG_INFO, "   Fault state transition script = %s"
-                   , vrrp->script_fault);
-  if (vrrp->smtp_alert)
-    syslog(LOG_INFO, "   Using smtp notification");
-}
-void alloc_vrrp_sync_group(char *gname)
-{
-  int size = strlen(gname);
-  vrrp_sgroup *new;
-
-  /* Allocate new VRRP group structure */
-  new = (vrrp_sgroup *)MALLOC(sizeof(vrrp_sgroup));
-  new->gname = (char *)MALLOC(size+1);
-  new->state = VRRP_STATE_BACK;
-  memcpy(new->gname, gname, size);
-
-  list_add(conf_data->vrrp_sync_group, new);
-}
-void alloc_vrrp(char *iname)
-{
-  int size = strlen(iname);
-  seq_counter *counter;
-  vrrp_rt *new;
-
-  /* Allocate new VRRP structure */
-  new     = (vrrp_rt *)      MALLOC(sizeof(vrrp_rt));
-  counter = (seq_counter *)  MALLOC(sizeof(seq_counter));
-
-  /* Build the structure */
-  new->ipsecah_counter = counter;
-
-  /* Set default values */
-  new->wantstate  = VRRP_STATE_BACK;
-  new->init_state = VRRP_STATE_BACK;
-  new->adver_int  = TIMER_HZ;
-  new->iname      = (char *)MALLOC(size+1);
-  memcpy(new->iname, iname, size);
-  new->sync = vrrp_get_sync_group(iname);
-
-  list_add(conf_data->vrrp, new);
-}
-void alloc_vrrp_vip(char *vip)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  uint32_t ipaddr = 0;
-  uint8_t mask = inet_stom(vip);
-  inet_ston(vip, &ipaddr);
-
-  vrrp->naddr++;
-  if (vrrp->vaddr)
-    vrrp->vaddr = REALLOC(vrrp->vaddr, vrrp->naddr*sizeof(*vrrp->vaddr));
-  else
-    vrrp->vaddr = (vip_addr *)MALLOC(sizeof(*vrrp->vaddr));
-  vrrp->vaddr[vrrp->naddr-1].addr = ipaddr;
-  vrrp->vaddr[vrrp->naddr-1].mask = mask;
-  vrrp->vaddr[vrrp->naddr-1].set  = 0;
-}
-void alloc_vrrp_evip(char *vip)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  uint32_t ipaddr = 0;
-  uint8_t mask = inet_stom(vip);
-  inet_ston(vip, &ipaddr);
-
-  vrrp->neaddr++;
-  if (vrrp->evaddr)
-    vrrp->evaddr = REALLOC(vrrp->evaddr, vrrp->neaddr*sizeof(*vrrp->evaddr));
-  else
-    vrrp->evaddr = (vip_addr *)MALLOC(sizeof(*vrrp->evaddr));
-  vrrp->evaddr[vrrp->neaddr-1].addr = ipaddr;
-  vrrp->evaddr[vrrp->neaddr-1].mask = mask;
-  vrrp->evaddr[vrrp->neaddr-1].set  = 0;
-}
-
-/* Virtual server facility functions */
-static void free_vs(void *data)
-{
-  virtual_server *vs = data;
-  FREE_PTR(vs->virtualhost);
-  FREE_PTR(vs->s_svr);
-  if (!LIST_ISEMPTY(vs->rs))
-    free_list(vs->rs);
-  if (!LIST_ISEMPTY(vs->rs_group))
-    free_list(vs->rs_group);
-  FREE(vs);
-}
-static void dump_vs(void *data)
-{
-  virtual_server *vs = data;
-
-  if (vs->vfwmark)
-    syslog(LOG_INFO, " VS FWMARK = %d", vs->vfwmark);
-  else
-    syslog(LOG_INFO, " VIP = %s, VPORT = %d"
-                   , inet_ntop2(SVR_IP(vs))
-                   , 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
-                 , vs->sched);
-  if (atoi(vs->timeout_persistence) > 0)
-    syslog(LOG_INFO, "   persistence timeout = %s"
-                   , vs->timeout_persistence);
-  if (vs->granularity_persistence)
-    syslog(LOG_INFO, "   persistence granularity = %s"
-                   , inet_ntop2(vs->granularity_persistence));
-  syslog(LOG_INFO, "   protocol = %s"
-                 , (vs->service_type == IPPROTO_TCP)?"TCP":"UDP");
-
-  switch (vs->loadbalancing_kind) {
-#ifdef _WITH_LVS_
-#ifdef _KRNL_2_2_
-    case 0:
-      syslog(LOG_INFO, "   lb_kind = NAT");
-      syslog(LOG_INFO, "   nat mask = %s", inet_ntop2(vs->nat_mask));
-      break;
-    case IP_MASQ_F_VS_DROUTE:
-      syslog(LOG_INFO, "   lb_kind = DR");
-      break;
-    case IP_MASQ_F_VS_TUNNEL:
-      syslog(LOG_INFO, "   lb_kind = TUN");
-      break;
-#else
-    case IP_VS_CONN_F_MASQ:
-      syslog(LOG_INFO, "   lb_kind = NAT");
-      break;
-    case IP_VS_CONN_F_DROUTE:
-      syslog(LOG_INFO, "   lb_kind = DR");
-      break;
-    case IP_VS_CONN_F_TUNNEL:
-      syslog(LOG_INFO, "   lb_kind = TUN");
-      break;
-#endif
-#endif
-  }
-
-  if (vs->s_svr) {
-    syslog(LOG_INFO, "   sorry server = %s:%d"
-                   , inet_ntop2(SVR_IP(vs->s_svr))
-                   , ntohs(SVR_PORT(vs->s_svr)));
-  }
-  if (!LIST_ISEMPTY(vs->rs))
-    dump_list(vs->rs);
-  if (!LIST_ISEMPTY(vs->rs_group))
-    dump_list(vs->rs_group);
-}
-void alloc_vs(char *ip, char *port)
-{
-  virtual_server *new;
-
-  new = (virtual_server *)MALLOC(sizeof(virtual_server));
-
-  if (!strcmp(ip, "fwmark")) {
-    new->vfwmark = atoi(port);
-  } else {
-    inet_ston(ip, &new->addr_ip);
-    new->addr_port = htons(atoi(port));
-  }
-  new->delay_loop = KEEPALIVED_DEFAULT_DELAY;
-  strncpy(new->timeout_persistence, "0", 1);
-  new->virtualhost = NULL;
-
-  list_add(conf_data->vs, new);
-}
-
-/* Sorry server facility functions */
-void alloc_ssvr(char *ip, char *port)
-{
-  virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
-
-  vs->s_svr = (real_server *)MALLOC(sizeof(real_server));
-  vs->s_svr->weight    = 1;
-  inet_ston(ip, &vs->s_svr->addr_ip);
-  vs->s_svr->addr_port = htons(atoi(port));
-}
-
-/* Real server facility functions */
-static void free_rs(void *data)
-{
-  real_server *rs = data;
-  FREE(rs);
-}
-static void dump_rs(void *data)
-{
-  real_server *rs = data;
-  syslog(LOG_INFO, "   RIP = %s, RPORT = %d, WEIGHT = %d"
-                 , inet_ntop2(SVR_IP(rs))
-                 , ntohs(SVR_PORT(rs))
-                 , rs->weight);
-}
-void alloc_rs(char *ip, char *port)
-{
-  virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
-  real_server *new;
-
-  new = (real_server *)MALLOC(sizeof(real_server));
-
-  inet_ston(ip, &new->addr_ip);
-  new->addr_port = htons(atoi(port));
-  new->alive = 1;
-
-  if (LIST_ISEMPTY(vs->rs))
-    vs->rs = alloc_list(free_rs, dump_rs);
-  list_add(vs->rs, new);
-  vs->last_rs_type = RS;
-}
-
-/* Real server group facility functions */
-static void free_group(void *data)
-{
-  real_server_group *group = data;
-  FREE(group->gname);
-  if (!LIST_ISEMPTY(group->rs))
-    free_list(group->rs);
-//  if (!LIST_ISEMPTY(group->vs))
-//    free_list(group->vs);
-  FREE(group);
-}
-static void dump_group(void *data)
-{
-  real_server_group *group = data;
-  syslog(LOG_INFO, " Real Server Group = %s", group->gname);
-  dump_list(group->rs);
-}
-void alloc_rsgroup(char *ip, char *port)
-{
-  real_server_group *group = LIST_TAIL_DATA(conf_data->group);
-  real_server *new;
-
-  new = (real_server *)MALLOC(sizeof(real_server));
-
-  inet_ston(ip, &new->addr_ip);
-  new->addr_port = htons(atoi(port));
-  new->alive     = 1;
-
-  if (LIST_ISEMPTY(group->rs))
-    group->rs = alloc_list(free_rs, dump_rs);
-  list_add(group->rs, new);
-}
-void alloc_group(char *name)
-{
-  real_server_group *new;
-  int size = strlen(name);
-
-  new = (real_server_group *)MALLOC(sizeof(real_server_group));
-
-  new->gname   = (char *)MALLOC(size+1);
-  memcpy(new->gname, name, size);
-  list_add(conf_data->group, new);
-}
-static real_server_group *get_group_by_name(char *name)
-{
-  real_server_group *group;
-  element e;
-
-  for (e = LIST_HEAD(conf_data->group); e; ELEMENT_NEXT(e)) {
-    group = ELEMENT_DATA(e);
-    if (strcmp(group->gname, name) == 0)
-      return group;
-  }
-  return NULL;
-}
-static void dump_rs_group(void *data)
-{
-  real_server_group *group = data;
-  syslog(LOG_INFO, "   Linking Real Server Group = %s", group->gname);
-}
-void set_rsgroup(char *gname)
-{
-  real_server_group *group = get_group_by_name(gname);
-  virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
-
-  if (group) {
-    if (LIST_ISEMPTY(vs->rs_group))
-      vs->rs_group = alloc_list(NULL, dump_rs_group);
-    list_add(vs->rs_group, group);
-    vs->last_rs_type = RS_GROUP;
-  }
-}
-
-/* data facility functions */
-data *alloc_data(void)
-{
-  data *new;
-
-  new = (data *)MALLOC(sizeof(data));
-  new->email = alloc_list(free_email, dump_email);
-  new->vrrp  = alloc_list(free_vrrp,  dump_vrrp);
-  new->vrrp_sync_group  = alloc_list(free_vgroup,  dump_vgroup);
-  new->vs    = alloc_list(free_vs,    dump_vs);
-  new->group = alloc_list(free_group, dump_group);
-
-  return new;
-}
-void free_data(void)
-{
-  free_ssl();
-  free_list(conf_data->email);
-  free_list(conf_data->vrrp);
-  free_list(conf_data->vrrp_sync_group);
-  free_list(conf_data->vs);
-  free_list(conf_data->group);
-
-  FREE_PTR(conf_data->lvs_id);
-  FREE_PTR(conf_data->email_from);
-  FREE(conf_data);
-}
-void dump_data(void)
-{
-  if (conf_data->lvs_id             ||
-      conf_data->smtp_server        ||
-      conf_data->smtp_connection_to ||
-      conf_data->email_from) {
-    syslog(LOG_INFO, "------< Global definitions >------");
-  }
-  if (conf_data->lvs_id)
-    syslog(LOG_INFO, " LVS ID = %s", conf_data->lvs_id);
-  if (conf_data->smtp_server)
-    syslog(LOG_INFO, " Smtp server = %s", inet_ntop2(conf_data->smtp_server));
-  if (conf_data->smtp_connection_to)
-    syslog(LOG_INFO, " Smtp server connection timeout = %d"
-                   , conf_data->smtp_connection_to);
-  if (conf_data->email_from) {
-    syslog(LOG_INFO, " Email notification from = %s"
-                   , conf_data->email_from);
-    dump_list(conf_data->email);
-  }
-  if (conf_data->ssl) {
-    syslog(LOG_INFO, "------< SSL definitions >------");
-    dump_ssl();
-  }
-  if (!LIST_ISEMPTY(conf_data->vrrp)) {
-    syslog(LOG_INFO, "------< VRRP Topology >------");
-    dump_list(conf_data->vrrp);
-  }
-  if (!LIST_ISEMPTY(conf_data->vrrp_sync_group)) {
-    syslog(LOG_INFO, "------< VRRP Sync groups >------");
-    dump_list(conf_data->vrrp_sync_group);
-  }
-  if (!LIST_ISEMPTY(conf_data->group)) {
-    syslog(LOG_INFO, "------< Real Servers groups >------");
-    dump_list(conf_data->group);
-  }
-#ifdef _WITH_LVS_
-  if (!LIST_ISEMPTY(conf_data->vs)) {
-    syslog(LOG_INFO, "------< LVS Topology >------");
-    syslog(LOG_INFO, " System is compiled with LVS v%d.%d.%d"
-                   , NVERSION(IP_VS_VERSION_CODE));
-    dump_list(conf_data->vs);
-  }
-  dump_checkers_queue();
-#endif
-}
index 5ed972c..c754d1e 100644 (file)
@@ -5,7 +5,7 @@
 # Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
 
 EXEC = genhash
-
+BIN  = ../bin
 prefix = @prefix@
 exec_prefix = @exec_prefix@
 bindir = @bindir@
@@ -17,19 +17,22 @@ LDFLAGS = @LIBS@ @LDFLAGS@
 OBJS = main.o client.o common.o
 
 all:   $(EXEC)
-       strip $(EXEC)
+       strip $(BIN)/$(EXEC)
        @echo ""
        @echo "Make complete"
 
 $(EXEC): $(OBJS)
-       $(CC) $(OBJS) -o $(EXEC) $(LDFLAGS)
+       $(CC) $(OBJS) -o $(BIN)/$(EXEC) $(LDFLAGS)
 
 clean:
-       rm -f core *.o $(EXEC)
+       rm -f core *.o
+
+distclean:
+       rm -f Makefile
 
-clean-dist:
+uninstall:
        rm -f $(bindir)/$(EXEC)
 
 install:
        install -d $(bindir)
-       install -m 755 $(EXEC) $(bindir)/
+       install -m 755 $(BIN)/$(EXEC) $(bindir)/
index a7aa110..8f09497 100644 (file)
 
 #include "client.h"
 
-int tcp_connect(int fd, char *host, int port)
+int
+tcp_connect(int fd, char *host, int port)
 {
-  int long_inet = sizeof(struct sockaddr_in);
-  struct sockaddr_in adr_serv;
-  struct hostent *ip_serv;
-  int arglen;
-  struct timeval tv;
-  fd_set wfds;
-  int rc, val;
-
-  /* Proceed remote hostname */
-  memset(&ip_serv, 0, sizeof(struct hostent));
-  if ((ip_serv = gethostbyname(host)) == NULL)
-    return TCP_RESOLV_ERROR;
-
-  /* Fill in connection structure */
-  memset(&adr_serv, 0, long_inet);
-  adr_serv.sin_family = AF_INET;
-  adr_serv.sin_port = htons(port);
-  adr_serv.sin_addr = *(struct in_addr*)ip_serv->h_addr;
-
-  /* Set read/write socket nonblock */
-  val = fcntl(fd, F_GETFL);
-  fcntl(fd, F_SETFL, val | O_NONBLOCK);
-
-  /* Connect the remote host */
-  rc = connect(fd, (struct sockaddr *)&adr_serv, long_inet);
-  if (rc == -1) {
-    if (errno !=  EINPROGRESS) {
-      rc = errno;
-      return TCP_CONNECT_ERROR;
-    }
-  }
-
-  /* Timeout settings */
-  tv.tv_sec = SOCKET_TIMEOUT_READ;
-  tv.tv_usec = 0;
-  FD_ZERO(&wfds);
-  FD_SET(fd, &wfds);
-
-  rc = select(fd+1, NULL, &wfds, NULL, &tv);
-  if (!FD_ISSET(fd, &wfds)) 
-    return TCP_WRITE_TIMEOUT;
-
-  if (rc <= 0) return TCP_SELECT_ERROR;
-
-  rc = 0;
-  arglen = sizeof(int);
-  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &rc, &arglen) < 0)
-    rc = errno;
-  if (rc) return TCP_CONNECT_FAILED;
-
-  /* Restore socket parameters */
-  fcntl(fd, F_SETFL, val);
-
-  return TCP_CONNECT_SUCCESS;
+       int long_inet = sizeof (struct sockaddr_in);
+       struct sockaddr_in adr_serv;
+       struct hostent *ip_serv;
+       int arglen;
+       struct timeval tv;
+       fd_set wfds;
+       int rc, val;
+
+       /* Proceed remote hostname */
+       memset(&ip_serv, 0, sizeof (struct hostent));
+       if ((ip_serv = gethostbyname(host)) == NULL)
+               return TCP_RESOLV_ERROR;
+
+       /* Fill in connection structure */
+       memset(&adr_serv, 0, long_inet);
+       adr_serv.sin_family = AF_INET;
+       adr_serv.sin_port = htons(port);
+       adr_serv.sin_addr = *(struct in_addr *) ip_serv->h_addr;
+
+       /* Set read/write socket nonblock */
+       val = fcntl(fd, F_GETFL);
+       fcntl(fd, F_SETFL, val | O_NONBLOCK);
+
+       /* Connect the remote host */
+       rc = connect(fd, (struct sockaddr *) &adr_serv, long_inet);
+       if (rc == -1) {
+               if (errno != EINPROGRESS) {
+                       rc = errno;
+                       return TCP_CONNECT_ERROR;
+               }
+       }
+
+       /* Timeout settings */
+       tv.tv_sec = SOCKET_TIMEOUT_READ;
+       tv.tv_usec = 0;
+       FD_ZERO(&wfds);
+       FD_SET(fd, &wfds);
+
+       rc = select(fd + 1, NULL, &wfds, NULL, &tv);
+       if (!FD_ISSET(fd, &wfds))
+               return TCP_WRITE_TIMEOUT;
+
+       if (rc <= 0)
+               return TCP_SELECT_ERROR;
+
+       rc = 0;
+       arglen = sizeof (int);
+       if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &rc, &arglen) < 0)
+               rc = errno;
+       if (rc)
+               return TCP_CONNECT_FAILED;
+
+       /* Restore socket parameters */
+       fcntl(fd, F_SETFL, val);
+
+       return TCP_CONNECT_SUCCESS;
 }
 
-int tcp_send(int fd, char *request, int len)
+int
+tcp_send(int fd, char *request, int len)
 {
-  if (send(fd, request, len, 0) == -1)
-    return TCP_SEND_ERROR;
-  return 0;
+       if (send(fd, request, len, 0) == -1)
+               return TCP_SEND_ERROR;
+       return 0;
 }
 
-int tcp_read_to(int fd)
+int
+tcp_read_to(int fd)
 {
-  struct timeval tv;
-  fd_set rfds;
-
-  /* Timeout settings */
-  tv.tv_sec = SOCKET_TIMEOUT_READ;
-  tv.tv_usec = 0;
-  FD_ZERO(&rfds);
-  FD_SET(fd, &rfds);
-
-  /* attempt read data */
-  select(fd+1, &rfds, NULL, NULL, &tv);
-  if (!FD_ISSET(fd, &rfds)) 
-    return TCP_READ_TIMEOUT;
-  return 0;
+       struct timeval tv;
+       fd_set rfds;
+
+       /* Timeout settings */
+       tv.tv_sec = SOCKET_TIMEOUT_READ;
+       tv.tv_usec = 0;
+       FD_ZERO(&rfds);
+       FD_SET(fd, &rfds);
+
+       /* attempt read data */
+       select(fd + 1, &rfds, NULL, NULL, &tv);
+       if (!FD_ISSET(fd, &rfds))
+               return TCP_READ_TIMEOUT;
+       return 0;
 }
 
-int tcp_sock(void)
+int
+tcp_sock(void)
 {
-  int fd;
-  struct sockaddr_in adr_local;
+       int fd;
+       struct sockaddr_in adr_local;
 
-  if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) return (-1);
-  memset(&adr_local, 0, sizeof(struct sockaddr_in));
-  adr_local.sin_family = AF_INET;
-  adr_local.sin_port = htons(0);
-  adr_local.sin_addr.s_addr = htonl(INADDR_ANY);
+       if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
+               return (-1);
+       memset(&adr_local, 0, sizeof (struct sockaddr_in));
+       adr_local.sin_family = AF_INET;
+       adr_local.sin_port = htons(0);
+       adr_local.sin_addr.s_addr = htonl(INADDR_ANY);
 
-  if (bind(fd, (struct sockaddr *)&adr_local, sizeof(struct sockaddr_in))) return (-1);
+       if (bind
+           (fd, (struct sockaddr *) &adr_local, sizeof (struct sockaddr_in)))
+               return (-1);
 
-  return(fd);
+       return (fd);
 }
index 137eb5f..2423cc7 100644 (file)
@@ -73,4 +73,3 @@ extern int tcp_read_to(int fd);
 extern int tcp_sock(void);
 
 #endif
-
diff --git a/genhash/client.o b/genhash/client.o
new file mode 100644 (file)
index 0000000..f8965ff
Binary files /dev/null and b/genhash/client.o differ
index ead37da..3b0262f 100644 (file)
  *              2 of the License, or (at your option) any later version.
  */
 
-#include <openssl/err.h>
 #include "common.h"
 
 static BIO *bio_err = 0;
 static char *pass;
 
 /* A simple error and exit routine*/
-int err_exit(char *string)
+int
+err_exit(char *string)
 {
-  fprintf(stderr, "%s\n", string);
-  exit(0);
+       fprintf(stderr, "%s\n", string);
+       exit(0);
 }
 
 /* Print SSL errors and exit*/
-int berr_exit(char *string)
+int
+berr_exit(char *string)
 {
-  BIO_printf(bio_err, "%s\n", string);
-  ERR_print_errors(bio_err);
-  exit(0);
+       BIO_printf(bio_err, "%s\n", string);
+       ERR_print_errors(bio_err);
+       exit(0);
 }
 
 /*The password code is not thread safe*/
-static int password_cb(char *buf, int num, int rwflag, void *userdata)
+static int
+password_cb(char *buf, int num, int rwflag, void *userdata)
 {
-  if (num < strlen(pass)+1)
-    return(0);
+       if (num < strlen(pass) + 1)
+               return (0);
 
-  strcpy(buf, pass);
-  return(strlen(pass));
+       strcpy(buf, pass);
+       return (strlen(pass));
 }
 
-static void sigpipe_handle(int x) {
+static void
+sigpipe_handle(int x)
+{
 }
 
 /* SSL context initializer */
-SSL_CTX *initialize_ctx(char *keyfile, char *password, char *cafile)
+SSL_CTX *
+initialize_ctx(char *keyfile, char *password, char *cafile)
 {
-  SSL_METHOD *meth;
-  SSL_CTX *ctx;
-    
-  if (!bio_err){
-    /* Global system initialization*/
-    SSL_library_init();
-    SSL_load_error_strings();
-      
-    /* An error write context */
-    bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
-  }
-
-  /* Set up a SIGPIPE handler */
-  signal(SIGPIPE, sigpipe_handle);
-    
-  /* Create our context*/
-  meth = SSLv23_method();
-  ctx = SSL_CTX_new(meth);
-
-  /* Load our keys and certificates*/
-  if (keyfile)
-    if(!(SSL_CTX_use_certificate_chain_file(ctx, keyfile)))
-      berr_exit("Can't read certificate file");
-
-  if (password) {
-    pass = password;
-    SSL_CTX_set_default_passwd_cb(ctx, password_cb);
-  }
-  if (keyfile)
-    if(!(SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM)))
-      berr_exit("Can't read key file");
-
-  /* Load the CAs we trust*/
-  if (cafile)
-    if(!(SSL_CTX_load_verify_locations(ctx, cafile, 0)))
-      berr_exit("Can't read CA list");
+       SSL_METHOD *meth;
+       SSL_CTX *ctx;
+
+       if (!bio_err) {
+               /* Global system initialization */
+               SSL_library_init();
+               SSL_load_error_strings();
+
+               /* An error write context */
+               bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
+       }
+
+       /* Set up a SIGPIPE handler */
+       signal(SIGPIPE, sigpipe_handle);
+
+       /* Create our context */
+       meth = SSLv23_method();
+       ctx = SSL_CTX_new(meth);
+
+       /* Load our keys and certificates */
+       if (keyfile)
+               if (!(SSL_CTX_use_certificate_chain_file(ctx, keyfile)))
+                       berr_exit("Can't read certificate file");
+
+       if (password) {
+               pass = password;
+               SSL_CTX_set_default_passwd_cb(ctx, password_cb);
+       }
+
+       if (keyfile)
+               if (!
+                   (SSL_CTX_use_PrivateKey_file
+                    (ctx, keyfile, SSL_FILETYPE_PEM)))
+                       berr_exit("Can't read key file");
+
+       /* Load the CAs we trust */
+       if (cafile)
+               if (!(SSL_CTX_load_verify_locations(ctx, cafile, 0)))
+                       berr_exit("Can't read CA list");
 #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
-  SSL_CTX_set_verify_depth(ctx,1);
+       SSL_CTX_set_verify_depth(ctx, 1);
 #endif
 
-  return ctx;
+       return ctx;
 }
-     
-void destroy_ctx(SSL_CTX *ctx)
+
+void
+destroy_ctx(SSL_CTX * ctx)
 {
-  SSL_CTX_free(ctx);
+       SSL_CTX_free(ctx);
 }
index 116b897..9fe4b43 100644 (file)
 #include <string.h>
 #include <signal.h>
 #include <openssl/ssl.h>
+#include <openssl/err.h>
 
 /* prototypes */
 extern int berr_exit(char *string);
 extern int err_exit(char *string);
 extern SSL_CTX *initialize_ctx(char *keyfile, char *password, char *cafile);
-extern void destroy_ctx(SSL_CTX *ctx);
+extern void destroy_ctx(SSL_CTX * ctx);
 
 #ifndef ALLOW_OLD_VERSIONS
 #if(OPENSSL_VERSION_NUMBER < 0x00905100L)
diff --git a/genhash/common.o b/genhash/common.o
new file mode 100644 (file)
index 0000000..52072a8
Binary files /dev/null and b/genhash/common.o differ
index 43a7ffa..a8885da 100644 (file)
  *              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.
- */     
+ */
 
 #include "main.h"
 #include "common.h"
 #include "client.h"
 
 /* Dump a buffer (ASCII or Binary) */
-static void print_buffer(int count, char *buff)
+static void
+print_buffer(int count, char *buff)
 {
-  int i,j,c;
-  int printnext=1;
-
-  if(count) {
-    if(count%16)
-      c=count+(16-count%16);
-    else c=count;
-  } else
-    c=count;
-
-  for(i=0;i<c;i++) {
-    if(printnext) { 
-      printnext--;
-      printf("%.4x ",i&0xffff);
-    }
-    if(i<count)
-      printf("%3.2x",buff[i]&0xff);
-    else
-      printf("   ");
-    if(!((i+1)%8)) {
-      if((i+1)%16)
-        printf(" -");
-      else {
-        printf("   ");
-        for(j=i-15;j<=i;j++)
-          if(j<count) {
-            if( (buff[j]&0xff) >= 0x20 && (buff[j]&0xff)<=0x7e)
-              printf("%c",buff[j]&0xff);
-            else printf(".");
-          } else printf(" ");
-        printf("\n"); printnext=1;
-      }
-    }
-  }
+       int i, j, c;
+       int printnext = 1;
+
+       if (count % 16)
+               c = count + (16 - count % 16);
+       else
+               c = count;
+
+       for (i = 0; i < c; i++) {
+               if (printnext) {
+                       printnext--;
+                       printf("%.4x ", i & 0xffff);
+               }
+               if (i < count)
+                       printf("%3.2x", buff[i] & 0xff);
+               else
+                       printf("   ");
+               if (!((i + 1) % 8)) {
+                       if ((i + 1) % 16)
+                               printf(" -");
+                       else {
+                               printf("   ");
+                               for (j = i - 15; j <= i; j++)
+                                       if (j < count) {
+                                               if ((buff[j] & 0xff) >= 0x20
+                                                   && (buff[j] & 0xff) <= 0x7e)
+                                                       printf("%c",
+                                                              buff[j] & 0xff);
+                                               else
+                                                       printf(".");
+                                       } else
+                                               printf(" ");
+                               printf("\n");
+                               printnext = 1;
+                       }
+               }
+       }
 }
 
 /* Allocate & clean a buffer */
-static char *xmalloc(const int size)
+static char *
+xmalloc(const int size)
 {
-  char *buffer;
+       char *buffer;
 
-  buffer = (char *)malloc(size);
-  if (!buffer) return NULL;
-  memset(buffer, 0, size);
+       buffer = (char *) malloc(size);
+       if (!buffer)
+               return NULL;
+       memset(buffer, 0, size);
 
-  return buffer;
+       return buffer;
 }
 
 /* Return the html header from a global HTTP buffer */
-static char *extract_html(char *buffer, int size_buffer)
+static char *
+extract_html(char *buffer, int size_buffer)
 {
-  char *end=buffer+size_buffer;
+       char *end = buffer + size_buffer;
 
-  while ( buffer < end && !(*buffer++ == '\n' &&
-                          (*buffer == '\n' || (*buffer++ == '\r' && *buffer =='\n'))));
+       while (buffer < end && !(*buffer++ == '\n' &&
+                                (*buffer == '\n'
+                                 || (*buffer++ == '\r' && *buffer == '\n')))) ;
 
-  if (*buffer == '\n') return buffer+1;
-  return NULL;
+       if (*buffer == '\n')
+               return buffer + 1;
+       return NULL;
 }
 
 /* Build the GET request */
-static char *build_request(REQ* req)
+static char *
+build_request(REQ * req)
 {
-  char *request;
-  char *vhost;
-  int request_len = 0;
-
-  request_len = strlen(REQUEST_TEMPLATE) +
-                strlen(req->host) +
-                strlen(req->url)  +
-                5                 + /* characters for port */
-                1;                  /* null terminator     */
-  request = xmalloc(request_len);
-  if (!request) return NULL;
-
-  vhost = req->host;
-  if (req->virtualhost)
-    vhost = req->virtualhost;
-  snprintf(request, request_len
-                  , REQUEST_TEMPLATE
-                  , req->url
-                  , vhost
-                  , req->port);
-  return request;
+       char *request;
+       char *vhost;
+       int request_len = 0;
+
+       request_len = strlen(REQUEST_TEMPLATE) + strlen(req->host) + strlen(req->url) + 5 +     /* characters for port */
+           1;                  /* null terminator     */
+       request = xmalloc(request_len);
+       if (!request)
+               return NULL;
+
+       vhost = req->host;
+       if (req->virtualhost)
+               vhost = req->virtualhost;
+       snprintf(request, request_len, REQUEST_TEMPLATE, req->url, vhost,
+                req->port);
+       return request;
 }
 
-static int https_request(SSL *ssl, REQ *req)
+static int
+https_request(SSL * ssl, REQ * req)
 {
-  char *request = NULL;
-  int r, i, e = 0;
-  int request_len;
-  char *extracted;      
-  unsigned char digest[16];
-  MD5_CTX context;
-
-  /* Build the SSL request */
-  request = build_request(req);
-  if (!request) return OUT_OF_MEMORY;
-  request_len = strlen(request);
-
-  /* Send the SSL request */
-  r = SSL_write(ssl, request, request_len);
-  if (SSL_ERROR_NONE != SSL_get_error(ssl, r)) {
-    free(request);
-    return SSL_WRITE_ERROR;
-  }
-
-  /* Test for eventual imcomplete SSL write */
-  if (request_len != r) {
-    free(request);
-    return SSL_INCOMPLETE_WRITE;
-  }
-  /* Init MD5 context */
-  MD5_Init(&context);
-  extracted = NULL;
-  req->len  = 0;
-  e         = 0;
-
-  /* 
-   * Now read the server's response, assuming
-   * that it's terminated by a close.
-   *
-   * FIXME: Create a function to read data from remote
-   *        server instead of code duplication.
-   */
-  printf(HTTP_HEADER_HEXA);
-
-  while (!e) {
-    r = SSL_read(ssl, req->buffer+req->len, req->max-req->len);
-    e = SSL_get_error(ssl, r);
-    if (e != SSL_ERROR_NONE) break;
-    if (r > 0 && e == 0) {
-      req->len +=r;
-      /* Only header yet ? */
-      if (!extracted) {
-        /* Found something more than header ? */
-        if ((extracted = extract_html(req->buffer, req->len))) {
-          r = req->len-(extracted-req->buffer);
-          if (r) { 
-            print_buffer(r, req->buffer);
-            printf(HTTP_HEADER_ASCII);
-            for (i=0; i < extracted-req->buffer; i++)
-              printf("%c", req->buffer[i]);
-            printf("\n");
-            printf(HTML_HEADER_HEXA);
-            memcpy(req->buffer,extracted,r);
-            MD5_Update(&context, req->buffer, r);
-            r = 0;
-          }
-          req->len = r;
-        } else {
-          if ( req->len > 3 ) {
-            print_buffer(req->len - 3 , req->buffer);
-            printf(HTTP_HEADER_ASCII);
-            for (i=0; i < req->len -3  ; i++)
-             printf("%c", req->buffer[i]);
-            printf("\n");
-            printf(HTML_HEADER_HEXA);
-            memcpy( req->buffer, req->buffer+req->len-3, 3);
-            req->len = 3;
-          }
-        }
-      } else {
-        if ( req -> len ) {
-          print_buffer(req->len, req->buffer);
-          MD5_Update(&context, req->buffer, req->len);
-          req->len = 0;
-        }
-      } 
-    }  
-  }
-
-  /* Error handling */
-  if (e != SSL_ERROR_ZERO_RETURN && e != SSL_ERROR_SYSCALL) {
-    free(request);
-    return SSL_READ_ERROR;
-  }
-
-  if (e == SSL_ERROR_ZERO_RETURN)  
-  if (SSL_shutdown(ssl) != 1) {
-    free(request);
-    return SSL_SHUTDOWN_FAILED;
-  }
-
-  if (e != SSL_ERROR_SYSCALL)
-    SSL_free(ssl);
-
-  MD5_Final(digest, &context);
-  printf(HTML_MD5);
-  print_buffer(16, digest);
-
-  printf(HTML_MD5_FINAL);
-  for (r=0; r<16; r++)
-    printf("%02x", digest[r]);
-  printf("\n\n");
-
-  free(request);
-  return SSL_GET_SUCCESS;
+       char *request = NULL;
+       int r, i, e = 0;
+       int request_len;
+       char *extracted;
+       unsigned char digest[16];
+       MD5_CTX context;
+
+       /* Build the SSL request */
+       request = build_request(req);
+       if (!request)
+               return OUT_OF_MEMORY;
+       request_len = strlen(request);
+
+       /* Send the SSL request */
+       r = SSL_write(ssl, request, request_len);
+       if (SSL_ERROR_NONE != SSL_get_error(ssl, r)) {
+               free(request);
+               return SSL_WRITE_ERROR;
+       }
+
+       /* Test for eventual imcomplete SSL write */
+       if (request_len != r) {
+               free(request);
+               return SSL_INCOMPLETE_WRITE;
+       }
+
+       /* Init MD5 context */
+       MD5_Init(&context);
+       extracted = NULL;
+       req->len = 0;
+       e = 0;
+
+       /* 
+        * Now read the server's response, assuming
+        * that it's terminated by a close.
+        *
+        * FIXME: Create a function to read data from remote
+        *        server instead of code duplication.
+        */
+       printf(HTTP_HEADER_HEXA);
+
+       while (!e) {
+               r = SSL_read(ssl, req->buffer + req->len, req->max - req->len);
+               e = SSL_get_error(ssl, r);
+               if (e != SSL_ERROR_NONE)
+                       break;
+               if (r > 0 && e == 0) {
+                       req->len += r;
+                       /* Only header yet ? */
+                       if (!extracted) {
+                               /* Found something more than header ? */
+                               if ((extracted =
+                                    extract_html(req->buffer, req->len))) {
+                                       r = req->len - (extracted -
+                                                       req->buffer);
+                                       if (r) {
+                                               print_buffer(r, req->buffer);
+                                               printf(HTTP_HEADER_ASCII);
+                                               for (i = 0;
+                                                    i <
+                                                    extracted - req->buffer;
+                                                    i++)
+                                                       printf("%c",
+                                                              req->buffer[i]);
+                                               printf("\n");
+                                               printf(HTML_HEADER_HEXA);
+                                               memcpy(req->buffer, extracted,
+                                                      r);
+                                               MD5_Update(&context,
+                                                          req->buffer, r);
+                                               r = 0;
+                                       }
+                                       req->len = r;
+                               } else {
+                                       if (req->len > 3) {
+                                               print_buffer(req->len - 3,
+                                                            req->buffer);
+                                               printf(HTTP_HEADER_ASCII);
+                                               for (i = 0; i < req->len - 3;
+                                                    i++)
+                                                       printf("%c",
+                                                              req->buffer[i]);
+                                               printf("\n");
+                                               printf(HTML_HEADER_HEXA);
+                                               memcpy(req->buffer,
+                                                      req->buffer + req->len -
+                                                      3, 3);
+                                               req->len = 3;
+                                       }
+                               }
+                       } else {
+                               if (req->len) {
+                                       print_buffer(req->len, req->buffer);
+                                       MD5_Update(&context, req->buffer,
+                                                  req->len);
+                                       req->len = 0;
+                               }
+                       }
+               }
+       }
+
+       /* Error handling */
+       if (e != SSL_ERROR_ZERO_RETURN && e != SSL_ERROR_SYSCALL) {
+               free(request);
+               return SSL_READ_ERROR;
+       }
+
+       if (e == SSL_ERROR_ZERO_RETURN)
+               if (SSL_shutdown(ssl) != 1) {
+                       free(request);
+                       return SSL_SHUTDOWN_FAILED;
+               }
+
+       if (e != SSL_ERROR_SYSCALL)
+               SSL_free(ssl);
+
+       MD5_Final(digest, &context);
+       printf(HTML_MD5);
+       print_buffer(16, digest);
+
+       printf(HTML_MD5_FINAL);
+       for (r = 0; r < 16; r++)
+               printf("%02x", digest[r]);
+       printf("\n\n");
+
+       free(request);
+       return SSL_GET_SUCCESS;
 }
 
 /*
  * Connect a remote SSL server and generate a MD5SUM
  * Upon the remote HTML content returned.
  */
-static int genhash_ssl(REQ * req)
+static int
+genhash_ssl(REQ * req)
 {
-  SSL_CTX *ctx;
-  SSL *ssl;
-  BIO *sbio;
-  int retcode = 0;
-  /* SSL context initialization */
-  ctx = initialize_ctx(req->keyfile, req->password, req->cafile);
-
-  /* TCP socket creation */
-  req->fd = tcp_sock();
-  if (req->fd == -1) {
-    destroy_ctx(ctx);
-    return TCP_BIND_ERROR;
-  }
-
-  /* TCP connect remote host */
-  retcode = tcp_connect(req->fd, req->host, req->port);
-  if (retcode != TCP_CONNECT_SUCCESS) goto end;
-
-  /* Create the SSL context */
-  ssl = SSL_new(ctx);
-  sbio = BIO_new_socket(req->fd, BIO_NOCLOSE);
-  SSL_set_bio(ssl, sbio, sbio);
-
-  /* Connect remote SSL server */
-  if (SSL_connect(ssl) <= 0) 
-    return -2;
-
-  /* Proceed the SSL server reply */
-  retcode = https_request(ssl, req);
-
-end:
-  /* Shutdown the socket */
-  destroy_ctx(ctx);
-  close(req->fd);
-  return(retcode);
+       SSL_CTX *ctx;
+       SSL *ssl;
+       BIO *sbio;
+       int retcode = 0;
+
+       /* SSL context initialization */
+       ctx = initialize_ctx(req->keyfile, req->password, req->cafile);
+
+       /* TCP socket creation */
+       req->fd = tcp_sock();
+       if (req->fd == -1) {
+               destroy_ctx(ctx);
+               return TCP_BIND_ERROR;
+       }
+
+       /* TCP connect remote host */
+       retcode = tcp_connect(req->fd, req->host, req->port);
+       if (retcode != TCP_CONNECT_SUCCESS)
+               goto end;
+
+       /* Create the SSL context */
+       ssl = SSL_new(ctx);
+       sbio = BIO_new_socket(req->fd, BIO_NOCLOSE);
+       SSL_set_bio(ssl, sbio, sbio);
+
+       /* Connect remote SSL server */
+       if (SSL_connect(ssl) <= 0)
+               return -2;
+
+       /* Proceed the SSL server reply */
+       retcode = https_request(ssl, req);
+
+      end:
+       /* Shutdown the socket */
+       destroy_ctx(ctx);
+       close(req->fd);
+       return (retcode);
 }
 
 /*
  * Connect a remote HTTP server and generate a MD5SUM
  * Upon the remote HTML content returned.
  */
-static int genhash_http(REQ *req)
+static int
+genhash_http(REQ * req)
 {
-  int request_len = 0;
-  char *request = NULL;
-  char *buffertmp = NULL; 
-  int retcode = 0;
-  int r;
-  char *extracted;      
-  unsigned char digest[16];
-  MD5_CTX context;
-
-  /* Temporary get buffer allocation */
-  buffertmp = xmalloc(RCV_BUFFER_LENGTH);
-  if (!buffertmp) {
-    free(request);
-    return OUT_OF_MEMORY;
-  }
-
-  /* Build the HTTP request */
-  request = build_request(req);
-  if (!request) {
-    free(buffertmp);
-    return OUT_OF_MEMORY;
-  }
-  request_len = strlen(request);
-
-  /* TCP socket creation */
-  req->fd = tcp_sock();
-  if (req->fd == -1) {
-    free(request);
-    free(buffertmp);
-    return TCP_BIND_ERROR;
-  }
-
-  /* TCP connect remote host */
-  retcode = tcp_connect(req->fd, req->host, req->port);
-  if (retcode != TCP_CONNECT_SUCCESS) goto error;
-
-  /* Send the HTTP request */
-  retcode = tcp_send(req->fd, request, request_len);
-  if (retcode == TCP_SEND_ERROR) goto error;
-
-  /* Proceed the HTTP server reply */
-  retcode = tcp_read_to(req->fd);
-  if (retcode == TCP_READ_TIMEOUT) goto error;
-
-  MD5_Init(&context);
-  extracted = NULL;
-  req->len = 0;
-
-  /* 
-   * Now read the server's response.
-   *
-   * FIXME: Create a function to read data from remote
-   *        server instead of code duplication.
-   */
-  printf(HTTP_HEADER_HEXA);
-  while (1) {
-    r = read(req->fd, buffertmp, RCV_BUFFER_LENGTH);
-    if (r == -1 || r == 0) break; 
-    memcpy(req->buffer+req->len, buffertmp, r);
-    req->len += r;
-    if (!extracted &&
-        (extracted = extract_html(req->buffer, req->len))) {
-      print_buffer(extracted-req->buffer, req->buffer);
-      printf(HTTP_HEADER_ASCII);
-      for ( r=0; r < extracted-req->buffer; r++)
-        printf("%c", req->buffer[r]);
-      printf("\n");
-
-      printf(HTML_HEADER_HEXA);
-      r = req->len - (extracted-req->buffer); 
-      if (r)  
-        memcpy(req->buffer,extracted,r);
-      req->len  = r;
-    }
-
-    if (extracted && req->len) { 
-      print_buffer(req->len, req->buffer);
-      MD5_Update(&context, req->buffer, req->len);
-      req->len = 0;
-    }
-  }
-  
-  MD5_Final(digest, &context);
-  printf(HTML_MD5);
-  print_buffer(16, digest);
-
-  printf(HTML_MD5_FINAL);
-  for (r=0; r<16; r++)
-    printf("%02x", digest[r]);
-  printf("\n\n");
-
-  /* All is fine just return a success code */
-  retcode = HTTP_GET_SUCCESS;
-
-error:
-  close(req->fd);
-  free(request);
-  free(buffertmp);
-  return(retcode);
+       int request_len = 0;
+       char *request = NULL;
+       char *buffertmp = NULL;
+       int retcode = 0;
+       int r;
+       char *extracted;
+       unsigned char digest[16];
+       MD5_CTX context;
+
+       /* Temporary get buffer allocation */
+       buffertmp = xmalloc(RCV_BUFFER_LENGTH);
+       if (!buffertmp) {
+               free(request);
+               return OUT_OF_MEMORY;
+       }
+
+       /* Build the HTTP request */
+       request = build_request(req);
+       if (!request) {
+               free(buffertmp);
+               return OUT_OF_MEMORY;
+       }
+       request_len = strlen(request);
+
+       /* TCP socket creation */
+       req->fd = tcp_sock();
+       if (req->fd == -1) {
+               free(request);
+               free(buffertmp);
+               return TCP_BIND_ERROR;
+       }
+
+       /* TCP connect remote host */
+       retcode = tcp_connect(req->fd, req->host, req->port);
+       if (retcode != TCP_CONNECT_SUCCESS)
+               goto error;
+
+       /* Send the HTTP request */
+       retcode = tcp_send(req->fd, request, request_len);
+       if (retcode == TCP_SEND_ERROR)
+               goto error;
+
+       /* Proceed the HTTP server reply */
+       retcode = tcp_read_to(req->fd);
+       if (retcode == TCP_READ_TIMEOUT)
+               goto error;
+
+       MD5_Init(&context);
+       extracted = NULL;
+       req->len = 0;
+
+       /* 
+        * Now read the server's response.
+        *
+        * FIXME: Create a function to read data from remote
+        *        server instead of code duplication.
+        */
+       printf(HTTP_HEADER_HEXA);
+       while (1) {
+               r = read(req->fd, buffertmp, RCV_BUFFER_LENGTH);
+               if (r == -1 || r == 0)
+                       break;
+               memcpy(req->buffer + req->len, buffertmp, r);
+               req->len += r;
+               if (!extracted &&
+                   (extracted = extract_html(req->buffer, req->len))) {
+                       print_buffer(extracted - req->buffer, req->buffer);
+                       printf(HTTP_HEADER_ASCII);
+                       for (r = 0; r < extracted - req->buffer; r++)
+                               printf("%c", req->buffer[r]);
+                       printf("\n");
+
+                       printf(HTML_HEADER_HEXA);
+                       r = req->len - (extracted - req->buffer);
+                       if (r)
+                               memcpy(req->buffer, extracted, r);
+                       req->len = r;
+               }
+
+               if (extracted && req->len) {
+                       print_buffer(req->len, req->buffer);
+                       MD5_Update(&context, req->buffer, req->len);
+                       req->len = 0;
+               }
+       }
+
+       MD5_Final(digest, &context);
+       printf(HTML_MD5);
+       print_buffer(16, digest);
+
+       printf(HTML_MD5_FINAL);
+       for (r = 0; r < 16; r++)
+               printf("%02x", digest[r]);
+       printf("\n\n");
+
+       /* All is fine just return a success code */
+       retcode = HTTP_GET_SUCCESS;
+
+      error:
+       close(req->fd);
+       free(request);
+       free(buffertmp);
+       return (retcode);
 }
 
 /* Error return function */
-static void print_error(int err)
+static void
+print_error(int err)
 {
-  switch (err) {
-    /* System errors */
-    case OUT_OF_MEMORY:      err_exit("Out Of Memery");                break;
-
-    /* TCP errors */
-    case TCP_BIND_ERROR:     err_exit("TCP Bind error");        break;
-    case TCP_RESOLV_ERROR:   err_exit("TCP Resolv error");     break;
-    case TCP_CONNECT_ERROR:  err_exit("TCP Connect error");    break;
-    case TCP_WRITE_TIMEOUT:  err_exit("TCP Write TimeOut");    break;
-    case TCP_READ_TIMEOUT:   err_exit("TCP Read error");       break;
-    case TCP_SELECT_ERROR:   err_exit("TCP Select error");     break;
-    case TCP_CONNECT_FAILED: err_exit("TCP Connectin failed"); break;
-    case TCP_SEND_ERROR:     err_exit("TCP Send error");       break;
-
-    /* SSL errors */
-    case SSL_WRITE_ERROR:    err_exit("SSL Write error");       break;
-    case SSL_INCOMPLETE_WRITE: err_exit("SSL Incomplete write");break;
-    case SSL_READ_ERROR:     err_exit("SSL Read error");       break;
-    case SSL_SHUTDOWN_FAILED:err_exit("SSL Shutdown failed");  break;
-  }
+       switch (err) {
+               /* System errors */
+       case OUT_OF_MEMORY:
+               err_exit("Out Of Memery");
+               break;
+
+               /* TCP errors */
+       case TCP_BIND_ERROR:
+               err_exit("TCP Bind error");
+               break;
+       case TCP_RESOLV_ERROR:
+               err_exit("TCP Resolv error");
+               break;
+       case TCP_CONNECT_ERROR:
+               err_exit("TCP Connect error");
+               break;
+       case TCP_WRITE_TIMEOUT:
+               err_exit("TCP Write TimeOut");
+               break;
+       case TCP_READ_TIMEOUT:
+               err_exit("TCP Read error");
+               break;
+       case TCP_SELECT_ERROR:
+               err_exit("TCP Select error");
+               break;
+       case TCP_CONNECT_FAILED:
+               err_exit("TCP Connectin failed");
+               break;
+       case TCP_SEND_ERROR:
+               err_exit("TCP Send error");
+               break;
+
+               /* SSL errors */
+       case SSL_WRITE_ERROR:
+               err_exit("SSL Write error");
+               break;
+       case SSL_INCOMPLETE_WRITE:
+               err_exit("SSL Incomplete write");
+               break;
+       case SSL_READ_ERROR:
+               err_exit("SSL Read error");
+               break;
+       case SSL_SHUTDOWN_FAILED:
+               err_exit("SSL Shutdown failed");
+               break;
+       }
 }
 
 /* Usage function */
-static void usage(const char *prog)
+static void
+usage(const char *prog)
 {
-  fprintf(stderr, "%s Version %s\n", PROG, VERSION);
-  fprintf(stderr, 
-    "Usage:\n"
-    "  %s -s server-address -p port -u url\n"
-    "  %s -S -K priv-key-file -P pem-password -s server-address -p port -u url\n"
-    "  %s -S -K priv-key-file -P pem-password -C cert-file -s server-address -p port -u url\n"
-    "  %s -h\n"
-    "  %s -v\n\n",
-    prog, prog, prog, prog, prog);
-  fprintf(stderr, 
-    "Commands:\n"
-    "Either long or short options are allowed.\n"
-    "  %s --use-ssl         -S       Use SSL connection to remote server.\n"
-    "  %s --server          -s       Use the specified remote server address.\n"
-    "  %s --port            -p       Use the specified remote server port.\n"
-    "  %s --url             -u       Use the specified remote server url.\n"
-    "  %s --use-private-key -K       Use the specified SSL private key.\n"
-    "  %s --use-password    -P       Use the specified SSL private key password.\n"
-    "  %s --use-virtualhost -V       Use the specified VirtualHost GET query.\n"
-    "  %s --use-certificate -C       Use the specified SSL Certificate file.\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);
+       fprintf(stderr, "%s Version %s\n", PROG, VERSION);
+       fprintf(stderr,
+               "Usage:\n"
+               "  %s -s server-address -p port -u url\n"
+               "  %s -S -K priv-key-file -P pem-password -s server-address -p port -u url\n"
+               "  %s -S -K priv-key-file -P pem-password -C cert-file -s server-address -p port -u url\n"
+               "  %s -h\n" "  %s -v\n\n", prog, prog, prog, prog, prog);
+       fprintf(stderr,
+               "Commands:\n"
+               "Either long or short options are allowed.\n"
+               "  %s --use-ssl         -S       Use SSL connection to remote server.\n"
+               "  %s --server          -s       Use the specified remote server address.\n"
+               "  %s --port            -p       Use the specified remote server port.\n"
+               "  %s --url             -u       Use the specified remote server url.\n"
+               "  %s --use-private-key -K       Use the specified SSL private key.\n"
+               "  %s --use-password    -P       Use the specified SSL private key password.\n"
+               "  %s --use-virtualhost -V       Use the specified VirtualHost GET query.\n"
+               "  %s --use-certificate -C       Use the specified SSL Certificate file.\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);
 }
 
 /* Command line parser */
-static int parse_cmdline(int argc, char **argv, REQ *req)
+static int
+parse_cmdline(int argc, char **argv, REQ * req)
 {
-  poptContext context;
-  char *optarg = NULL;
-  int c;
-
-  struct poptOption options_table[] = {
-    {"version",         'v', POPT_ARG_NONE,      NULL, 'v'},
-    {"help",            'h', POPT_ARG_NONE,      NULL, 'h'},
-    {"use-ssl",         'S', POPT_ARG_NONE,      NULL, 'S'},
-    {"server",          's', POPT_ARG_STRING, &optarg, 's'},
-    {"port",            'p', POPT_ARG_STRING, &optarg, 'p'},
-    {"url",             'u', POPT_ARG_STRING, &optarg, 'u'},
-    {"use-private-key", 'K', POPT_ARG_STRING, &optarg, 'K'},
-    {"use-virtualhost", 'V', POPT_ARG_STRING, &optarg, 'V'},
-    {"use-password",    'P', POPT_ARG_STRING, &optarg, 'P'},
-    {"use-certificate", 'C', POPT_ARG_STRING, &optarg, 'C'},
-    {NULL, 0, 0, NULL, 0}
-  };
-
-  context = poptGetContext(PROG, argc, (const char **)argv
-                                     , options_table, 0);
-  if ((c = poptGetNextOpt(context)) < 0) {
-    usage(argv[0]);
-    return CMD_LINE_ERROR;
-  }
-
-  /* The first option car */
-  switch (c) {
-    case 'v':
-      fprintf(stderr, "%s Version %s\n", PROG, VERSION);
-      break;
-    case 'h':
-      usage(argv[0]);
-      break;
-    case 'S':
-      req->ssl = 1;
-      break;
-    case 's':
-      req->host = optarg;
-      break;
-    default:
-      usage(argv[0]);
-      return CMD_LINE_ERROR;
-  }
-
-  /* the others */
-  while ((c = poptGetNextOpt(context)) >= 0) {
-    switch (c) {
-      case 's':
-        req->host = optarg;
-        break;
-      case 'p':
-        req->port = atoi(optarg);
-        break;
-      case 'u':
-        req->url = optarg;
-        break;
-      case 'K':
-        req->keyfile = optarg;
-        break;
-      case 'P':
-        req->password = optarg;
-        break;
-      case 'V':
-        req->virtualhost = optarg;
-        break;
-      case 'C':
-        req->cafile = optarg;
-        break;
-      default:
-        usage(argv[0]);
-        return CMD_LINE_ERROR;
-    }
-  }
-
-  /* check unexpected arguments */
-  if ((optarg = (char *)poptGetArg(context))) {
-    fprintf(stderr, "unexpected argument %s", optarg);
-    return CMD_LINE_ERROR;
-  }
-
-  /* free the allocated context */
-  poptFreeContext(context);
-  
-  return CMD_LINE_SUCCESS;
+       poptContext context;
+       char *optarg = NULL;
+       int c;
+
+       struct poptOption options_table[] = {
+               {"version", 'v', POPT_ARG_NONE, NULL, 'v'},
+               {"help", 'h', POPT_ARG_NONE, NULL, 'h'},
+               {"use-ssl", 'S', POPT_ARG_NONE, NULL, 'S'},
+               {"server", 's', POPT_ARG_STRING, &optarg, 's'},
+               {"port", 'p', POPT_ARG_STRING, &optarg, 'p'},
+               {"url", 'u', POPT_ARG_STRING, &optarg, 'u'},
+               {"use-private-key", 'K', POPT_ARG_STRING, &optarg, 'K'},
+               {"use-virtualhost", 'V', POPT_ARG_STRING, &optarg, 'V'},
+               {"use-password", 'P', POPT_ARG_STRING, &optarg, 'P'},
+               {"use-certificate", 'C', POPT_ARG_STRING, &optarg, 'C'},
+               {NULL, 0, 0, NULL, 0}
+       };
+
+       context =
+           poptGetContext(PROG, argc, (const char **) argv, options_table, 0);
+       if ((c = poptGetNextOpt(context)) < 0) {
+               usage(argv[0]);
+               return CMD_LINE_ERROR;
+       }
+
+       /* The first option car */
+       switch (c) {
+       case 'v':
+               fprintf(stderr, "%s Version %s\n", PROG, VERSION);
+               break;
+       case 'h':
+               usage(argv[0]);
+               break;
+       case 'S':
+               req->ssl = 1;
+               break;
+       case 's':
+               req->host = optarg;
+               break;
+       default:
+               usage(argv[0]);
+               return CMD_LINE_ERROR;
+       }
+
+       /* the others */
+       while ((c = poptGetNextOpt(context)) >= 0) {
+               switch (c) {
+               case 's':
+                       req->host = optarg;
+                       break;
+               case 'p':
+                       req->port = atoi(optarg);
+                       break;
+               case 'u':
+                       req->url = optarg;
+                       break;
+               case 'K':
+                       req->keyfile = optarg;
+                       break;
+               case 'P':
+                       req->password = optarg;
+                       break;
+               case 'V':
+                       req->virtualhost = optarg;
+                       break;
+               case 'C':
+                       req->cafile = optarg;
+                       break;
+               default:
+                       usage(argv[0]);
+                       return CMD_LINE_ERROR;
+               }
+       }
+
+       /* check unexpected arguments */
+       if ((optarg = (char *) poptGetArg(context))) {
+               fprintf(stderr, "unexpected argument %s", optarg);
+               return CMD_LINE_ERROR;
+       }
+
+       /* free the allocated context */
+       poptFreeContext(context);
+
+       return CMD_LINE_SUCCESS;
 }
 
-int main(int argc, char **argv)
+int
+main(int argc, char **argv)
 {
-  REQ *req;
-  char *buffer;
-  int err=0;
+       REQ *req;
+       char *buffer;
+       int err = 0;
 
-  /* Allocate the room */
-  req    = (REQ *)xmalloc(sizeof(REQ));
-  buffer = (char *)xmalloc(RCV_BUFFER_LENGTH);
+       /* Allocate the room */
+       req = (REQ *) xmalloc(sizeof (REQ));
+       buffer = (char *) xmalloc(RCV_BUFFER_LENGTH);
 
-  /* Command line parser */
-  if (!parse_cmdline(argc, argv, req))
-    exit(0);
+       /* Command line parser */
+       if (!parse_cmdline(argc, argv, req))
+               exit(0);
 
-  /* Check minimum configuration need */
-  if (!req->host && !req->port && !req->url) {
-    exit(0);
-  }
+       /* Check minimum configuration need */
+       if (!req->host && !req->port && !req->url) {
+               exit(0);
+       }
 
-  /* finalize req initialisation  */
-  req->buffer = buffer;
-  req->max    = RCV_BUFFER_LENGTH; 
+       /* finalize req initialisation  */
+       req->buffer = buffer;
+       req->max = RCV_BUFFER_LENGTH;
 
-  /* Now make our HTTP/SSL request */
-  err = req->ssl ? genhash_ssl(req) : genhash_http(req);
-  print_error(err); 
+       /* Now make our HTTP/SSL request */
+       err = req->ssl ? genhash_ssl(req) : genhash_http(req);
+       print_error(err);
 
-  free(req);
-  return(1);
+       free(req);
+       return (1);
 }
index 8f0b0de..ee29905 100644 (file)
 
 /* HTTP/HTTPS request structure */
 typedef struct {
-  char *host;
-  char *buffer;
-  int error;
-  int max;
-  int len;
-  char *url;
-  unsigned short int port;
-  int fd;
-  int ssl;
-  char *keyfile;
-  char *password;
-  char *virtualhost;
-  char *cafile;
+       char *host;
+       char *buffer;
+       int error;
+       int max;
+       int len;
+       char *url;
+       unsigned short int port;
+       int fd;
+       int ssl;
+       char *keyfile;
+       char *password;
+       char *virtualhost;
+       char *cafile;
 } REQ;
 
 /* Output delimiters */
diff --git a/genhash/main.o b/genhash/main.o
new file mode 100644 (file)
index 0000000..0b8c066
Binary files /dev/null and b/genhash/main.o differ
diff --git a/ipfwwrapper.c b/ipfwwrapper.c
deleted file mode 100644 (file)
index c62ce8f..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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:        IPFW Kernel wrapper. Use Rusty firewall manipulation
- *              library to add/remove server MASQ rules to the kernel 
- *              firewall framework.
- *
- * Version:     $Id: ipfwwrapper.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "ipfwwrapper.h"
-#include "utils.h"
-
-int ipfw_cmd(int cmd, virtual_server *vs, real_server *rs)
-{
-  struct ip_fwuser ctl;
-  int ret = 1;
-
-  memset(&ctl, 0, sizeof(struct ip_fwuser));
-
-  /* Create the firewall MASQ rule */
-  strncpy(ctl.label, IP_FW_LABEL_MASQUERADE, IP_FW_MAX_LABEL_LENGTH);
-  ctl.ipfw.fw_proto = vs->service_type;
-  /* compute the source ip address */
-  ctl.ipfw.fw_src.s_addr  = SVR_IP(rs) & vs->nat_mask;
-  ctl.ipfw.fw_smsk.s_addr = vs->nat_mask;
-
-  ctl.ipfw.fw_spts[0] = ctl.ipfw.fw_spts[1] = htons(SVR_PORT(rs));
-  ctl.ipfw.fw_dpts[0] = 0x0000;
-  ctl.ipfw.fw_dpts[1] = 0xFFFF;
-  ctl.ipfw.fw_tosand = 0xFF;
-  ctl.ipfw.fw_tosxor = 0x00;
-
-  if (cmd & IP_FW_CMD_ADD) {
-    ipfwc_delete_entry(IP_FW_LABEL_FORWARD, &ctl);
-    if (!(errno & EINVAL)) {
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "ipfw_cmd : MASQ firewall rule [%s:%d] already exist."
-                      , inet_ntop2(SVR_IP(rs))
-                      , ntohs(SVR_PORT(rs)));
-#endif
-    }
-    ret &= ipfwc_insert_entry(IP_FW_LABEL_FORWARD, &ctl, 1);
-  }
-
-  if (cmd & IP_FW_CMD_DEL)
-    ret &= ipfwc_delete_entry(IP_FW_LABEL_FORWARD, &ctl);
-
-  if(!ret) {
-#ifdef _DEBUG_
-    syslog(LOG_DEBUG, "ipfw_cmd : firewall error (%s) processing [%s:%d] MASQ rule."
-                    , strerror(errno)
-                    , inet_ntop2(SVR_IP(rs))
-                    , ntohs(SVR_PORT(rs)));
-#endif
-    return IPFW_ERROR;
-  }
-
-  return IPFW_SUCCESS;
-}
diff --git a/ipvswrapper.c b/ipvswrapper.c
deleted file mode 100644 (file)
index 3adee3c..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-/* 
- * 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:        IPVS Kernel wrapper. Use setsockopt call to add/remove
- *              server to/from the loadbalanced server pool.
- *  
- * Version:     $Id: ipvswrapper.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "ipvswrapper.h"
-#include "utils.h"
-
-#ifdef _KRNL_2_2_  /* KERNEL 2.2 LVS handling */
-
-int ipvs_syncd_cmd(int cmd, char *ifname, int state)
-{
-  syslog(LOG_INFO, "IPVS : Sync daemon not supported on kernel v2.2");
-  return IPVS_ERROR;
-}
-
-int ipvs_cmd(int cmd, virtual_server *vs, real_server *rs)
-{
-  struct ip_masq_ctl ctl;
-  int result=0;
-  int sockfd;
-
-  memset(&ctl, 0, sizeof(struct ip_masq_ctl));
-
-  ctl.m_target = IP_MASQ_TARGET_VS;
-  ctl.m_cmd = cmd;
-  strncpy(ctl.m_tname, vs->sched, IP_MASQ_TNAME_MAX);
-  ctl.u.vs_user.weight = -1;
-  ctl.u.vs_user.masq_flags = vs->loadbalancing_kind;
-  ctl.u.vs_user.netmask = ((u_int32_t) 0xffffffff);
-  ctl.u.vs_user.protocol = vs->service_type;
-
-  if(!parse_timeout(vs->timeout_persistence, &ctl.u.vs_user.timeout))
-    syslog(LOG_INFO, "IPVS : Virtual service [%s:%d] illegal timeout."
-                   , inet_ntop2(SVR_IP(vs))
-                   , ntohs(SVR_PORT(vs)));
-  if (ctl.u.vs_user.timeout != 0 || vs->granularity_persistence)
-    ctl.u.vs_user.vs_flags = IP_VS_SVC_F_PERSISTENT;
-  
-  /* VS specific */
-  if (vs->vfwmark) {
-    ctl.u.vs_user.vfwmark = vs->vfwmark;
-  } else {
-    ctl.u.vs_user.vaddr = SVR_IP(vs);
-    ctl.u.vs_user.vport = SVR_PORT(vs);
-  }
-
-  if (ctl.m_cmd == IP_MASQ_CMD_ADD || ctl.m_cmd == IP_MASQ_CMD_DEL)
-    if (vs->granularity_persistence)
-      ctl.u.vs_user.netmask = vs->granularity_persistence;
-
-  /* SVR specific */
-  if (ctl.m_cmd == IP_MASQ_CMD_ADD_DEST || ctl.m_cmd == IP_MASQ_CMD_DEL_DEST) {
-    ctl.u.vs_user.weight = rs->weight;
-    ctl.u.vs_user.daddr = SVR_IP(rs);
-    ctl.u.vs_user.dport = SVR_PORT(rs);
-  }
-
-  sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
-  if (sockfd == -1) {
-    syslog(LOG_INFO, "IPVS : Can not initialize SOCK_RAW descriptor.");
-    return IPVS_ERROR;
-  }
-
-  result = setsockopt(sockfd, IPPROTO_IP, IP_FW_MASQ_CTL, (char *)&ctl, sizeof(ctl));
-
-  if (errno == ESRCH) {
-    syslog(LOG_INFO, "IPVS : Virtual service [%s:%d] not defined."
-                   , inet_ntop2(SVR_IP(vs))
-                   , ntohs(SVR_PORT(vs)));
-    close(sockfd);
-    return IPVS_ERROR;
-  } else if (errno == EEXIST) {
-    if (rs)
-      syslog(LOG_INFO, "IPVS : Destination already exists [%s:%d]."
-                     , inet_ntop2(SVR_IP(rs))
-                     , ntohs(SVR_PORT(rs)));
-  } else if (errno == ENOENT) {
-    if (rs)
-      syslog(LOG_INFO, "IPVS : No such destination [%s:%d]."
-                     , inet_ntop2(SVR_IP(rs))
-                     , ntohs(SVR_PORT(rs)));
-  }
-
-  close(sockfd);
-  return IPVS_SUCCESS;
-}
-
-#else /* KERNEL 2.4 LVS handling */
-
-static int ipvs_talk(int cmd, struct ip_vs_rule_user *urule)
-{
-  int result;
-
-  /* Init IPVS kernel channel */
-  if (ipvs_init()) {
-    syslog(LOG_INFO, "IPVS : Can't initialize ipvs: %s"
-                   , ipvs_strerror(errno));
-    return IPVS_ERROR;
-  }
-
-  result = ipvs_command(cmd, urule);
-  if (result) {
-    syslog(LOG_INFO, "IPVS : %s", ipvs_strerror(errno));
-    ipvs_close();
-    return IPVS_ERROR;
-  }
-  ipvs_close();
-  return IPVS_SUCCESS;
-}
-
-int ipvs_syncd_cmd(int cmd, char *ifname, int state)
-{
-#ifdef _HAVE_IPVS_SYNCD_
-
-  struct ip_vs_rule_user urule;
-
-  memset(&urule, 0, sizeof(struct ip_vs_rule_user));
-
-  /* prepare user rule */
-  urule.state = state;
-  if (ifname != NULL)
-    strncpy(urule.mcast_ifn, ifname, IP_VS_IFNAME_MAXLEN);
-
-  /* Talk to the IPVS channel */
-  return ipvs_talk(cmd, &urule);
-
-#else
-  syslog(LOG_INFO, "IPVS : Sync daemon not supported");
-  return IPVS_ERROR;
-#endif
-}
-
-int ipvs_cmd(int cmd, virtual_server *vs, real_server *rs)
-{
-  struct ip_vs_rule_user urule;
-
-  memset(&urule, 0, sizeof(struct ip_vs_rule_user));
-
-  strncpy(urule.sched_name, vs->sched, IP_VS_SCHEDNAME_MAXLEN);
-  urule.weight = 1;
-  urule.conn_flags = vs->loadbalancing_kind;
-  urule.netmask    = ((u_int32_t) 0xffffffff);
-  urule.protocol   = vs->service_type;
-  
-  if (!parse_timeout(vs->timeout_persistence, &urule.timeout))
-    syslog(LOG_INFO, "IPVS : Virtual service [%s:%d] illegal timeout."
-                   , inet_ntop2(SVR_IP(vs))
-                   , ntohs(SVR_PORT(vs)));
-  if (urule.timeout != 0 || vs->granularity_persistence)
-    urule.vs_flags = IP_VS_SVC_F_PERSISTENT;
-
-  /* VS specific */
-  if (vs->vfwmark) {
-    urule.vfwmark = vs->vfwmark;
-  } else {
-    urule.vaddr = SVR_IP(vs);
-    urule.vport = SVR_PORT(vs);
-  }
-
-  if (cmd == IP_VS_SO_SET_ADD || cmd == IP_VS_SO_SET_DEL)
-    if (vs->granularity_persistence)
-      urule.netmask  = vs->granularity_persistence;
-
-  /* SVR specific */
-  if (cmd == IP_VS_SO_SET_ADDDEST || cmd == IP_VS_SO_SET_DELDEST) {
-    urule.weight = rs->weight;
-    urule.daddr  = SVR_IP(rs);
-    urule.dport  = SVR_PORT(rs);
-  }
-
-  /* Talk to the IPVS channel */
-  return ipvs_talk(cmd, &urule);
-}
-
-#endif
-
-/*
- * IPVS synchronization daemon state transition
- */
-void ipvs_syncd_master(char *ifname)
-{
-  ipvs_syncd_cmd(IPVS_STOPDAEMON, ifname, IPVS_BACKUP);
-  ipvs_syncd_cmd(IPVS_STARTDAEMON, ifname, IPVS_MASTER);
-}
-
-void ipvs_syncd_backup(char *ifname)
-{
-  ipvs_syncd_cmd(IPVS_STOPDAEMON, ifname, IPVS_MASTER);
-  ipvs_syncd_cmd(IPVS_STARTDAEMON, ifname, IPVS_BACKUP);
-}
-
-/*
- * Source code from the ipvsadm.c Wensong code
- */
-
-int parse_timeout(char *buf, unsigned *timeout)
-{
-  int i;
-
-  if (buf == NULL) {
-    *timeout = IP_VS_TEMPLATE_TIMEOUT;
-    return 1;
-  }
-
-  if ((i=string_to_number(buf, 0, 86400*31)) == -1)
-    return 0;
-
-  *timeout = i * HZ;
-  return 1;
-}
-
-int string_to_number(const char *s, int min, int max)
-{
-  int number;
-  char *end;
-
-  number = (int)strtol(s, &end, 10);
-  if (*end == '\0' && end != s) {
-    /*
-     * We parsed a number, let's see if we want this.
-     * If max <= min then ignore ranges
-     */
-    if (max <= min || ( min <= number && number <= max))
-      return number;
-    else
-      return -1;
-  } else
-    return -1;
-}
diff --git a/ipwrapper.c b/ipwrapper.c
deleted file mode 100644 (file)
index a2d8787..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * 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:        Manipulation functions for IPVS & IPFW wrappers.
- *
- * Version:     $id: ipwrapper.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "ipwrapper.h"
-#include "utils.h"
-
-extern data *conf_data;
-
-static int clear_service_rs(virtual_server *vs, list l)
-{
-  element e;
-
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-    if (!ipvs_cmd(LVS_CMD_DEL_DEST, vs, ELEMENT_DATA(e)))
-      return 0;
-#ifdef _KRNL_2_2_
-    /* if we have a /32 mask, we create one nat rules per
-     * realserver.
-     */
-    if (vs->nat_mask == HOST_NETMASK)
-      if(!ipfw_cmd(IP_FW_CMD_DEL, vs, ELEMENT_DATA(e)))
-        return 0;
-#endif
-  }
-  return 1;
-}
-
-int clear_service_vs(virtual_server *vs)
-{
-  element e;
-  real_server_group *group;
-
-  /* Processing real server queue */
-  if (!LIST_ISEMPTY(vs->rs)) {
-    if (vs->s_svr->alive) {
-      if (!ipvs_cmd(LVS_CMD_DEL_DEST, vs, vs->s_svr))
-        return 0;
-    } else if (!clear_service_rs(vs, vs->rs))
-      return 0;
-  }
-
-  /* Processing real server group queue */
-  if (!LIST_ISEMPTY(vs->rs_group)) {
-    for (e = LIST_HEAD(vs->rs_group); e; ELEMENT_NEXT(e)) {
-      group = ELEMENT_DATA(e);
-      if (!clear_service_rs(vs, group->rs))
-        return 0;
-    }
-  }
-
-  if (!ipvs_cmd(LVS_CMD_DEL, vs, NULL))
-    return 0;
-  return 1;
-}
-
-/* IPVS cleaner processing */
-int clear_services(void)
-{
-  element e;
-  list vs = conf_data->vs;
-  virtual_server *vsvr;
-  real_server *rsvr;
-
-  for (e = LIST_HEAD(vs); e; ELEMENT_NEXT(e)) {
-    vsvr = ELEMENT_DATA(e);
-    rsvr = ELEMENT_DATA(LIST_HEAD(vsvr->rs));
-    if (!clear_service_vs(vsvr))
-      return 0;
-
-#ifdef _KRNL_2_2_
-    if (vsvr->nat_mask != HOST_NETMASK)
-      if (!ipfw_cmd(IP_FW_CMD_DEL, vsvr, rsvr))
-        return 0;
-#endif
-  }
-  return 1;
-}
-
-int all_realservers_down(virtual_server *vs)
-{
-  element e;
-  real_server *svr;
-
-  for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) {
-    svr = ELEMENT_DATA(e);
-    if (svr->alive) return 0;
-  }
-  return 1;
-}
-
-void perform_svr_state(int alive, virtual_server *vs, real_server *rs)
-{
-  char rsip[16], vsip[16];
-
-  if (!ISALIVE(rs) && alive) {
-
-    /* adding a server to the vs pool, if sorry server is flagged alive,
-     * we remove it from the vs pool.
-     */
-    if (vs->s_svr) {
-      if (vs->s_svr->alive) {
-        syslog(LOG_INFO, "Removing sorry server [%s:%d] from VS [%s:%d]"
-                       , inet_ntoa2(SVR_IP(vs->s_svr), rsip)
-                       , ntohs(SVR_PORT(vs->s_svr))
-                       , inet_ntoa2(SVR_IP(vs), vsip)
-                       , ntohs(SVR_PORT(vs)));
-
-        vs->s_svr->alive = 0;
-        ipvs_cmd(LVS_CMD_DEL_DEST, vs, vs->s_svr);
-#ifdef _KRNL_2_2_
-        ipfw_cmd(IP_FW_CMD_DEL, vs, vs->s_svr);
-#endif
-      }
-    }
-
-    rs->alive = alive;
-    syslog(LOG_INFO, "Adding service [%s:%d] to VS [%s:%d]"
-                   , inet_ntoa2(SVR_IP(rs), rsip)
-                   , ntohs(SVR_PORT(rs))
-                   , inet_ntoa2(SVR_IP(vs), vsip)
-                   , ntohs(SVR_PORT(vs)));
-    ipvs_cmd(LVS_CMD_ADD_DEST, vs, rs);
-
-#ifdef _KRNL_2_2_
-    if (vs->nat_mask == HOST_NETMASK)
-      ipfw_cmd(IP_FW_CMD_ADD, vs, rs);
-#endif
-
-  } else {
-
-    rs->alive = alive;
-    syslog(LOG_INFO, "Removing service [%s:%d] from VS [%s:%d]"
-                   , inet_ntoa2(SVR_IP(rs), rsip)
-                   , ntohs(SVR_PORT(rs))
-                   , inet_ntoa2(SVR_IP(vs), vsip)
-                   , ntohs(SVR_PORT(vs)));
-
-    /* server is down, it is removed from the LVS realserver pool */
-    ipvs_cmd(LVS_CMD_DEL_DEST, vs, rs);
-
-#ifdef _KRNL_2_2_
-    if (vs->nat_mask == HOST_NETMASK)
-      ipfw_cmd(IP_FW_CMD_DEL, vs, rs);
-#endif
-
-    /* if all the realserver pool is down, we add sorry server */
-    if (vs->s_svr && all_realservers_down(vs)) {
-      syslog(LOG_INFO, "Adding sorry server [%s:%d] to VS [%s:%d]"
-                     , inet_ntoa2(SVR_IP(vs->s_svr), rsip)
-                     , ntohs(SVR_PORT(vs->s_svr))
-                     , inet_ntoa2(SVR_IP(vs), vsip)
-                     , ntohs(SVR_PORT(vs)));
-
-      /* the sorry server is now up in the pool, we flag it alive */
-      vs->s_svr->alive = 1;
-      ipvs_cmd(LVS_CMD_ADD_DEST, vs, vs->s_svr);
-
-#ifdef _KRNL_2_2_
-      ipfw_cmd(IP_FW_CMD_ADD, vs, vs->s_svr);
-#endif
-    }
-
-  }
-}
-
-static int init_service_rs(virtual_server *vs, list l)
-{
-  element e;
-
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-    if (!ipvs_cmd(LVS_CMD_ADD_DEST, vs, ELEMENT_DATA(e)))
-      return 0;
-#ifdef _KRNL_2_2_
-    /* if we have a /32 mask, we create one nat rules per
-     * realserver.
-     */
-    if (vs->nat_mask == HOST_NETMASK)
-      if(!ipfw_cmd(IP_FW_CMD_ADD, vs, ELEMENT_DATA(e)))
-        return 0;
-#endif
-  }
-  return 1;
-}
-
-int init_service_vs(virtual_server *vs)
-{
-  element e;
-  real_server_group *group;
-
-  /* Init the IPVS root */
-  if (!ipvs_cmd(LVS_CMD_ADD, vs, NULL))
-    return 0;
-
-  /* Processing real server queue */
-  if (!LIST_ISEMPTY(vs->rs))
-    if (!init_service_rs(vs, vs->rs))
-      return 0;
-
-  /* Processing real server group queue */
-  if (!LIST_ISEMPTY(vs->rs_group)) {
-    for (e = LIST_HEAD(vs->rs_group); e; ELEMENT_NEXT(e)) {
-      group = ELEMENT_DATA(e);
-      if (!init_service_rs(vs, group->rs))
-        return 0;
-    }
-  }
-  return 1;
-}
-
-int init_services(void)
-{
-  element e;
-  list vs = conf_data->vs;
-  virtual_server *vsvr;
-  real_server *rsvr;
-
-  for (e = LIST_HEAD(vs); e; ELEMENT_NEXT(e)) {
-    vsvr = ELEMENT_DATA(e);
-    rsvr = ELEMENT_DATA(LIST_HEAD(vsvr->rs));
-    if (!init_service_vs(vsvr))
-      return 0;
-
-#ifdef _KRNL_2_2_
-    /* work if all realserver ip address are in the
-     * same network (it is assumed).
-     */
-    if (vsvr->nat_mask != HOST_NETMASK)
-      if (!ipfw_cmd(IP_FW_CMD_ADD, vsvr, rsvr))
-        return 0;
-#endif
-  }
-  return 1;
-}
diff --git a/keepalived.spec b/keepalived.spec
new file mode 100644 (file)
index 0000000..6789e88
--- /dev/null
@@ -0,0 +1,33 @@
+Summary: Generic HA monitor build upon VRRP and services poller, strongly recommanded for LVS HA.
+Name: keepalived
+Packager: Christophe Varoqui <christophe.varoqui@free.fr>
+Version: 0.6.6
+Release: 1
+Source: http://www.keepalived.org/software/keepalived-0.6.6.tar.gz
+Copyright: GPL
+Group: Utilities/File
+BuildRoot: /tmp/%{name}-%{version}.build
+BuildArchitectures: i386
+
+%description
+The main goal of the keepalived project is to add a strong & robust keepalive facility to the Linux Virtual Server project. This project is written in C with multilayer TCP/IP stack checks. Keepalived implements a framework based on three family checks : Layer3, Layer4 & Layer5. This framework gives the daemon the ability of checking a LVS server pool states. When one of the server of the LVS server pool is down, keepalived informs the linux kernel via a setsockopt call to remove this server entrie from the LVS topology. In addition keepalived implements a VRRPv2 stack to handle director failover. So in short keepalived is a userspace daemon for LVS cluster nodes healthchecks and LVS directors failover.
+
+%prep
+rm -rf %{buildroot}
+%setup -n keepalived-0.6.6
+
+%build
+./configure --prefix=%{buildroot} --exec-prefix=%{buildroot} --sysconfdir=%{buildroot}/etc
+make
+
+%install
+make install
+
+%files
+%defattr(-,root,root)
+/bin/genhash
+/sbin/keepalived
+/etc/init.d/keepalived.init
+%config /etc/keepalived/keepalived.conf
+%config /etc/keepalived/samples/*
+%doc AUTHOR CONTRIBUTORS TODO COPYING README INSTALL VERSION ChangeLog
diff --git a/keepalived/Makefile.in b/keepalived/Makefile.in
new file mode 100644 (file)
index 0000000..cacbd02
--- /dev/null
@@ -0,0 +1,87 @@
+# Makefile
+#
+# Keepalived OpenSource project.
+#
+# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
+
+EXEC = keepalived
+BIN       = ../bin
+KERNEL    = @KERN@
+IPVS_FLAG = @IPVS_SUPPORT@
+VRRP_FLAG = @VRRP_SUPPORT@
+
+prefix      = @prefix@
+exec_prefix = @exec_prefix@
+sbindir     = @sbindir@
+sysconfdir  = @sysconfdir@
+init_script = etc/init.d/keepalived.init
+conf_file   = etc/keepalived/keepalived.conf
+
+CC = @CC@
+LDFLAGS = @LIBS@ @LDFLAGS@
+SUBDIRS = core
+
+ifeq ($(IPVS_FLAG),_WITH_LVS_)
+  SUBDIRS += healthcheck
+endif
+
+ifeq ($(VRRP_FLAG),_WITH_VRRP_)
+  SUBDIRS += vrrp
+endif
+
+ifeq ($(IPVS_FLAG),_WITH_LVS_)
+  ifeq ($(KERNEL),_KRNL_2_2_)
+    SUBDIRS += libipfwc
+  else
+    SUBDIRS += libipvs
+  endif
+endif
+
+all:
+       @set -e; \
+       for i in $(SUBDIRS); do \
+       $(MAKE) -C $$i; done && \
+       echo "Building $(EXEC) in $(BIN)" && \
+       $(CC) -o $(BIN)/$(EXEC) $(LDFLAGS) `find $(SUBDIRS) -name '*.[oa]'`
+       strip $(BIN)/$(EXEC)
+       @echo ""
+       @echo "Make complete"
+
+debug:
+       @set -e; \
+       for i in $(SUBDIRS); do \
+       $(MAKE) -C $$i; done && \
+       echo "Building $(EXEC) in $(BIN)" && \
+       $(CC) -o $(BIN)/$(EXEC) $(LDFLAGS) `find $(SUBDIRS) -name '*.[oa]'`
+       @echo ""
+       @echo "Make complete"
+
+clean:
+       @set -e; \
+       for i in $(SUBDIRS); do \
+       $(MAKE) -C $$i clean; done
+       @echo ""
+       @echo "Make complete"
+
+distclean:
+       @set -e; \
+       for i in $(SUBDIRS); do \
+       $(MAKE) -C $$i distclean; done
+       rm -f Makefile
+
+mrproper: distclean
+       rm -f config.*
+
+uninstall:
+       rm -f $(sbindir)/$(EXEC)
+       rm -rf $(sysconfdir)/keepalived
+       rm -f $(init_dir)/$(init_script)
+
+install:
+       install -d $(sbindir)
+       install -m 700 $(BIN)/$(EXEC) $(sbindir)/
+       install -d $(sysconfdir)/init.d
+       install -m 755 $(init_script) $(sysconfdir)/init.d/
+       install -d $(sysconfdir)/keepalived/samples
+       install -m 644 $(conf_file) $(sysconfdir)/keepalived/
+       install -m 644 samples/* $(sysconfdir)/keepalived/samples/
diff --git a/keepalived/core/Makefile.in b/keepalived/core/Makefile.in
new file mode 100644 (file)
index 0000000..dea3ec9
--- /dev/null
@@ -0,0 +1,28 @@
+# Makefile
+#
+# Keepalived OpenSource project.
+#
+# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
+
+CC      = @CC@
+INCLUDES = -I../include
+CFLAGS  = @CFLAGS@ $(INCLUDES) \
+          -Wall -Wunused -Wstrict-prototypes
+DEFS    = -D@KERN@ -D@IPVS_SUPPORT@ @DFLAGS@
+COMPILE         = $(CC) $(CFLAGS) $(DEFS)
+
+OBJS =         main.o memory.o daemon.o pidfile.o utils.o timer.o \
+       scheduler.o vector.o list.o data.o parser.o layer4.o \
+       smtp.o
+HEADERS = $(OBJS:.o=.h)
+
+.c.o:
+       $(COMPILE) -c $<
+
+all:   $(OBJS)
+
+clean:
+       rm -f *.a *.o *~
+
+distclean: clean
+       rm -f Makefile
similarity index 55%
rename from daemon.c
rename to keepalived/core/daemon.c
index 6265c8a..920f31a 100644 (file)
--- a/daemon.c
@@ -5,7 +5,7 @@
  *
  * Part:        Main program structure.
  *
- * Version:     $Id: main.c,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: main.c,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include "daemon.h"
 
 /* Daemonization function coming from zebra source code */
-pid_t xdaemon(int nochdir, int noclose, int exitflag)
+pid_t
+xdaemon(int nochdir, int noclose, int exitflag)
 {
-  pid_t pid;
+       pid_t pid;
 
-  /* In case of fork is error. */
-  pid = fork ();
-  if (pid < 0) {
-    perror ("fork");
-    return -1;
-  }
+       /* In case of fork is error. */
+       pid = fork();
+       if (pid < 0) {
+               perror("fork");
+               return -1;
+       }
 
-  /* In case of this is parent process. */
-  if (pid != 0 ) {
-    if (!exitflag)
-      exit(0);
-    else
-      return pid;
-  }
+       /* In case of this is parent process. */
+       if (pid != 0) {
+               if (!exitflag)
+                       exit(0);
+               else
+                       return pid;
+       }
 
-  /* Become session leader and get pid. */
-  pid = setsid();
-  if (pid < -1) {
-    perror ("setsid");
-    return -1;
-  }
+       /* Become session leader and get pid. */
+       pid = setsid();
+       if (pid < -1) {
+               perror("setsid");
+               return -1;
+       }
 
-  /* Change directory to root. */
-  if (!nochdir)
-    chdir ("/");
+       /* Change directory to root. */
+       if (!nochdir)
+               chdir("/");
 
-  /* File descriptor close. */
-  if (!noclose) {
-    int fd;
+       /* File descriptor close. */
+       if (!noclose) {
+               int fd;
 
-    fd = open("/dev/null", O_RDWR, 0);
-    if (fd != -1) {
-      dup2(fd, STDIN_FILENO);
-      dup2(fd, STDOUT_FILENO);
-      dup2(fd, STDERR_FILENO);
-      if (fd > 2)
-        close (fd);
-    }
-  }
+               fd = open("/dev/null", O_RDWR, 0);
+               if (fd != -1) {
+                       dup2(fd, STDIN_FILENO);
+                       dup2(fd, STDOUT_FILENO);
+                       dup2(fd, STDERR_FILENO);
+                       if (fd > 2)
+                               close(fd);
+               }
+       }
 
-  umask (0);
-  return 0;
+       umask(0);
+       return 0;
 }
diff --git a/keepalived/core/data.c b/keepalived/core/data.c
new file mode 100644 (file)
index 0000000..b03c3ed
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * 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:        Dynamic data structure definition.
+ *
+ * Version:     $Id: data.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "data.h"
+#include "memory.h"
+#include "utils.h"
+#include "check_api.h"
+#include "vrrp.h"
+#include "vrrp_sync.h"
+
+extern data *conf_data;
+
+/* email facility functions */
+static void
+free_email(void *data)
+{
+       FREE(data);
+}
+static void
+dump_email(void *data)
+{
+       char *addr = data;
+       syslog(LOG_INFO, " Email notification = %s", addr);
+}
+
+void
+alloc_email(char *addr)
+{
+       int size = strlen(addr);
+       char *new;
+
+       new = (char *) MALLOC(size + 1);
+       memcpy(new, addr, size);
+
+       list_add(conf_data->email, new);
+}
+
+/* SSL facility functions */
+SSL_DATA *
+alloc_ssl(void)
+{
+       SSL_DATA *ssl = (SSL_DATA *) MALLOC(sizeof (SSL_DATA));
+       return ssl;
+}
+static void
+free_ssl(void)
+{
+       SSL_DATA *ssl = conf_data->ssl;
+
+       if (!ssl)
+               return;
+       FREE_PTR(ssl->password);
+       FREE_PTR(ssl->cafile);
+       FREE_PTR(ssl->certfile);
+       FREE_PTR(ssl->keyfile);
+       FREE(ssl);
+}
+static void
+dump_ssl(void)
+{
+       SSL_DATA *ssl = conf_data->ssl;
+
+       if (ssl->password)
+               syslog(LOG_INFO, " Password : %s", ssl->password);
+       if (ssl->cafile)
+               syslog(LOG_INFO, " CA-file : %s", ssl->cafile);
+       if (ssl->certfile)
+               syslog(LOG_INFO, " Certificate file : %s", ssl->certfile);
+       if (ssl->keyfile)
+               syslog(LOG_INFO, " Key file : %s", ssl->keyfile);
+       if (!ssl->password && !ssl->cafile && !ssl->certfile && !ssl->keyfile)
+               syslog(LOG_INFO, " Using autogen SSL context");
+}
+
+/* VRRP facility functions */
+static void
+free_vgroup(void *data)
+{
+       vrrp_sgroup *vgroup = data;
+
+       FREE(vgroup->gname);
+       free_strvec(vgroup->iname);
+       FREE_PTR(vgroup->script_backup);
+       FREE_PTR(vgroup->script_master);
+       FREE_PTR(vgroup->script_fault);
+       FREE(vgroup);
+}
+static void
+dump_vgroup(void *data)
+{
+       vrrp_sgroup *vgroup = data;
+       int i;
+       char *str;
+
+       syslog(LOG_INFO, " VRRP Sync Group = %s, %s", vgroup->gname,
+              (vgroup->state == VRRP_STATE_MAST) ? "MASTER" : "BACKUP");
+       for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
+               str = VECTOR_SLOT(vgroup->iname, i);
+               syslog(LOG_INFO, "   monitor = %s", str);
+       }
+       if (vgroup->script_backup)
+               syslog(LOG_INFO, "   Backup state transition script = %s",
+                      vgroup->script_backup);
+       if (vgroup->script_master)
+               syslog(LOG_INFO, "   Master state transition script = %s",
+                      vgroup->script_master);
+       if (vgroup->script_fault)
+               syslog(LOG_INFO, "   Fault state transition script = %s",
+                      vgroup->script_fault);
+}
+
+static void
+free_vrrp(void *data)
+{
+       vrrp_rt *vrrp = data;
+
+       FREE(vrrp->iname);
+       FREE_PTR(vrrp->lvs_syncd_if);
+       FREE_PTR(vrrp->vaddr);
+       FREE_PTR(vrrp->evaddr);
+       FREE_PTR(vrrp->script_backup);
+       FREE_PTR(vrrp->script_master);
+       FREE_PTR(vrrp->script_fault);
+       FREE(vrrp->ipsecah_counter);
+       FREE(vrrp);
+}
+static void
+dump_vrrp(void *data)
+{
+       vrrp_rt *vrrp = data;
+       int i;
+
+       syslog(LOG_INFO, " VRRP Instance = %s", vrrp->iname);
+       if (vrrp->init_state == VRRP_STATE_BACK)
+               syslog(LOG_INFO, "   Want State = BACKUP");
+       else
+               syslog(LOG_INFO, "   Want State = MASTER");
+       syslog(LOG_INFO, "   Runing on device = %s", IF_NAME(vrrp->ifp));
+       if (vrrp->mcast_saddr)
+               syslog(LOG_INFO, "   Using mcast src_ip = %s",
+                      inet_ntop2(vrrp->mcast_saddr));
+       if (vrrp->lvs_syncd_if)
+               syslog(LOG_INFO, "   Runing LVS sync daemon on interface = %s",
+                      vrrp->lvs_syncd_if);
+       syslog(LOG_INFO, "   Virtual Router ID = %d", vrrp->vrid);
+       syslog(LOG_INFO, "   Priority = %d", vrrp->priority);
+       syslog(LOG_INFO, "   Advert interval = %dsec",
+              vrrp->adver_int / TIMER_HZ);
+       if (vrrp->preempt)
+               syslog(LOG_INFO, "   Preempt Active");
+       if (vrrp->auth_type) {
+               syslog(LOG_INFO, "   Authentication type = %s",
+                      (vrrp->auth_type ==
+                       VRRP_AUTH_AH) ? "IPSEC_AH" : "SIMPLE_PASSWORD");
+               syslog(LOG_INFO, "   Password = %s", vrrp->auth_data);
+       }
+       syslog(LOG_INFO, "   VIP count = %d", vrrp->naddr);
+       for (i = 0; i < vrrp->naddr; i++)
+               syslog(LOG_INFO, "     VIP%d = %s/%d", i + 1,
+                      inet_ntop2(vrrp->vaddr[i].addr)
+                      , vrrp->vaddr[i].mask);
+       if (vrrp->neaddr) {
+               syslog(LOG_INFO, "   Excluded VIP count = %d", vrrp->neaddr);
+               for (i = 0; i < vrrp->neaddr; i++)
+                       syslog(LOG_INFO, "     E-VIP%d = %s/%d", i + 1,
+                              inet_ntop2(vrrp->evaddr[i].addr)
+                              , vrrp->evaddr[i].mask);
+       }
+       if (vrrp->script_backup)
+               syslog(LOG_INFO, "   Backup state transition script = %s",
+                      vrrp->script_backup);
+       if (vrrp->script_master)
+               syslog(LOG_INFO, "   Master state transition script = %s",
+                      vrrp->script_master);
+       if (vrrp->script_fault)
+               syslog(LOG_INFO, "   Fault state transition script = %s",
+                      vrrp->script_fault);
+       if (vrrp->smtp_alert)
+               syslog(LOG_INFO, "   Using smtp notification");
+}
+
+void
+alloc_vrrp_sync_group(char *gname)
+{
+       int size = strlen(gname);
+       vrrp_sgroup *new;
+
+       /* Allocate new VRRP group structure */
+       new = (vrrp_sgroup *) MALLOC(sizeof (vrrp_sgroup));
+       new->gname = (char *) MALLOC(size + 1);
+       new->state = VRRP_STATE_BACK;
+       memcpy(new->gname, gname, size);
+
+       list_add(conf_data->vrrp_sync_group, new);
+}
+
+void
+alloc_vrrp(char *iname)
+{
+       int size = strlen(iname);
+       seq_counter *counter;
+       vrrp_rt *new;
+
+       /* Allocate new VRRP structure */
+       new = (vrrp_rt *) MALLOC(sizeof (vrrp_rt));
+       counter = (seq_counter *) MALLOC(sizeof (seq_counter));
+
+       /* Build the structure */
+       new->ipsecah_counter = counter;
+
+       /* Set default values */
+       new->wantstate = VRRP_STATE_BACK;
+       new->init_state = VRRP_STATE_BACK;
+       new->adver_int = TIMER_HZ;
+       new->iname = (char *) MALLOC(size + 1);
+       memcpy(new->iname, iname, size);
+       new->sync = vrrp_get_sync_group(iname);
+
+       list_add(conf_data->vrrp, new);
+}
+
+void
+alloc_vrrp_vip(char *vip)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       uint32_t ipaddr = 0;
+       uint8_t mask = inet_stom(vip);
+       inet_ston(vip, &ipaddr);
+
+       vrrp->naddr++;
+       if (vrrp->vaddr)
+               vrrp->vaddr =
+                   REALLOC(vrrp->vaddr, vrrp->naddr * sizeof (*vrrp->vaddr));
+       else
+               vrrp->vaddr = (vip_addr *) MALLOC(sizeof (*vrrp->vaddr));
+       vrrp->vaddr[vrrp->naddr - 1].addr = ipaddr;
+       vrrp->vaddr[vrrp->naddr - 1].mask = mask;
+       vrrp->vaddr[vrrp->naddr - 1].set = 0;
+}
+
+void
+alloc_vrrp_evip(char *vip)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       uint32_t ipaddr = 0;
+       uint8_t mask = inet_stom(vip);
+       inet_ston(vip, &ipaddr);
+
+       vrrp->neaddr++;
+       if (vrrp->evaddr)
+               vrrp->evaddr =
+                   REALLOC(vrrp->evaddr,
+                           vrrp->neaddr * sizeof (*vrrp->evaddr));
+       else
+               vrrp->evaddr = (vip_addr *) MALLOC(sizeof (*vrrp->evaddr));
+       vrrp->evaddr[vrrp->neaddr - 1].addr = ipaddr;
+       vrrp->evaddr[vrrp->neaddr - 1].mask = mask;
+       vrrp->evaddr[vrrp->neaddr - 1].set = 0;
+}
+
+/* Virtual server facility functions */
+static void
+free_vs(void *data)
+{
+       virtual_server *vs = data;
+       FREE_PTR(vs->virtualhost);
+       FREE_PTR(vs->s_svr);
+       if (!LIST_ISEMPTY(vs->rs))
+               free_list(vs->rs);
+       if (!LIST_ISEMPTY(vs->rs_group))
+               free_list(vs->rs_group);
+       FREE(vs);
+}
+static void
+dump_vs(void *data)
+{
+       virtual_server *vs = data;
+
+       if (vs->vfwmark)
+               syslog(LOG_INFO, " VS FWMARK = %d", vs->vfwmark);
+       else
+               syslog(LOG_INFO, " VIP = %s, VPORT = %d", inet_ntop2(SVR_IP(vs))
+                      , 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,
+              vs->sched);
+       if (atoi(vs->timeout_persistence) > 0)
+               syslog(LOG_INFO, "   persistence timeout = %s",
+                      vs->timeout_persistence);
+       if (vs->granularity_persistence)
+               syslog(LOG_INFO, "   persistence granularity = %s",
+                      inet_ntop2(vs->granularity_persistence));
+       syslog(LOG_INFO, "   protocol = %s",
+              (vs->service_type == IPPROTO_TCP) ? "TCP" : "UDP");
+
+       switch (vs->loadbalancing_kind) {
+#ifdef _WITH_LVS_
+#ifdef _KRNL_2_2_
+       case 0:
+               syslog(LOG_INFO, "   lb_kind = NAT");
+               syslog(LOG_INFO, "   nat mask = %s", inet_ntop2(vs->nat_mask));
+               break;
+       case IP_MASQ_F_VS_DROUTE:
+               syslog(LOG_INFO, "   lb_kind = DR");
+               break;
+       case IP_MASQ_F_VS_TUNNEL:
+               syslog(LOG_INFO, "   lb_kind = TUN");
+               break;
+#else
+       case IP_VS_CONN_F_MASQ:
+               syslog(LOG_INFO, "   lb_kind = NAT");
+               break;
+       case IP_VS_CONN_F_DROUTE:
+               syslog(LOG_INFO, "   lb_kind = DR");
+               break;
+       case IP_VS_CONN_F_TUNNEL:
+               syslog(LOG_INFO, "   lb_kind = TUN");
+               break;
+#endif
+#endif
+       }
+
+       if (vs->s_svr) {
+               syslog(LOG_INFO, "   sorry server = %s:%d",
+                      inet_ntop2(SVR_IP(vs->s_svr))
+                      , ntohs(SVR_PORT(vs->s_svr)));
+       }
+       if (!LIST_ISEMPTY(vs->rs))
+               dump_list(vs->rs);
+       if (!LIST_ISEMPTY(vs->rs_group))
+               dump_list(vs->rs_group);
+}
+
+void
+alloc_vs(char *ip, char *port)
+{
+       virtual_server *new;
+
+       new = (virtual_server *) MALLOC(sizeof (virtual_server));
+
+       if (!strcmp(ip, "fwmark")) {
+               new->vfwmark = atoi(port);
+       } else {
+               inet_ston(ip, &new->addr_ip);
+               new->addr_port = htons(atoi(port));
+       }
+       new->delay_loop = KEEPALIVED_DEFAULT_DELAY;
+       strncpy(new->timeout_persistence, "0", 1);
+       new->virtualhost = NULL;
+
+       list_add(conf_data->vs, new);
+}
+
+/* Sorry server facility functions */
+void
+alloc_ssvr(char *ip, char *port)
+{
+       virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+
+       vs->s_svr = (real_server *) MALLOC(sizeof (real_server));
+       vs->s_svr->weight = 1;
+       inet_ston(ip, &vs->s_svr->addr_ip);
+       vs->s_svr->addr_port = htons(atoi(port));
+}
+
+/* Real server facility functions */
+static void
+free_rs(void *data)
+{
+       real_server *rs = data;
+       FREE(rs);
+}
+static void
+dump_rs(void *data)
+{
+       real_server *rs = data;
+       syslog(LOG_INFO, "   RIP = %s, RPORT = %d, WEIGHT = %d",
+              inet_ntop2(SVR_IP(rs))
+              , ntohs(SVR_PORT(rs))
+              , rs->weight);
+}
+
+void
+alloc_rs(char *ip, char *port)
+{
+       virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+       real_server *new;
+
+       new = (real_server *) MALLOC(sizeof (real_server));
+
+       inet_ston(ip, &new->addr_ip);
+       new->addr_port = htons(atoi(port));
+       new->alive = 1;
+
+       if (LIST_ISEMPTY(vs->rs))
+               vs->rs = alloc_list(free_rs, dump_rs);
+       list_add(vs->rs, new);
+       vs->last_rs_type = RS;
+}
+
+/* Real server group facility functions */
+static void
+free_group(void *data)
+{
+       real_server_group *group = data;
+       FREE(group->gname);
+       if (!LIST_ISEMPTY(group->rs))
+               free_list(group->rs);
+//  if (!LIST_ISEMPTY(group->vs))
+//    free_list(group->vs);
+       FREE(group);
+}
+static void
+dump_group(void *data)
+{
+       real_server_group *group = data;
+       syslog(LOG_INFO, " Real Server Group = %s", group->gname);
+       dump_list(group->rs);
+}
+
+void
+alloc_rsgroup(char *ip, char *port)
+{
+       real_server_group *group = LIST_TAIL_DATA(conf_data->group);
+       real_server *new;
+
+       new = (real_server *) MALLOC(sizeof (real_server));
+
+       inet_ston(ip, &new->addr_ip);
+       new->addr_port = htons(atoi(port));
+       new->alive = 1;
+
+       if (LIST_ISEMPTY(group->rs))
+               group->rs = alloc_list(free_rs, dump_rs);
+       list_add(group->rs, new);
+}
+
+void
+alloc_group(char *name)
+{
+       real_server_group *new;
+       int size = strlen(name);
+
+       new = (real_server_group *) MALLOC(sizeof (real_server_group));
+
+       new->gname = (char *) MALLOC(size + 1);
+       memcpy(new->gname, name, size);
+       list_add(conf_data->group, new);
+}
+static real_server_group *
+get_group_by_name(char *name)
+{
+       real_server_group *group;
+       element e;
+
+       for (e = LIST_HEAD(conf_data->group); e; ELEMENT_NEXT(e)) {
+               group = ELEMENT_DATA(e);
+               if (strcmp(group->gname, name) == 0)
+                       return group;
+       }
+       return NULL;
+}
+static void
+dump_rs_group(void *data)
+{
+       real_server_group *group = data;
+       syslog(LOG_INFO, "   Linking Real Server Group = %s", group->gname);
+}
+
+void
+set_rsgroup(char *gname)
+{
+       real_server_group *group = get_group_by_name(gname);
+       virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+
+       if (group) {
+               if (LIST_ISEMPTY(vs->rs_group))
+                       vs->rs_group = alloc_list(NULL, dump_rs_group);
+               list_add(vs->rs_group, group);
+               vs->last_rs_type = RS_GROUP;
+       }
+}
+
+/* data facility functions */
+data *
+alloc_data(void)
+{
+       data *new;
+
+       new = (data *) MALLOC(sizeof (data));
+       new->email = alloc_list(free_email, dump_email);
+       new->vrrp = alloc_list(free_vrrp, dump_vrrp);
+       new->vrrp_sync_group = alloc_list(free_vgroup, dump_vgroup);
+       new->vs = alloc_list(free_vs, dump_vs);
+       new->group = alloc_list(free_group, dump_group);
+
+       return new;
+}
+
+void
+free_data(void)
+{
+       free_ssl();
+       free_list(conf_data->email);
+       free_list(conf_data->vrrp);
+       free_list(conf_data->vrrp_sync_group);
+       free_list(conf_data->vs);
+       free_list(conf_data->group);
+
+       FREE_PTR(conf_data->lvs_id);
+       FREE_PTR(conf_data->email_from);
+       FREE(conf_data);
+}
+
+void
+dump_data(void)
+{
+       if (conf_data->lvs_id ||
+           conf_data->smtp_server ||
+           conf_data->smtp_connection_to || conf_data->email_from) {
+               syslog(LOG_INFO, "------< Global definitions >------");
+       }
+       if (conf_data->lvs_id)
+               syslog(LOG_INFO, " LVS ID = %s", conf_data->lvs_id);
+       if (conf_data->smtp_server)
+               syslog(LOG_INFO, " Smtp server = %s",
+                      inet_ntop2(conf_data->smtp_server));
+       if (conf_data->smtp_connection_to)
+               syslog(LOG_INFO, " Smtp server connection timeout = %d",
+                      conf_data->smtp_connection_to);
+       if (conf_data->email_from) {
+               syslog(LOG_INFO, " Email notification from = %s",
+                      conf_data->email_from);
+               dump_list(conf_data->email);
+       }
+       if (conf_data->ssl) {
+               syslog(LOG_INFO, "------< SSL definitions >------");
+               dump_ssl();
+       }
+       if (!LIST_ISEMPTY(conf_data->vrrp)) {
+               syslog(LOG_INFO, "------< VRRP Topology >------");
+               dump_list(conf_data->vrrp);
+       }
+       if (!LIST_ISEMPTY(conf_data->vrrp_sync_group)) {
+               syslog(LOG_INFO, "------< VRRP Sync groups >------");
+               dump_list(conf_data->vrrp_sync_group);
+       }
+       if (!LIST_ISEMPTY(conf_data->group)) {
+               syslog(LOG_INFO, "------< Real Servers groups >------");
+               dump_list(conf_data->group);
+       }
+#ifdef _WITH_LVS_
+       if (!LIST_ISEMPTY(conf_data->vs)) {
+               syslog(LOG_INFO, "------< LVS Topology >------");
+               syslog(LOG_INFO, " System is compiled with LVS v%d.%d.%d",
+                      NVERSION(IP_VS_VERSION_CODE));
+               dump_list(conf_data->vs);
+       }
+       dump_checkers_queue();
+#endif
+}
diff --git a/keepalived/core/layer4.c b/keepalived/core/layer4.c
new file mode 100644 (file)
index 0000000..072cd77
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * 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:        Layer4 checkers handling. Register worker threads &
+ *              upper layer checkers.
+ *
+ * Version:     $Id: layer4.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "layer4.h"
+#include "check_api.h"
+#include "utils.h"
+
+enum connect_result
+tcp_connect(int fd, uint32_t addr_ip, uint16_t addr_port)
+{
+       struct linger li = { 0 };
+       int long_inet;
+       struct sockaddr_in adr_serv;
+       int ret;
+       int val;
+
+       /* free the tcp port after closing the socket descriptor */
+       li.l_onoff = 1;
+       li.l_linger = 0;
+       setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &li,
+                  sizeof (struct linger));
+
+       long_inet = sizeof (struct sockaddr_in);
+       memset(&adr_serv, 0, long_inet);
+       adr_serv.sin_family = AF_INET;
+       adr_serv.sin_port = addr_port;
+       adr_serv.sin_addr.s_addr = addr_ip;
+
+       /* Make socket non-block. */
+       val = fcntl(fd, F_GETFL, 0);
+       fcntl(fd, F_SETFL, val | O_NONBLOCK);
+
+       /* Call connect function. */
+       ret = connect(fd, (struct sockaddr *) &adr_serv, long_inet);
+
+       /* Immediate success */
+       if (ret == 0) {
+               fcntl(fd, F_SETFL, val);
+               return connect_success;
+       }
+
+       /* If connect is in progress then return 1 else it's real error. */
+       if (ret < 0) {
+               if (errno != EINPROGRESS)
+                       return connect_error;
+       }
+
+       /* restore previous fd args */
+       fcntl(fd, F_SETFL, val);
+       return connect_in_progress;
+}
+
+enum connect_result
+tcp_socket_state(int fd, thread * thread, uint32_t addr_ip, uint16_t addr_port,
+                int (*func) (struct _thread *))
+{
+       int status;
+       int slen;
+       int ret = 0;
+       TIMEVAL timer_min;
+
+       /* Handle connection timeout */
+       if (thread->type == THREAD_WRITE_TIMEOUT) {
+               DBG("TCP connection timeout to [%s:%d].",
+                   inet_ntop2(addr_ip), ntohs(addr_port));
+               close(thread->u.fd);
+               return connect_timeout;
+       }
+
+       /* Check file descriptor */
+       slen = sizeof (status);
+       if (getsockopt
+           (thread->u.fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen) < 0)
+               ret = errno;
+
+       /* Connection failed !!! */
+       if (ret) {
+               DBG("TCP connection failed to [%s:%d].",
+                   inet_ntop2(addr_ip), ntohs(addr_port));
+               close(thread->u.fd);
+               return connect_error;
+       }
+
+       /* If status = 0, TCP connection to remote host is established.
+        * Otherwise register checker thread to handle connection in progress,
+        * and other error code until connection is established.
+        * Recompute the write timeout (or pending connection).
+        */
+       if (status != 0) {
+               DBG("TCP connection to [%s:%d] still IN_PROGRESS.",
+                   inet_ntop2(addr_ip), ntohs(addr_port));
+
+               timer_min = timer_sub_now(thread->sands);
+
+               if (TIMER_SEC(timer_min) <= 0)
+                       thread_add_write(thread->master, func,
+                                        THREAD_ARG(thread)
+                                        , thread->u.fd, 0);
+               else
+                       thread_add_write(thread->master, func,
+                                        THREAD_ARG(thread)
+                                        , thread->u.fd, TIMER_SEC(timer_min));
+               return connect_in_progress;
+       }
+
+       return connect_success;
+}
+
+void
+tcp_connection_state(int fd, enum connect_result status, thread * thread,
+                    int (*func) (struct _thread *)
+                    , int timeout)
+{
+       checker *checker;
+
+       checker = THREAD_ARG(thread);
+
+       switch (status) {
+       case connect_error:
+               DBG("TCP connection ERROR to [%s:%d].",
+                   inet_ntop2(SVR_IP(checker->rs)),
+                   ntohs(SVR_PORT(checker->rs)));
+               close(fd);
+               break;
+
+       case connect_success:
+               DBG("TCP connection SUCCESS to [%s:%d].",
+                   inet_ntop2(SVR_IP(checker->rs)),
+                   ntohs(SVR_PORT(checker->rs)));
+               thread_add_write(thread->master, func, checker, fd, timeout);
+               break;
+
+               /* Checking non-blocking connect, we wait until socket is writable */
+       case connect_in_progress:
+               DBG("TCP connection to [%s:%d] now IN_PROGRESS.",
+                   inet_ntop2(SVR_IP(checker->rs)),
+                   ntohs(SVR_PORT(checker->rs)));
+               thread_add_write(thread->master, func, checker, fd, timeout);
+               break;
+
+       default:
+               break;
+       }
+}
diff --git a/keepalived/core/list.c b/keepalived/core/list.c
new file mode 100644 (file)
index 0000000..f6f4f79
--- /dev/null
@@ -0,0 +1,99 @@
+/* 
+ * 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:        List structure manipulation.
+ *  
+ * Version:     $Id: list.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "list.h"
+#include "memory.h"
+
+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;
+}
+
+static element
+alloc_element(void)
+{
+       element new = (element) MALLOC(sizeof (struct _element));
+       return new;
+}
+
+void
+list_add(list l, void *data)
+{
+       element e = alloc_element();
+
+       e->prev = l->tail;
+       e->data = data;
+
+       if (l->head == NULL)
+               l->head = e;
+       else
+               l->tail->next = e;
+       l->tail = e;
+       l->count++;
+}
+
+void *
+list_element(list l, int num)
+{
+       element e;
+       int i = 0;
+
+       e = LIST_HEAD(l);
+
+       /* fetch element number num */
+       for (i = 0; i < num; i++)
+               if (e)
+                       e = ELEMENT_NEXT(e);
+
+       if (e)
+               return ELEMENT_DATA(e);
+       return NULL;
+}
+
+void
+dump_list(list l)
+{
+       element e;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e))
+               if (l->dump)
+                       (*l->dump) (e->data);
+}
+
+void
+free_list(list l)
+{
+       element e;
+       element next;
+
+       for (e = LIST_HEAD(l); e; e = next) {
+               next = e->next;
+               if (l->free)
+                       (*l->free) (e->data);
+               FREE(e);
+       }
+       FREE(l);
+}
diff --git a/keepalived/core/main.c b/keepalived/core/main.c
new file mode 100644 (file)
index 0000000..2ffa8db
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * 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:        Main program structure.
+ *
+ * Version:     $Id: main.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "main.h"
+
+/* SIGHUP handler */
+void
+sighup(int sig)
+{
+       syslog(LOG_INFO, "Terminating on signal");
+
+       /* register the terminate thread */
+       thread_add_terminate_event(master);
+}
+
+/* SIGCHLD handler */
+void
+sigchld(int sig)
+{
+       int child;
+       wait(&child);
+}
+
+/* Signal wrapper */
+void *
+signal_set(int signo, void (*func) (int))
+{
+       int ret;
+       struct sigaction sig;
+       struct sigaction osig;
+
+       sig.sa_handler = func;
+       sigemptyset(&sig.sa_mask);
+       sig.sa_flags = 0;
+#ifdef SA_RESTART
+       sig.sa_flags |= SA_RESTART;
+#endif                         /* SA_RESTART */
+
+       ret = sigaction(signo, &sig, &osig);
+
+       if (ret < 0)
+               return (SIG_ERR);
+       else
+               return (osig.sa_handler);
+}
+
+/* Initialize signal handler */
+void
+signal_init(void)
+{
+       signal_set(SIGHUP, sighup);
+       signal_set(SIGINT, sighup);
+       signal_set(SIGTERM, sighup);
+       signal_set(SIGKILL, sighup);
+       signal_set(SIGCHLD, sigchld);
+}
+
+/* Usage function */
+static void
+usage(const char *prog)
+{
+       fprintf(stderr, VERSION_STRING);
+       fprintf(stderr,
+               "\nUsage:\n"
+               "  %s\n"
+               "  %s -n\n"
+               "  %s -f keepalived.conf\n"
+               "  %s -d\n"
+               "  %s -h\n" "  %s -v\n\n", prog, prog, prog, prog, prog, prog);
+       fprintf(stderr,
+               "Commands:\n"
+               "Either long or short options are allowed.\n"
+               "  %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 --dump-conf       -d       Dump the configuration data.\n"
+               "  %s --log-console     -l       Log message to local console.\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);
+}
+
+/* Command line parser */
+static char *
+parse_cmdline(int argc, char **argv)
+{
+       poptContext context;
+       char *optarg = NULL;
+       char *conf_file = NULL;
+       int c;
+
+       struct poptOption options_table[] = {
+               {"version", 'v', POPT_ARG_NONE, NULL, 'v'},
+               {"help", 'h', POPT_ARG_NONE, NULL, 'h'},
+               {"log-console", 'l', POPT_ARG_NONE, NULL, 'l'},
+               {"dont-fork", 'n', POPT_ARG_NONE, NULL, 'n'},
+               {"dump-conf", 'd', POPT_ARG_NONE, NULL, 'd'},
+               {"use-file", 'f', POPT_ARG_STRING, &optarg, 'f'},
+               {NULL, 0, 0, NULL, 0}
+       };
+
+       context =
+           poptGetContext(PROG, argc, (const char **) argv, options_table, 0);
+       if ((c = poptGetNextOpt(context)) < 0) {
+               return NULL;
+       }
+
+       /* The first option car */
+       switch (c) {
+       case 'v':
+               fprintf(stderr, VERSION_STRING);
+               exit(0);
+               break;
+       case 'h':
+               usage(argv[0]);
+               exit(0);
+               break;
+       case 'l':
+               debug |= 1;
+               break;
+       case 'n':
+               debug |= 2;
+               break;
+       case 'd':
+               debug |= 4;
+               break;
+       case 'f':
+               conf_file = optarg;
+               break;
+       }
+
+       /* the others */
+       while ((c = poptGetNextOpt(context)) >= 0) {
+               switch (c) {
+               case 'l':
+                       debug |= 1;
+                       break;
+               case 'n':
+                       debug |= 2;
+                       break;
+               case 'd':
+                       debug |= 4;
+                       break;
+               case 'f':
+                       conf_file = optarg;
+                       break;
+               }
+       }
+
+       /* check unexpected arguments */
+       if ((optarg = (char *) poptGetArg(context))) {
+               fprintf(stderr, "unexpected argument %s\n", optarg);
+               return NULL;
+       }
+
+       /* free the allocated context */
+       poptFreeContext(context);
+
+       return ((conf_file) ? conf_file : NULL);
+}
+
+/* Entry point */
+int
+main(int argc, char **argv)
+{
+       char *conf_file = NULL;
+       thread thread;
+
+       /* Init debugging level */
+       debug = 0;
+
+       /*
+        * Parse command line and set debug level.
+        * bits 0..7 reserved by main.c
+        */
+       conf_file = parse_cmdline(argc, argv);
+
+       openlog(PROG, LOG_PID | (debug & 1) ? LOG_CONS : 0, LOG_DAEMON);
+       syslog(LOG_INFO, "Starting " VERSION_STRING);
+
+       /* Check if keepalived is already running */
+       if (keepalived_running()) {
+               syslog(LOG_INFO, "Stopping " VERSION_STRING);
+               closelog();
+               exit(0);
+       }
+
+       /* daemonize process */
+       if (!(debug & 2))
+               xdaemon(0, 0, 0);
+
+       /* write the pidfile */
+       if (!pidfile_write(getpid())) {
+               syslog(LOG_INFO, "Stopping " VERSION_STRING);
+               closelog();
+               exit(0);
+       }
+
+       /* Signal handling initialization  */
+       signal_init();
+
+       /* Init interface queue */
+       init_interface_queue();
+
+       /* Parse the configuration file */
+#ifdef _WITH_LVS_
+       init_checkers_queue();
+#endif
+       init_data(conf_file);
+       if (!conf_data) {
+               syslog(LOG_INFO, "Stopping " VERSION_STRING);
+               closelog();
+#ifdef _DEBUG_
+               keepalived_free_final();
+#endif
+               exit(0);
+       }
+
+       /* SSL load static data & initialize common ctx context */
+#ifdef _WITH_LVS_
+       if (!init_ssl_ctx()) {
+               closelog();
+#ifdef _DEBUG_
+               keepalived_free_final();
+#endif
+               exit(0);
+       }
+#endif
+
+#ifdef _WITH_LVS_
+       if (!init_services()) {
+               syslog(LOG_INFO, "Stopping " VERSION_STRING);
+               closelog();
+               free_data();
+               exit(0);
+       }
+#endif
+
+       /* Create the master thread */
+       master = thread_make_master();
+
+       /* register workers threads */
+       kernel_netlink_init();
+       if_mii_poller_init();
+#ifdef _WITH_LVS_
+       register_checkers_thread();
+#endif
+       if (!vrrp_complete_init())
+               goto end;
+       register_vrrp_thread();
+
+       /* Dump the configuration */
+       if (debug & 4)
+               dump_data();
+
+       /* processing the master thread queues, return and execute one ready thread */
+       while (thread_fetch(master, &thread)) {
+
+               /* Run until error, used for debuging only */
+#ifdef _DEBUG_
+               if ((debug & 520) == 520) {
+                       debug &= ~520;
+                       thread_add_terminate_event(master);
+               }
+#endif
+               thread_call(&thread);
+       }
+
+end:
+       /* Reached when terminate signal catched */
+       syslog(LOG_INFO, "Stopping " VERSION_STRING);
+       /* Just cleanup memory & exit */
+       thread_destroy_master(master);
+#ifdef _WITH_LVS_
+       free_checkers_queue();
+       clear_services();
+#endif
+       shutdown_vrrp_instances();
+       free_interface_queue();
+       free_data();
+
+       pidfile_rm();
+
+#ifdef _DEBUG_
+       keepalived_free_final();
+#endif
+
+       closelog();
+       /* finally return from system */
+       exit(0);
+}
diff --git a/keepalived/core/memory.c b/keepalived/core/memory.c
new file mode 100644 (file)
index 0000000..d60c875
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ * 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:        Memory management framework. This framework is used to
+ *              find any memory leak.
+ *
+ * Version:     $Id: memory.c,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.net>
+ *
+ *              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.
+ */
+
+#include "memory.h"
+
+void *
+xalloc(unsigned long size)
+{
+       void *mem;
+       if ((mem = malloc(size)))
+               mem_allocated += size;
+       return mem;
+}
+
+void *
+zalloc(unsigned long size)
+{
+       void *mem;
+       if ((mem = malloc(size))) {
+               memset(mem, 0, size);
+               mem_allocated += size;
+       }
+       return mem;
+}
+
+void
+xfree(void *p)
+{
+       mem_allocated -= sizeof (p);
+       free(p);
+}
+
+/* KeepAlived memory management. in debug mode,
+ * help finding eventual memory leak.
+ * Allocation memory types manipulated are :
+ *
+ * +type+--------meaning--------+
+ * ! 0  ! Free slot             !
+ * ! 1  ! Overrun               !
+ * ! 2  ! free null             !
+ * ! 3  ! realloc null          !
+ * ! 4  ! Not previus allocated !
+ * ! 8  ! Last free list        !
+ * ! 9  ! Allocated             !
+ * +----+-----------------------+
+ *
+ * global variabel debug bit 9 ( 512 ) used to
+ * flag some memory error.
+ *
+ */
+
+#ifdef _DEBUG_
+extern void print_buffer(int, char *);
+
+typedef struct {
+       int type;
+       int line;
+       char *func;
+       char *file;
+       void *ptr;
+       unsigned long size;
+       long csum;
+} MEMCHECK;
+
+/* Last free pointers */
+static MEMCHECK free_list[256];
+
+static MEMCHECK alloc_list[512];
+static int number_alloc_list = 0;
+static int n = 0;              /* Alloc list pointer */
+static int f = 0;              /* Free list pointer */
+static int s = 0;              /* Indent counter */
+
+static char *
+nspace(int n)
+{
+
+       return "";
+
+/*
+ static char buf[64];
+ int start = 0; 
+ char *p;
+ p = buf;
+ while ( n-- > start ) {       
+  *p++ = ' '; 
+ }
+ *p=0;
+
+ return buf;
+*/
+
+}
+
+char *
+keepalived_malloc(unsigned long size, char *file, char *function, int line)
+{
+       void *buf;
+       int i = 0;
+       long check;
+
+       buf = zalloc(size + sizeof (long));
+
+       check = 0xa5a5 + size;
+       *(long *) ((char *) buf + size) = check;
+
+       while (i < number_alloc_list) {
+               if (alloc_list[i].type == 0)
+                       break;
+               i++;
+       }
+
+       if (i == number_alloc_list)
+               number_alloc_list++;
+
+       alloc_list[i].ptr = buf;
+       alloc_list[i].size = size;
+       alloc_list[i].file = file;
+       alloc_list[i].func = function;
+       alloc_list[i].line = line;
+       alloc_list[i].csum = check;
+       alloc_list[i].type = 9;
+
+       if (debug & 1)
+               printf("%szalloc[%3d:%3d], %p, %4ld at %s, %3d, %s\n",
+                      nspace(s++), i, number_alloc_list, buf, size, file, line,
+                      function);
+
+       n++;
+       return buf;
+}
+
+int
+keepalived_free(void *buffer, char *file, char *function, int line)
+{
+       int i = 0;
+       void *buf;
+
+       /* If nullpointer remember */
+       if (buffer == NULL) {
+               i = number_alloc_list++;
+               alloc_list[i].ptr = buffer;
+               alloc_list[i].size = 0;
+               alloc_list[i].file = file;
+               alloc_list[i].func = function;
+               alloc_list[i].line = line;
+               alloc_list[i].type = 2;
+               if (debug & 1)
+                       printf("%sfree NULL in %s, %3d, %s\n", nspace(s), file,
+                              line, function);
+
+               debug |= 512;   /* Memory Error detect */
+
+               return n;
+       } else
+               buf = buffer;
+
+       while (i < number_alloc_list) {
+               if (alloc_list[i].type == 9 && alloc_list[i].ptr == buf) {
+                       if (*
+                           ((long *) ((char *) alloc_list[i].ptr +
+                                      alloc_list[i].size)) ==
+                           alloc_list[i].csum)
+                               alloc_list[i].type = 0; /* Release */
+                       else {
+                               alloc_list[i].type = 1; /* Overrun */
+                               if (debug & 1) {
+                                       printf
+                                           ("%sfree corrupt, buffer overrun [%3d:%3d], %p, %4ld at %s, %3d, %s\n",
+                                            nspace(--s), i, number_alloc_list,
+                                            buf, alloc_list[i].size, file,
+                                            line, function);
+                                       print_buffer(alloc_list[i].size +
+                                                    sizeof (long),
+                                                    alloc_list[i].ptr);
+                                       printf("%sCheck_sum\n", nspace(i));
+                                       print_buffer(sizeof (long),
+                                                    (char *) &alloc_list[i].
+                                                    csum);
+
+                                       debug |= 512;   /* Memory Error detect */
+                               }
+                       }
+                       break;
+               }
+               i++;
+       }
+
+       /*  Not found */
+       if (i == number_alloc_list) {
+               printf("Free ERROR %p\n", buffer);
+               number_alloc_list++;
+               alloc_list[i].ptr = buf;
+               alloc_list[i].size = 0;
+               alloc_list[i].file = file;
+               alloc_list[i].func = function;
+               alloc_list[i].line = line;
+               alloc_list[i].type = 4;
+               debug |= 512;
+
+               return n;
+       }
+
+       if (buffer != NULL)
+               free(buffer);
+
+       if (debug & 1)
+               printf("%sfree  [%3d:%3d], %p, %4ld at %s, %3d, %s\n",
+                      nspace(--s), i, number_alloc_list, buf,
+                      alloc_list[i].size, file, line, function);
+
+       free_list[f].file = file;
+       free_list[f].line = line;
+       free_list[f].func = function;
+       free_list[f].ptr = buffer;
+       free_list[f].type = 8;
+       free_list[f].csum = i;  /* Using this field for row id */
+
+       f++;
+       f &= 255;
+       n--;
+
+       return n;
+}
+
+void
+keepalived_free_final(void)
+{
+       unsigned int sum = 0, overrun = 0, badptr = 0;
+       int i, j;
+       i = 0;
+
+       printf("\n---[Keepalived memory dump]---\n\n");
+
+       while (i < number_alloc_list) {
+               switch (alloc_list[i].type) {
+               case 3:
+                       badptr++;
+                       printf
+                           ("null pointer to realloc(nil,%ld)! at %s, %3d, %s\n",
+                            alloc_list[i].size, alloc_list[i].file,
+                            alloc_list[i].line, alloc_list[i].func);
+                       break;
+               case 4:
+                       badptr++;
+                       printf
+                           ("pointer not found in table to free(%p) [%3d:%3d], at %s, %3d, %s\n",
+                            alloc_list[i].ptr, i, number_alloc_list,
+                            alloc_list[i].file, alloc_list[i].line,
+                            alloc_list[i].func);
+                       for (j = 0; j < 256; j++)
+                               if (free_list[j].ptr == alloc_list[i].ptr)
+                                       if (free_list[j].type == 8)
+                                               printf
+                                                   ("  -> pointer allready released at [%3d:%3d], at %s, %3d, %s\n",
+                                                    (int) free_list[j].csum,
+                                                    number_alloc_list,
+                                                    free_list[j].file,
+                                                    free_list[j].line,
+                                                    free_list[j].func);
+                       break;
+               case 2:
+                       badptr++;
+                       printf("null pointer to free(nil)! at %s, %3d, %s\n",
+                              alloc_list[i].file, alloc_list[i].line,
+                              alloc_list[i].func);
+                       break;
+               case 1:
+                       overrun++;
+                       printf("%p [%3d:%3d], %4ld buffer overrun!:\n",
+                              alloc_list[i].ptr, i, number_alloc_list,
+                              alloc_list[i].size);
+                       printf(" --> source of malloc: %s, %3d, %s\n",
+                              alloc_list[i].file, alloc_list[i].line,
+                              alloc_list[i].func);
+                       break;
+               case 9:
+                       sum += alloc_list[i].size;
+                       printf("%p [%3d:%3d], %4ld not released!:\n",
+                              alloc_list[i].ptr, i, number_alloc_list,
+                              alloc_list[i].size);
+                       printf(" --> source of malloc: %s, %3d, %s\n",
+                              alloc_list[i].file, alloc_list[i].line,
+                              alloc_list[i].func);
+                       break;
+               }
+               i++;
+       }
+
+       printf("\n\n---[Keepalived memory dump summary]---\n");
+       printf("Total number of bytes not freed...: %d\n", sum);
+       printf("Number of entries not freed.......: %d\n", n);
+       printf("Maximum allocated entries.........: %d\n", number_alloc_list);
+       printf("Number of bad entries.............: %d\n", badptr);
+       printf("Number of buffer overrun..........: %d\n\n", overrun);
+
+       if (sum || n || badptr || overrun)
+               printf("=> Program seems to have some memory problem !!!\n\n");
+       else
+               printf("=> Program seems to be memory allocation safe...\n\n");
+}
+
+void *
+keepalived_realloc(void *buffer, unsigned long size, char *file, char *function,
+                  int line)
+{
+       int i = 0;
+       void *buf, *buf2;
+       long check;
+
+       if (buffer == NULL) {
+               printf("realloc %p %s, %3d %s\n", buffer, file, line, function);
+               i = number_alloc_list++;
+               alloc_list[i].ptr = NULL;
+               alloc_list[i].size = 0;
+               alloc_list[i].file = file;
+               alloc_list[i].func = function;
+               alloc_list[i].line = line;
+               alloc_list[i].type = 3;
+               return keepalived_malloc(size, file, function, line);
+       }
+
+       buf = buffer;
+
+       while (i < number_alloc_list) {
+               if (alloc_list[i].ptr == buf) {
+                       buf = alloc_list[i].ptr;
+                       break;
+               }
+               i++;
+       }
+
+       /* not found */
+       if (i == number_alloc_list) {
+               printf("realloc ERROR no matching zalloc %p \n", buffer);
+               number_alloc_list++;
+               alloc_list[i].ptr = buf;
+               alloc_list[i].size = 0;
+               alloc_list[i].file = file;
+               alloc_list[i].func = function;
+               alloc_list[i].line = line;
+               alloc_list[i].type = 9;
+               debug |= 512;   /* Memory Error detect */
+               return NULL;
+       }
+
+       buf2 = ((char *) buf) + alloc_list[i].size;
+
+       if (*(long *) (buf2) != alloc_list[i].csum) {
+               alloc_list[i].type = 1;
+               debug |= 512;   /* Memory Error detect */
+       }
+       buf = realloc(buffer, size + sizeof (long));
+
+       check = 0xa5a5 + size;
+       *(long *) ((char *) buf + size) = check;
+       alloc_list[i].csum = check;
+
+       if (debug & 1)
+               printf
+                   ("%srealloc [%3d:%3d] %p, %4ld %s %d %s -> %p %4ld %s %d %s\n",
+                    nspace(s), i, number_alloc_list, alloc_list[i].ptr,
+                    alloc_list[i].size, file, line, function, buf, size,
+                    alloc_list[i].file, alloc_list[i].line,
+                    alloc_list[i].func);
+
+       alloc_list[i].ptr = buf;
+       alloc_list[i].size = size;
+       alloc_list[i].file = file;
+       alloc_list[i].line = line;
+       alloc_list[i].func = function;
+
+       return buf;
+}
+
+#endif
diff --git a/keepalived/core/parser.c b/keepalived/core/parser.c
new file mode 100644 (file)
index 0000000..3232148
--- /dev/null
@@ -0,0 +1,836 @@
+/* 
+ * 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:        Configuration file parser/reader. Place into the dynamic
+ *              data structure representation the conf file representing
+ *              the loadbalanced server pool.
+ *  
+ * Version:     $Id: parser.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "parser.h"
+#include "memory.h"
+#include "vrrp.h"
+#include "vrrp_if.h"
+#include "check_api.h"
+
+/* global defs */
+static vector keywords;
+static int sublevel = 0;
+static FILE *stream;
+extern data *conf_data;
+extern unsigned long mem_allocated;
+
+static void
+keyword_alloc(vector keywords, char *string, void (*handler) (vector))
+{
+       struct keyword *keyword;
+
+       vector_alloc_slot(keywords);
+
+       keyword = (struct keyword *) MALLOC(sizeof (struct keyword));
+       keyword->string = string;
+       keyword->handler = handler;
+
+       vector_set_slot(keywords, keyword);
+}
+
+static void
+install_keyword_root(char *string, void (*handler) (vector))
+{
+       keyword_alloc(keywords, string, handler);
+}
+
+void
+install_sublevel(void)
+{
+       sublevel++;
+}
+
+void
+install_sublevel_end(void)
+{
+       sublevel--;
+}
+
+void
+install_keyword(char *string, void (*handler) (vector))
+{
+       int i = 0;
+       struct keyword *keyword;
+
+       /* fetch last keyword */
+       keyword = VECTOR_SLOT(keywords, VECTOR_SIZE(keywords) - 1);
+
+       /* position to last sub level */
+       for (i = 0; i < sublevel; i++)
+               keyword =
+                   VECTOR_SLOT(keyword->sub, VECTOR_SIZE(keyword->sub) - 1);
+
+       /* First sub level allocation */
+       if (!keyword->sub)
+               keyword->sub = vector_alloc();
+
+       /* add new sub keyword */
+       keyword_alloc(keyword->sub, string, handler);
+}
+
+static void
+dump_keywords(vector keydump, int level)
+{
+       int i, j;
+       struct keyword *keyword;
+
+       for (i = 0; i < VECTOR_SIZE(keydump); i++) {
+               keyword = VECTOR_SLOT(keydump, i);
+               for (j = 0; j < level; j++)
+                       printf("  ");
+               printf("Keyword : %s\n", keyword->string);
+               if (keyword->sub)
+                       dump_keywords(keyword->sub, level + 1);
+       }
+}
+
+static void
+free_keywords(vector keywords)
+{
+       struct keyword *keyword;
+       int i;
+
+       for (i = 0; i < VECTOR_SIZE(keywords); i++) {
+               keyword = VECTOR_SLOT(keywords, i);
+               if (keyword->sub)
+                       free_keywords(keyword->sub);
+               FREE(keyword);
+       }
+       vector_free(keywords);
+}
+
+static vector
+alloc_strvec(char *string)
+{
+       char *cp, *start, *token;
+       int strlen;
+       vector strvec;
+
+       if (!string)
+               return NULL;
+
+       cp = string;
+
+       /* Skip white spaces */
+       while (isspace((int) *cp) && *cp != '\0')
+               cp++;
+
+       /* Return if there is only white spaces */
+       if (*cp == '\0')
+               return NULL;
+
+       /* Return if string begin with a comment */
+       if (*cp == '!' || *cp == '#')
+               return NULL;
+
+       /* Create a vector and alloc each command piece */
+       strvec = vector_alloc();
+
+       while (1) {
+               start = cp;
+               if (*cp == '"') {
+                       cp++;
+                       token = MALLOC(2);
+                       *(token) = '"';
+                       *(token + 1) = '\0';
+               } else {
+                       while (!isspace((int) *cp) && *cp != '\0' && *cp != '"')
+                               cp++;
+                       strlen = cp - start;
+                       token = MALLOC(strlen + 1);
+                       memcpy(token, start, strlen);
+                       *(token + strlen) = '\0';
+               }
+
+               /* Alloc & set the slot */
+               vector_alloc_slot(strvec);
+               vector_set_slot(strvec, token);
+
+               while (isspace((int) *cp) && *cp != '\0')
+                       cp++;
+               if (*cp == '\0' || *cp == '!' || *cp == '#')
+                       return strvec;
+       }
+}
+
+static int
+read_line(char *buf, int size)
+{
+       int ch;
+       int count = 0;
+
+       while ((ch = fgetc(stream)) != EOF && (int) ch != '\n'
+              && (int) ch != '\r') {
+               if (count < size)
+                       buf[count] = (int) ch;
+               else
+                       break;
+               count++;
+       }
+       return (ch == EOF) ? 0 : 1;
+}
+
+vector
+read_value_block(void)
+{
+       char *buf;
+       int i;
+       char *str = NULL;
+       char *dup;
+       vector vec = NULL;
+       vector elements = vector_alloc();
+
+       buf = (char *) MALLOC(MAXBUF);
+       while (read_line(buf, MAXBUF)) {
+               vec = alloc_strvec(buf);
+               if (vec) {
+                       str = VECTOR_SLOT(vec, 0);
+                       if (!strcmp(str, EOB)) {
+                               free_strvec(vec);
+                               break;
+                       }
+
+                       if (VECTOR_SIZE(vec))
+                               for (i = 0; i < VECTOR_SIZE(vec); i++) {
+                                       str = VECTOR_SLOT(vec, i);
+                                       dup = (char *) MALLOC(strlen(str) + 1);
+                                       memcpy(dup, str, strlen(str));
+                                       vector_alloc_slot(elements);
+                                       vector_set_slot(elements, dup);
+                               }
+                       free_strvec(vec);
+               }
+               memset(buf, 0, MAXBUF);
+       }
+
+       FREE(buf);
+       return elements;
+}
+
+void *
+set_value(vector strvec)
+{
+       char *str = VECTOR_SLOT(strvec, 1);
+       int size = strlen(str);
+       int i = 0;
+       int len = 0;
+       char *alloc = NULL;
+
+       if (*str == '"') {
+               for (i = 2; i < VECTOR_SIZE(strvec); i++) {
+                       str = VECTOR_SLOT(strvec, i);
+                       len += strlen(str);
+                       if (!alloc)
+                               alloc =
+                                   (char *) MALLOC(sizeof (char *) *
+                                                   (len + 1));
+                       else {
+                               alloc =
+                                   REALLOC(alloc, sizeof (char *) * (len + 1));
+                               strncat(alloc, " ", 1);
+                       }
+                       if (*str != '"')
+                               strncat(alloc, str, strlen(str));
+               }
+       } else {
+               alloc = MALLOC(sizeof (char *) * (size + 1));
+               memcpy(alloc, str, size);
+       }
+       return alloc;
+}
+
+/* data handlers */
+/* Global def handlers */
+static void
+lvsid_handler(vector strvec)
+{
+       conf_data->lvs_id = set_value(strvec);
+}
+static void
+emailfrom_handler(vector strvec)
+{
+       conf_data->email_from = set_value(strvec);
+}
+static void
+smtpto_handler(vector strvec)
+{
+       conf_data->smtp_connection_to = atoi(VECTOR_SLOT(strvec, 1));
+}
+static void
+smtpip_handler(vector strvec)
+{
+       inet_ston(VECTOR_SLOT(strvec, 1), &conf_data->smtp_server);
+}
+static void
+email_handler(vector strvec)
+{
+       vector email = read_value_block();
+       int i;
+       char *str;
+
+       for (i = 0; i < VECTOR_SIZE(email); i++) {
+               str = VECTOR_SLOT(email, i);
+               alloc_email(str);
+       }
+
+       free_strvec(email);
+}
+
+/* SSL handlers */
+static void
+ssl_handler(vector strvec)
+{
+       conf_data->ssl = alloc_ssl();
+}
+static void
+sslpass_handler(vector strvec)
+{
+       conf_data->ssl->password = set_value(strvec);
+}
+static void
+sslca_handler(vector strvec)
+{
+       conf_data->ssl->cafile = set_value(strvec);
+}
+static void
+sslcert_handler(vector strvec)
+{
+       conf_data->ssl->certfile = set_value(strvec);
+}
+static void
+sslkey_handler(vector strvec)
+{
+       conf_data->ssl->keyfile = set_value(strvec);
+}
+
+/* VRRP handlers */
+static void
+vrrp_sync_group_handler(vector strvec)
+{
+       alloc_vrrp_sync_group(VECTOR_SLOT(strvec, 1));
+}
+static void
+vrrp_group_handler(vector strvec)
+{
+       vrrp_sgroup *vgroup = LIST_TAIL_DATA(conf_data->vrrp_sync_group);
+       vgroup->iname = read_value_block();
+}
+static void
+vrrp_gnotify_backup_handler(vector strvec)
+{
+       vrrp_sgroup *vgroup = LIST_TAIL_DATA(conf_data->vrrp_sync_group);
+       vgroup->script_backup = set_value(strvec);
+       vgroup->notify_exec = 1;
+}
+static void
+vrrp_gnotify_master_handler(vector strvec)
+{
+       vrrp_sgroup *vgroup = LIST_TAIL_DATA(conf_data->vrrp_sync_group);
+       vgroup->script_master = set_value(strvec);
+       vgroup->notify_exec = 1;
+}
+static void
+vrrp_gnotify_fault_handler(vector strvec)
+{
+       vrrp_sgroup *vgroup = LIST_TAIL_DATA(conf_data->vrrp_sync_group);
+       vgroup->script_fault = set_value(strvec);
+       vgroup->notify_exec = 1;
+}
+static void
+vrrp_handler(vector strvec)
+{
+       alloc_vrrp(VECTOR_SLOT(strvec, 1));
+}
+static void
+vrrp_state_handler(vector strvec)
+{
+       char *str = VECTOR_SLOT(strvec, 1);
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       vrrp_sgroup *vgroup = vrrp->sync;
+
+       if (!strcmp(str, "MASTER")) {
+               vrrp->wantstate = VRRP_STATE_MAST;
+               vrrp->init_state = VRRP_STATE_MAST;
+       }
+
+       /* set eventual sync group */
+       if (vgroup)
+               vgroup->state = vrrp->wantstate;
+}
+static void
+vrrp_int_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       char *name = VECTOR_SLOT(strvec, 1);
+
+       vrrp->ifp = if_get_by_ifname(name);
+}
+static void
+vrrp_mcastip_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       inet_ston(VECTOR_SLOT(strvec, 1), &vrrp->mcast_saddr);
+}
+static void
+vrrp_vrid_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       vrrp->vrid = atoi(VECTOR_SLOT(strvec, 1));
+
+       if (VRRP_IS_BAD_VID(vrrp->vrid)) {
+               syslog(LOG_INFO, "VRRP Error : VRID not valid !\n");
+               syslog(LOG_INFO,
+                      "             must be between 1 & 255. reconfigure !\n");
+       }
+}
+static void
+vrrp_prio_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       vrrp->priority = atoi(VECTOR_SLOT(strvec, 1));
+
+       if (VRRP_IS_BAD_PRIORITY(vrrp->priority)) {
+               syslog(LOG_INFO, "VRRP Error : Priority not valid !\n");
+               syslog(LOG_INFO,
+                      "             must be between 1 & 255. reconfigure !\n");
+               syslog(LOG_INFO, "             Using default value : 100\n");
+               vrrp->priority = 100;
+       }
+}
+static void
+vrrp_adv_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       vrrp->adver_int = atoi(VECTOR_SLOT(strvec, 1));
+
+       if (VRRP_IS_BAD_ADVERT_INT(vrrp->adver_int)) {
+               syslog(LOG_INFO, "VRRP Error : Advert intervall not valid !\n");
+               syslog(LOG_INFO,
+                      "             must be between less than 1sec.\n");
+               syslog(LOG_INFO, "             Using default value : 1sec\n");
+               vrrp->adver_int = 1;
+       }
+       vrrp->adver_int *= TIMER_HZ;
+}
+static void
+vrrp_debug_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       vrrp->debug = atoi(VECTOR_SLOT(strvec, 1));
+
+       if (VRRP_IS_BAD_DEBUG_INT(vrrp->debug)) {
+               syslog(LOG_INFO, "VRRP Error : Debug intervall not valid !\n");
+               syslog(LOG_INFO, "             must be between 0-4\n");
+               vrrp->debug = 0;
+       }
+}
+static void
+vrrp_preempt_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       vrrp->preempt = !vrrp->preempt;
+}
+static void
+vrrp_notify_backup_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       vrrp->script_backup = set_value(strvec);
+       vrrp->notify_exec = 1;
+}
+static void
+vrrp_notify_master_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       vrrp->script_master = set_value(strvec);
+       vrrp->notify_exec = 1;
+}
+static void
+vrrp_notify_fault_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       vrrp->script_fault = set_value(strvec);
+       vrrp->notify_exec = 1;
+}
+static void
+vrrp_smtp_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       vrrp->smtp_alert = 1;
+}
+static void
+vrrp_lvs_syncd_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       vrrp->lvs_syncd_if = set_value(strvec);
+}
+static void
+vrrp_auth_type_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       char *str = VECTOR_SLOT(strvec, 1);
+
+       if (!strcmp(str, "AH"))
+               vrrp->auth_type = VRRP_AUTH_AH;
+       else
+               vrrp->auth_type = VRRP_AUTH_PASS;
+}
+static void
+vrrp_auth_pass_handler(vector strvec)
+{
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       char *str = VECTOR_SLOT(strvec, 1);
+       int max_size = sizeof (vrrp->auth_data);
+       int size;
+
+       size = (strlen(str) >= max_size) ? max_size - 1 : strlen(str);
+       memcpy(vrrp->auth_data, str, size);
+}
+static void
+vrrp_vip_handler(vector strvec)
+{
+       vector vips = read_value_block();
+       vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+       int i;
+       int nbvip = 0;
+
+       if (VECTOR_SIZE(vips) > VRRP_MAX_VIP) {
+               syslog(LOG_INFO,
+                      "VRRP_Instance(%s) use %d VIPs, trunc to the first %d VIPs.",
+                      vrrp->iname, VECTOR_SIZE(vips)
+                      , VRRP_MAX_VIP);
+               syslog(LOG_INFO,
+                      "  => Declare another VRRP instance to handle all the VIPs");
+               nbvip = VRRP_MAX_VIP;
+       } else
+               nbvip = VECTOR_SIZE(vips);
+
+       for (i = 0; i < nbvip; i++)
+               alloc_vrrp_vip(VECTOR_SLOT(vips, i));
+       free_strvec(vips);
+}
+static void
+vrrp_evip_handler(vector strvec)
+{
+       vector vips = read_value_block();
+       int i;
+
+       for (i = 0; i < VECTOR_SIZE(vips); i++)
+               alloc_vrrp_evip(VECTOR_SLOT(vips, i));
+       free_strvec(vips);
+}
+
+#ifdef _WITH_LVS_
+/* Real Servers groups handlers */
+static void
+group_handler(vector strvec)
+{
+       alloc_group(VECTOR_SLOT(strvec, 1));
+}
+static void
+rsgroup_handler(vector strvec)
+{
+       alloc_rsgroup(VECTOR_SLOT(strvec, 1), VECTOR_SLOT(strvec, 2));
+}
+static void
+group_weight_handler(vector strvec)
+{
+       real_server_group *group = LIST_TAIL_DATA(conf_data->group);
+       real_server *rs = LIST_TAIL_DATA(group->rs);
+       rs->weight = atoi(VECTOR_SLOT(strvec, 1));
+}
+
+/* Virtual Servers handlers */
+static void
+vs_handler(vector strvec)
+{
+       alloc_vs(VECTOR_SLOT(strvec, 1), VECTOR_SLOT(strvec, 2));
+}
+static void
+delay_handler(vector strvec)
+{
+       virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+       vs->delay_loop = atoi(VECTOR_SLOT(strvec, 1));
+}
+static void
+lbalgo_handler(vector strvec)
+{
+       virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+       char *str = VECTOR_SLOT(strvec, 1);
+       int size = sizeof (vs->sched);
+
+       memcpy(vs->sched, str, size);
+}
+static void
+lbkind_handler(vector strvec)
+{
+       virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+       char *str = VECTOR_SLOT(strvec, 1);
+
+#ifdef _KRNL_2_2_
+       if (!strcmp(str, "NAT"))
+               vs->loadbalancing_kind = 0;
+       else if (!strcmp(str, "DR"))
+               vs->loadbalancing_kind = IP_MASQ_F_VS_DROUTE;
+       else if (!strcmp(str, "TUN"))
+               vs->loadbalancing_kind = IP_MASQ_F_VS_TUNNEL;
+#else
+       if (!strcmp(str, "NAT"))
+               vs->loadbalancing_kind = IP_VS_CONN_F_MASQ;
+       else if (!strcmp(str, "DR"))
+               vs->loadbalancing_kind = IP_VS_CONN_F_DROUTE;
+       else if (!strcmp(str, "TUN"))
+               vs->loadbalancing_kind = IP_VS_CONN_F_TUNNEL;
+#endif
+       else
+               syslog(LOG_INFO, "PARSER : unknown [%s] routing method.", str);
+}
+static void
+natmask_handler(vector strvec)
+{
+       virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+       inet_ston(VECTOR_SLOT(strvec, 1), &vs->nat_mask);
+}
+static void
+pto_handler(vector strvec)
+{
+       virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+       char *str = VECTOR_SLOT(strvec, 1);
+       int size = sizeof (vs->timeout_persistence);
+
+       memcpy(vs->timeout_persistence, str, size);
+}
+static void
+pgr_handler(vector strvec)
+{
+       virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+       inet_ston(VECTOR_SLOT(strvec, 1), &vs->granularity_persistence);
+}
+static void
+proto_handler(vector strvec)
+{
+       virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+       char *str = VECTOR_SLOT(strvec, 1);
+       vs->service_type = (!strcmp(str, "TCP")) ? IPPROTO_TCP : IPPROTO_UDP;
+}
+static void
+virtualhost_handler(vector strvec)
+{
+       virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+       vs->virtualhost = set_value(strvec);
+}
+
+/* Sorry Servers handlers */
+static void
+ssvr_handler(vector strvec)
+{
+       alloc_ssvr(VECTOR_SLOT(strvec, 1), VECTOR_SLOT(strvec, 2));
+}
+
+/* Real Servers handlers */
+static void
+rs_handler(vector strvec)
+{
+       alloc_rs(VECTOR_SLOT(strvec, 1), VECTOR_SLOT(strvec, 2));
+}
+static void
+weight_handler(vector strvec)
+{
+       virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+       real_server *rs = LIST_TAIL_DATA(vs->rs);
+       rs->weight = atoi(VECTOR_SLOT(strvec, 1));
+}
+
+/* Real Servers Groups for VS handlers */
+static void
+realgroup_handler(vector strvec)
+{
+       set_rsgroup(VECTOR_SLOT(strvec, 1));
+}
+#endif
+
+/* recursive configuration stream handler */
+static void
+process_stream(vector keywords)
+{
+       int i;
+       struct keyword *keyword;
+       char *str;
+       char *buf;
+       vector strvec;
+
+       buf = MALLOC(MAXBUF);
+       if (!read_line(buf, MAXBUF)) {
+               FREE(buf);
+               return;
+       }
+
+       strvec = alloc_strvec(buf);
+       FREE(buf);
+
+       if (!strvec) {
+               process_stream(keywords);
+               return;
+       }
+
+       str = VECTOR_SLOT(strvec, 0);
+
+       if (!strcmp(str, EOB)) {
+               free_strvec(strvec);
+               return;
+       }
+
+       for (i = 0; i < VECTOR_SIZE(keywords); i++) {
+               keyword = VECTOR_SLOT(keywords, i);
+
+               if (!strcmp(keyword->string, str)) {
+                       if (keyword->handler)
+                               (*keyword->handler) (strvec);
+
+                       if (keyword->sub)
+                               process_stream(keyword->sub);
+                       break;
+               }
+       }
+
+       free_strvec(strvec);
+       process_stream(keywords);
+}
+
+static vector
+init_keywords(void)
+{
+       keywords = vector_alloc();
+
+       /* global definitions mapping */
+       install_keyword_root("global_defs", NULL);
+       install_keyword("lvs_id", &lvsid_handler);
+       install_keyword("notification_email_from", &emailfrom_handler);
+       install_keyword("smtp_server", &smtpip_handler);
+       install_keyword("smtp_connect_timeout", &smtpto_handler);
+       install_keyword("notification_email", &email_handler);
+
+       /* SSL mapping */
+       install_keyword_root("SSL", &ssl_handler);
+       install_keyword("password", &sslpass_handler);
+       install_keyword("ca", &sslca_handler);
+       install_keyword("certificate", &sslcert_handler);
+       install_keyword("key", &sslkey_handler);
+
+       /* VRRP Instance mapping */
+       install_keyword_root("vrrp_sync_group", &vrrp_sync_group_handler);
+       install_keyword("group", &vrrp_group_handler);
+       install_keyword("notify_backup", &vrrp_gnotify_backup_handler);
+       install_keyword("notify_master", &vrrp_gnotify_master_handler);
+       install_keyword("notify_fault", &vrrp_gnotify_fault_handler);
+       install_keyword_root("vrrp_instance", &vrrp_handler);
+       install_keyword("state", &vrrp_state_handler);
+       install_keyword("interface", &vrrp_int_handler);
+       install_keyword("mcast_src_ip", &vrrp_mcastip_handler);
+       install_keyword("virtual_router_id", &vrrp_vrid_handler);
+       install_keyword("priority", &vrrp_prio_handler);
+       install_keyword("advert_int", &vrrp_adv_handler);
+       install_keyword("virtual_ipaddress", &vrrp_vip_handler);
+       install_keyword("virtual_ipaddress_excluded", &vrrp_evip_handler);
+       install_keyword("preempt", &vrrp_preempt_handler);
+       install_keyword("debug", &vrrp_debug_handler);
+       install_keyword("notify_backup", &vrrp_notify_backup_handler);
+       install_keyword("notify_master", &vrrp_notify_master_handler);
+       install_keyword("notify_fault", &vrrp_notify_fault_handler);
+       install_keyword("smtp_alert", &vrrp_smtp_handler);
+       install_keyword("lvs_sync_daemon_interface", &vrrp_lvs_syncd_handler);
+       install_keyword("authentication", NULL);
+       install_sublevel();
+       install_keyword("auth_type", &vrrp_auth_type_handler);
+       install_keyword("auth_pass", &vrrp_auth_pass_handler);
+       install_sublevel_end();
+
+#ifdef _WITH_LVS_
+       /* Real server group mapping */
+       install_keyword_root("real_server_group", &group_handler);
+       install_keyword("real_server", &rsgroup_handler);
+       install_sublevel();
+       install_keyword("weight", &group_weight_handler);
+       install_sublevel_end();
+
+       /* Virtual server mapping */
+       install_keyword_root("virtual_server", &vs_handler);
+       install_keyword("delay_loop", &delay_handler);
+       install_keyword("lb_algo", &lbalgo_handler);
+       install_keyword("lb_kind", &lbkind_handler);
+       install_keyword("nat_mask", &natmask_handler);
+       install_keyword("persistence_timeout", &pto_handler);
+       install_keyword("persistence_granularity", &pgr_handler);
+       install_keyword("protocol", &proto_handler);
+       install_keyword("virtualhost", &virtualhost_handler);
+
+       /* Real server mapping */
+       install_keyword("sorry_server", &ssvr_handler);
+       install_keyword("real_server", &rs_handler);
+       install_sublevel();
+       install_keyword("weight", &weight_handler);
+
+       /* Checkers mapping */
+       install_checkers_keyword();
+       install_sublevel_end();
+
+       /* VS group mapping */
+       install_keyword("real_group", &realgroup_handler);
+       install_sublevel();
+       install_checkers_keyword();
+       install_sublevel_end();
+#endif
+
+       return keywords;
+}
+
+void
+init_data(char *conf_file)
+{
+       vector kw_root;
+       conf_data = NULL;
+       stream = fopen((conf_file) ? conf_file : CONF, "r");
+       if (!stream) {
+               syslog(LOG_INFO, "Configuration file open problem...\n");
+               return;
+       }
+
+       /* Init Keywords structure */
+       kw_root = init_keywords();
+
+/* Dump configuration *
+  vector_dump(keywords);
+  dump_keywords(keywords, 0);
+*/
+
+       /* Init data structure */
+       conf_data = alloc_data();
+
+       /* Stream handling */
+       process_stream(keywords);
+
+       fclose(stream);
+       free_keywords(kw_root);
+
+       syslog(LOG_INFO, "Configuration is using : %lu Bytes", mem_allocated);
+}
similarity index 59%
rename from pidfile.c
rename to keepalived/core/pidfile.c
index e19bab7..8b5ca64 100644 (file)
--- a/pidfile.c
@@ -5,7 +5,7 @@
  *
  * Part:        pidfile utility.
  *
- * Version:     $Id: pidfile.c,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: pidfile.c,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include "pidfile.h"
 
 /* Create the runnnig daemon pidfile */
-int pidfile_write(int pid)
+int
+pidfile_write(int pid)
 {
-  FILE *pidfile = fopen(PIDFILENAME,"w");
+       FILE *pidfile = fopen(PIDFILENAME, "w");
 
-  if(!pidfile) {
-    syslog(LOG_INFO,"pidfile_write : Can not open pidfile");
-    return 0;
-  }
-  fprintf(pidfile,"%d\n",pid);
-  fclose(pidfile);
-  return 1;
+       if (!pidfile) {
+               syslog(LOG_INFO, "pidfile_write : Can not open pidfile");
+               return 0;
+       }
+       fprintf(pidfile, "%d\n", pid);
+       fclose(pidfile);
+       return 1;
 }
 
 /* Remove the running daemon pidfile */
-void pidfile_rm(void)
+void
+pidfile_rm(void)
 {
-  unlink(PIDFILENAME);
+       unlink(PIDFILENAME);
 }
 
 /* return the daemon running state */
-int keepalived_running(void)
+int
+keepalived_running(void)
 {
-  FILE *pidfile = fopen(PIDFILENAME,"r");
-  pid_t pid;
+       FILE *pidfile = fopen(PIDFILENAME, "r");
+       pid_t pid;
 
-  /* No pidfile */
-  if (!pidfile) return 0;
+       /* No pidfile */
+       if (!pidfile)
+               return 0;
 
-  fscanf(pidfile,"%d",&pid);
-  fclose(pidfile);
+       fscanf(pidfile, "%d", &pid);
+       fclose(pidfile);
 
-  /* If no process is attached to pidfile, remove it */
-  if (kill(pid,0)) {
-    syslog(LOG_INFO,"Remove a zombie pid file %s.",PIDFILENAME);
-    pidfile_rm();
-    return 0;
-  }
+       /* If no process is attached to pidfile, remove it */
+       if (kill(pid, 0)) {
+               syslog(LOG_INFO, "Remove a zombie pid file %s.", PIDFILENAME);
+               pidfile_rm();
+               return 0;
+       }
 
-  syslog(LOG_INFO,"daemon is already running");
-  return 1;
+       syslog(LOG_INFO, "daemon is already running");
+       return 1;
 }
diff --git a/keepalived/core/scheduler.c b/keepalived/core/scheduler.c
new file mode 100644 (file)
index 0000000..3edab12
--- /dev/null
@@ -0,0 +1,606 @@
+/*
+ * 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:        Scheduling framework. This code is highly inspired from
+ *              the thread management routine (thread.c) present in the 
+ *              very nice zebra project (http://www.zebra.org).
+ *
+ * Version:     $Id: scheduler.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "scheduler.h"
+#include "memory.h"
+#include "utils.h"
+
+/* Make thread master. */
+thread_master *
+thread_make_master(void)
+{
+       thread_master *new;
+
+       new = (thread_master *) MALLOC(sizeof (thread_master));
+       return new;
+}
+
+/* Add a new thread to the list. */
+static void
+thread_list_add(thread_list * list, thread * thread)
+{
+       thread->next = NULL;
+       thread->prev = list->tail;
+       if (list->tail)
+               list->tail->next = thread;
+       else
+               list->head = thread;
+       list->tail = thread;
+       list->count++;
+}
+
+/* Add a new thread to the list. */
+void
+thread_list_add_before(thread_list * list, thread * point, thread * thread)
+{
+       thread->next = point;
+       thread->prev = point->prev;
+       if (point->prev)
+               point->prev->next = thread;
+       else
+               list->head = thread;
+       point->prev = thread;
+       list->count++;
+}
+
+/* Add a thread in the list sorted by timeval */
+void
+thread_list_add_timeval(thread_list * list, thread * thread)
+{
+       struct _thread *tt;
+
+       for (tt = list->head; tt; tt = tt->next)
+               if (timer_cmp(thread->sands, tt->sands) <= 0)
+                       break;
+
+       if (tt)
+               thread_list_add_before(list, tt, thread);
+       else
+               thread_list_add(list, thread);
+}
+
+/* Delete a thread from the list. */
+thread *
+thread_list_delete(thread_list * list, thread * thread)
+{
+       if (thread->next)
+               thread->next->prev = thread->prev;
+       else
+               list->tail = thread->prev;
+       if (thread->prev)
+               thread->prev->next = thread->next;
+       else
+               list->head = thread->next;
+       thread->next = thread->prev = NULL;
+       list->count--;
+       return thread;
+}
+
+/* Free all unused thread. */
+static void
+thread_clean_unuse(thread_master * m)
+{
+       thread *thread;
+
+       thread = m->unuse.head;
+       while (thread) {
+               struct _thread *t;
+
+               t = thread;
+               thread = t->next;
+
+               thread_list_delete(&m->unuse, t);
+
+               /* free the thread */
+               FREE(t);
+               m->alloc--;
+       }
+}
+
+/* Move thread to unuse list. */
+static void
+thread_add_unuse(thread_master * m, thread * thread)
+{
+       assert(m != NULL);
+       assert(thread->next == NULL);
+       assert(thread->prev == NULL);
+       assert(thread->type == THREAD_UNUSED);
+       thread_list_add(&m->unuse, thread);
+}
+
+/* Move list element to unuse queue */
+void
+thread_destroy_list(thread_master * m, thread_list thread_list)
+{
+       thread *thread;
+
+       thread = thread_list.head;
+
+       while (thread) {
+               struct _thread *t;
+
+               t = thread;
+               thread = t->next;
+
+               thread_list_delete(&thread_list, t);
+               t->type = THREAD_UNUSED;
+               thread_add_unuse(m, t);
+       }
+}
+
+/* Stop thread scheduler. */
+void
+thread_destroy_master(thread_master * m)
+{
+       thread_destroy_list(m, m->read);
+       thread_destroy_list(m, m->write);
+       thread_destroy_list(m, m->timer);
+       thread_destroy_list(m, m->event);
+       thread_destroy_list(m, m->ready);
+
+       thread_clean_unuse(m);
+       FREE(m);
+}
+
+/* Delete top of the list and return it. */
+thread *
+thread_trim_head(thread_list * list)
+{
+       if (list->head)
+               return thread_list_delete(list, list->head);
+       return NULL;
+}
+
+/* Make new thread. */
+thread *
+thread_new(thread_master * m)
+{
+       thread *new;
+
+       /* If one thread is already allocated return it */
+       if (m->unuse.head) {
+               new = thread_trim_head(&m->unuse);
+               memset(new, 0, sizeof (thread));
+               return new;
+       }
+
+       new = (thread *) MALLOC(sizeof (thread));
+       m->alloc++;
+       return new;
+}
+
+/* Add new read thread. */
+thread *
+thread_add_read(thread_master * m, int (*func) (thread *)
+               , void *arg, int fd, long timer)
+{
+       thread *thread;
+       TIMEVAL time_now;
+
+       assert(m != NULL);
+
+       if (FD_ISSET(fd, &m->readfd)) {
+               syslog(LOG_WARNING, "There is already read fd [%d]", fd);
+               return NULL;
+       }
+
+       thread = thread_new(m);
+       thread->type = THREAD_READ;
+       thread->id = 0;
+       thread->master = m;
+       thread->func = func;
+       thread->arg = arg;
+       FD_SET(fd, &m->readfd);
+       thread->u.fd = fd;
+
+       /* Compute read 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 the thread. */
+       thread_list_add_timeval(&m->read, thread);
+
+       return thread;
+}
+
+/* Add new write thread. */
+thread *
+thread_add_write(thread_master * m, int (*func) (thread *)
+                , void *arg, int fd, long timer)
+{
+       thread *thread;
+       TIMEVAL time_now;
+
+       assert(m != NULL);
+
+       if (FD_ISSET(fd, &m->writefd)) {
+               syslog(LOG_WARNING, "There is already write fd [%d]", fd);
+               return NULL;
+       }
+
+       thread = thread_new(m);
+       thread->type = THREAD_WRITE;
+       thread->id = 0;
+       thread->master = m;
+       thread->func = func;
+       thread->arg = arg;
+       FD_SET(fd, &m->writefd);
+       thread->u.fd = fd;
+
+       /* 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 the thread. */
+       thread_list_add_timeval(&m->write, thread);
+
+       return thread;
+}
+
+/* Add timer event thread. */
+thread *
+thread_add_timer(thread_master * m, int (*func) (thread *)
+                , void *arg, long timer)
+{
+       thread *thread;
+       TIMEVAL time_now;
+
+       assert(m != NULL);
+
+       thread = thread_new(m);
+       thread->type = THREAD_TIMER;
+       thread->id = 0;
+       thread->master = m;
+       thread->func = func;
+       thread->arg = arg;
+
+       /* Do we need jitter here? */
+       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->timer, thread);
+
+       return thread;
+}
+
+/* Add simple event thread. */
+thread *
+thread_add_event(thread_master * m, int (*func) (thread *)
+                , void *arg, int val)
+{
+       thread *thread;
+
+       assert(m != NULL);
+
+       thread = thread_new(m);
+       thread->type = THREAD_EVENT;
+       thread->id = 0;
+       thread->master = m;
+       thread->func = func;
+       thread->arg = arg;
+       thread->u.val = val;
+       thread_list_add(&m->event, thread);
+
+       return thread;
+}
+
+/* Add simple event thread. */
+thread *
+thread_add_terminate_event(thread_master * m)
+{
+       thread *thread;
+
+       assert(m != NULL);
+
+       thread = thread_new(m);
+       thread->type = THREAD_TERMINATE;
+       thread->id = 0;
+       thread->master = m;
+       thread->func = NULL;
+       thread->arg = NULL;
+       thread->u.val = 0;
+       thread_list_add(&m->event, thread);
+
+       return thread;
+}
+
+/* Cancel thread from scheduler. */
+void
+thread_cancel(thread * thread)
+{
+       switch (thread->type) {
+       case THREAD_READ:
+               assert(FD_ISSET(thread->u.fd, &thread->master->readfd));
+               FD_CLR(thread->u.fd, &thread->master->readfd);
+               thread_list_delete(&thread->master->read, thread);
+               break;
+       case THREAD_WRITE:
+               assert(FD_ISSET(thread->u.fd, &thread->master->writefd));
+               FD_CLR(thread->u.fd, &thread->master->writefd);
+               thread_list_delete(&thread->master->write, thread);
+               break;
+       case THREAD_TIMER:
+               thread_list_delete(&thread->master->timer, thread);
+               break;
+       case THREAD_EVENT:
+               thread_list_delete(&thread->master->event, thread);
+               break;
+       case THREAD_READY:
+               thread_list_delete(&thread->master->ready, thread);
+               break;
+       default:
+               break;
+       }
+
+       thread->type = THREAD_UNUSED;
+       thread_add_unuse(thread->master, thread);
+}
+
+/* Delete all events which has argument value arg. */
+void
+thread_cancel_event(thread_master * m, void *arg)
+{
+       thread *thread;
+
+       thread = m->event.head;
+       while (thread) {
+               struct _thread *t;
+
+               t = thread;
+               thread = t->next;
+
+               if (t->arg == arg) {
+                       thread_list_delete(&m->event, t);
+                       t->type = THREAD_UNUSED;
+                       thread_add_unuse(m, t);
+               }
+       }
+}
+
+/* Compute the wait timer. Take care of timeouted fd */
+TIMEVAL *
+thread_compute_timer(thread_master * m, TIMEVAL * timer_wait)
+{
+       TIMEVAL time_now;
+       TIMEVAL timer_min;
+
+       TIMER_RESET(timer_min);
+       time_now = timer_now();
+
+       if (m->timer.head)
+               timer_min = m->timer.head->sands;
+
+       if (m->write.head) {
+               if (!TIMER_ISNULL(timer_min)) {
+                       if (timer_cmp(m->write.head->sands, timer_min) <= 0)
+                               timer_min = m->write.head->sands;
+               } else
+                       timer_min = m->write.head->sands;
+       }
+
+       if (m->read.head) {
+               if (!TIMER_ISNULL(timer_min)) {
+                       if (timer_cmp(m->read.head->sands, timer_min) <= 0)
+                               timer_min = m->read.head->sands;
+               } else
+                       timer_min = m->read.head->sands;
+       }
+
+       if (!TIMER_ISNULL(timer_min)) {
+               timer_min = timer_sub(timer_min, time_now);
+               if (timer_min.tv_sec < 0) {
+                       timer_min.tv_sec = 0;
+                       timer_min.tv_usec = 10;
+               }
+               timer_wait->tv_sec = timer_min.tv_sec;
+               timer_wait->tv_usec = timer_min.tv_usec;
+       } else
+               timer_wait = NULL;
+
+       return timer_wait;
+}
+
+/* Fetch next ready thread. */
+thread *
+thread_fetch(thread_master * m, thread * fetch)
+{
+       int ret;
+       thread *thread;
+       fd_set readfd;
+       fd_set writefd;
+       fd_set exceptfd;
+       TIMEVAL time_now;
+       TIMEVAL *timer_wait;
+
+       assert(m != NULL);
+
+       /* Timer allocation */
+       timer_wait = (TIMEVAL *) MALLOC(sizeof (TIMEVAL));
+
+retry: /* When thread can't fetch try to find next thread again. */
+
+       /* If there is event process it first. */
+       while ((thread = thread_trim_head(&m->event))) {
+               *fetch = *thread;
+               FREE(timer_wait);
+
+               /* If daemon hanging event is received return NULL pointer */
+               if (thread->type == THREAD_TERMINATE) {
+                       thread->type = THREAD_UNUSED;
+                       thread_add_unuse(m, thread);
+                       return NULL;
+               }
+               thread->type = THREAD_UNUSED;
+               thread_add_unuse(m, thread);
+               return fetch;
+       }
+
+       /* If there is ready threads process them */
+       while ((thread = thread_trim_head(&m->ready))) {
+               *fetch = *thread;
+               thread->type = THREAD_UNUSED;
+               thread_add_unuse(m, thread);
+               FREE(timer_wait);
+               return fetch;
+       }
+
+       /* Calculate select wait timer. Take care of timeouted fd */
+       timer_wait = thread_compute_timer(m, timer_wait);
+
+       /* Call select function. */
+       readfd = m->readfd;
+       writefd = m->writefd;
+       exceptfd = m->exceptfd;
+
+       ret = select(FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
+       if (ret < 0) {
+               if (errno != EINTR) {
+                       /* Real error. */
+                       DBG("select error: %s", strerror(errno));
+                       assert(0);
+               }
+               /* Signal is coming. */
+               goto retry;
+       }
+
+       /* Read thead. */
+       time_now = timer_now();
+       thread = m->read.head;
+
+       while (thread) {
+               struct _thread *t;
+
+               t = thread;
+               thread = t->next;
+
+               if (FD_ISSET(t->u.fd, &readfd)) {
+                       assert(FD_ISSET(t->u.fd, &m->readfd));
+                       FD_CLR(t->u.fd, &m->readfd);
+                       thread_list_delete(&m->read, t);
+                       thread_list_add(&m->ready, t);
+                       t->type = THREAD_READY;
+               } else {
+                       if (timer_cmp(time_now, t->sands) >= 0) {
+                               FD_CLR(t->u.fd, &m->readfd);
+                               thread_list_delete(&m->read, t);
+                               thread_list_add(&m->ready, t);
+                               t->type = THREAD_READ_TIMEOUT;
+                       }
+               }
+       }
+
+       /* Write thead. */
+       time_now = timer_now();
+       thread = m->write.head;
+
+       while (thread) {
+               struct _thread *t;
+
+               t = thread;
+               thread = t->next;
+
+               if (FD_ISSET(t->u.fd, &writefd)) {
+                       assert(FD_ISSET(t->u.fd, &writefd));
+                       FD_CLR(t->u.fd, &m->writefd);
+                       thread_list_delete(&m->write, t);
+                       thread_list_add(&m->ready, t);
+                       t->type = THREAD_READY;
+               } else {
+                       if (timer_cmp(time_now, t->sands) >= 0) {
+                               FD_CLR(t->u.fd, &m->writefd);
+                               thread_list_delete(&m->write, t);
+                               thread_list_add(&m->ready, t);
+                               t->type = THREAD_WRITE_TIMEOUT;
+                       }
+               }
+       }
+       /* Exception thead. */
+       /*... */
+
+       /* Timer update. */
+       time_now = timer_now();
+
+       thread = m->timer.head;
+       while (thread) {
+               struct _thread *t;
+
+               t = thread;
+               thread = t->next;
+
+               if (timer_cmp(time_now, t->sands) >= 0) {
+                       thread_list_delete(&m->timer, t);
+                       thread_list_add(&m->ready, t);
+                       t->type = THREAD_READY;
+               }
+       }
+
+       /* Return one event. */
+       thread = thread_trim_head(&m->ready);
+
+       /* There is no ready thread. */
+       if (!thread)
+               goto retry;
+
+       *fetch = *thread;
+       thread->type = THREAD_UNUSED;
+       thread_add_unuse(m, thread);
+
+       FREE(timer_wait);
+       return fetch;
+}
+
+/* Make unique thread id for non pthread version of thread manager. */
+unsigned long int
+thread_get_id(void)
+{
+       static unsigned long int counter = 0;
+       return ++counter;
+}
+
+/* Call thread ! */
+void
+thread_call(thread * thread)
+{
+       thread->id = thread_get_id();
+       (*thread->func) (thread);
+}
diff --git a/keepalived/core/smtp.c b/keepalived/core/smtp.c
new file mode 100644 (file)
index 0000000..0be9e4a
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * 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:        SMTP WRAPPER connect to a specified smtp server and send mail
+ *              using the smtp protocol according to the RFC 821. A non blocking
+ *              timeouted connection is used to handle smtp protocol.
+ *
+ * Version:     $Id: smtp.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "smtp.h"
+#include "memory.h"
+#include "list.h"
+#include "utils.h"
+
+extern data *conf_data;
+
+/* static prototype */
+static int smtp_send_cmd_thread(thread *);
+
+static void
+free_smtp_all(smtp_thread_arg * smtp_arg)
+{
+       FREE(smtp_arg->buffer);
+       FREE(smtp_arg->subject);
+       FREE(smtp_arg->body);
+       FREE(smtp_arg);
+}
+
+static char *
+fetch_next_email(smtp_thread_arg * smtp_arg)
+{
+       return list_element(conf_data->email, smtp_arg->email_it);
+}
+
+static int
+smtp_read_cmd_thread(thread * thread)
+{
+       smtp_thread_arg *smtp_arg;
+       char *fetched_email;
+       char *buffer;
+       char *reply;
+       int rcv_buffer_size = 0;
+       int status = -1;
+
+       smtp_arg = THREAD_ARG(thread);
+
+       if (thread->type == THREAD_READ_TIMEOUT) {
+               DBG("Timeout reading data to remote SMTP server [%s:%d].",
+                   inet_ntop2(conf_data->smtp_server), SMTP_PORT);
+               free_smtp_all(smtp_arg);
+               close(thread->u.fd);
+               return 0;
+       }
+
+       buffer = smtp_arg->buffer;
+
+       while ((rcv_buffer_size =
+               read(thread->u.fd, buffer + smtp_arg->buflen,
+                    SMTP_BUFFER_LENGTH - smtp_arg->buflen)) != 0) {
+               if (rcv_buffer_size == -1) {
+                       if (errno == EAGAIN)
+                               goto end;
+                       DBG("Error reading data to remote SMTP server [%s:%d].",
+                           inet_ntop2(conf_data->smtp_server), SMTP_PORT);
+                       free_smtp_all(smtp_arg);
+                       close(thread->u.fd);
+                       return 0;
+               }
+
+               /* received data overflow buffer size ? */
+               if (smtp_arg->buflen >= SMTP_BUFFER_MAX) {
+                       DBG("Received buffer from remote SMTP server [%s:%d]"
+                           " overflow our get read buffer length.",
+                           inet_ntop2(conf_data->smtp_server), SMTP_PORT);
+                       free_smtp_all(smtp_arg);
+                       close(thread->u.fd);
+                       return 0;
+               } else {
+                       smtp_arg->buflen += rcv_buffer_size;
+                       buffer[smtp_arg->buflen] = 0;   /* NULL terminate */
+                       if (rcv_buffer_size < SMTP_BUFFER_LENGTH)
+                               goto end;
+               }
+       }
+
+      end:
+
+// printf("Received : %s", buffer);
+
+       /* parse the buffer, finding the last line of the response for the code */
+       reply = buffer;
+       while (reply < buffer + smtp_arg->buflen) {
+               char *p;
+
+               p = strstr(reply, "\r\n");
+               if (!p) {
+                       memmove(buffer, reply,
+                               smtp_arg->buflen - (reply - buffer));
+                       smtp_arg->buflen -= (reply - buffer);
+                       buffer[smtp_arg->buflen] = 0;
+
+                       thread_add_read(thread->master, smtp_read_cmd_thread,
+                                       smtp_arg, thread->u.fd,
+                                       conf_data->smtp_connection_to);
+                       return 0;
+               }
+
+               if (reply[3] == '-') {
+                       /* Skip over the \r\n */
+                       reply = p + 2;
+                       continue;
+               }
+
+               status =
+                   ((reply[0] - '0') * 100) + ((reply[1] - '0') * 10) +
+                   (reply[2] - '0');
+
+               reply = p + 2;
+               break;
+       }
+
+       memmove(buffer, reply, smtp_arg->buflen - (reply - buffer));
+       smtp_arg->buflen -= (reply - buffer);
+       buffer[smtp_arg->buflen] = 0;
+
+       if (status == -1) {
+               thread_add_read(thread->master, smtp_read_cmd_thread, smtp_arg,
+                               thread->u.fd, conf_data->smtp_connection_to);
+               return 0;
+       }
+
+       /* setting the next stage */
+       switch (smtp_arg->stage) {
+       case CONNECTION:
+               if (status == 220) {
+                       smtp_arg->stage = HELO;
+               } else {
+                       DBG("Error connecting smtp server : [%s]",
+                           buffer);
+                       smtp_arg->stage = ERROR;
+               }
+               break;
+
+       case HELO:
+               if (status == 250) {
+                       smtp_arg->stage = MAIL;
+               } else {
+                       DBG("Error processing HELO cmd : [%s]",
+                           buffer);
+                       smtp_arg->stage = ERROR;
+               }
+               break;
+
+       case MAIL:
+               if (status == 250) {
+                       smtp_arg->stage = RCPT;
+               } else {
+                       DBG("Error processing MAIL FROM cmd : [%s]",
+                           buffer);
+                       smtp_arg->stage = ERROR;
+               }
+               break;
+
+       case RCPT:
+               if (status == 250) {
+                       smtp_arg->email_it++;
+
+                       fetched_email = fetch_next_email(smtp_arg);
+
+                       if (!fetched_email)
+                               smtp_arg->stage = DATA;
+               } else {
+                       DBG("Error processing RCPT TO cmd : [%s]",
+                           buffer);
+                       smtp_arg->stage = ERROR;
+               }
+               break;
+
+       case DATA:
+               if (status == 354) {
+                       smtp_arg->stage = BODY;
+               } else {
+                       DBG("Error processing DATA cmd : [%s]",
+                           buffer);
+                       smtp_arg->stage = ERROR;
+               }
+               break;
+
+       case BODY:
+               if (status == 250) {
+                       smtp_arg->stage = QUIT;
+                       syslog(LOG_INFO, "SMTP alert successfully sent.");
+               } else {
+                       DBG("Error processing DOT cmd : [%s]",
+                           buffer);
+                       smtp_arg->stage = ERROR;
+               }
+               break;
+
+       case QUIT:
+               /* final state, we are disconnected from the remote host */
+               free_smtp_all(smtp_arg);
+               close(thread->u.fd);
+               return 0;
+
+       case ERROR:
+               break;
+       }
+
+       /* Registering next smtp command processing thread */
+       thread_add_write(thread->master, smtp_send_cmd_thread, smtp_arg,
+                        thread->u.fd, conf_data->smtp_connection_to);
+       return 0;
+}
+
+/* Getting localhost official canonical name */
+static char *
+get_local_name(void)
+{
+       struct hostent *host;
+       struct utsname name;
+
+       if (uname(&name) < 0)
+               return NULL;
+
+       if (!(host = gethostbyname(name.nodename)))
+               return NULL;
+
+       return host->h_name;
+}
+
+static int
+smtp_send_cmd_thread(thread * thread)
+{
+       smtp_thread_arg *smtp_arg;
+       char *fetched_email;
+       char *buffer;
+
+       smtp_arg = THREAD_ARG(thread);
+
+       if (thread->type == THREAD_WRITE_TIMEOUT) {
+               DBG("Timeout sending data to remote SMTP server [%s:%d].",
+                   inet_ntop2(conf_data->smtp_server), SMTP_PORT);
+               free_smtp_all(smtp_arg);
+               close(thread->u.fd);
+               return 0;
+       }
+
+       /* allocate temporary command buffer */
+       buffer = (char *) MALLOC(SMTP_BUFFER_MAX);
+
+       switch (smtp_arg->stage) {
+       case CONNECTION:
+               break;
+
+       case HELO:
+               snprintf(buffer, SMTP_BUFFER_MAX, SMTP_HELO_CMD,
+                        get_local_name());
+               if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
+                       smtp_arg->stage = ERROR;
+               break;
+
+       case MAIL:
+               snprintf(buffer, SMTP_BUFFER_MAX, SMTP_MAIL_CMD,
+                        conf_data->email_from);
+               if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
+                       smtp_arg->stage = ERROR;
+               break;
+
+       case RCPT:
+               /* We send RCPT TO command multiple time to add all our email receivers.
+                * --rfc821.3.1
+                */
+               fetched_email = fetch_next_email(smtp_arg);
+
+               snprintf(buffer, SMTP_BUFFER_MAX, SMTP_RCPT_CMD, fetched_email);
+               if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
+                       smtp_arg->stage = ERROR;
+               break;
+
+       case DATA:
+               if (send(thread->u.fd, SMTP_DATA_CMD, strlen(SMTP_DATA_CMD), 0)
+                   == -1)
+                       smtp_arg->stage = ERROR;
+               break;
+
+       case BODY:
+               snprintf(buffer, SMTP_BUFFER_MAX, SMTP_HEADERS_CMD,
+                        conf_data->email_from, smtp_arg->subject);
+               /* send the subject field */
+               if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
+                       smtp_arg->stage = ERROR;
+
+               memset(buffer, 0, SMTP_BUFFER_MAX);
+               snprintf(buffer, SMTP_BUFFER_MAX, SMTP_BODY_CMD,
+                        smtp_arg->body);
+               /* send the the body field */
+               if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
+                       smtp_arg->stage = ERROR;
+
+               /* send the sending dot */
+               if (send(thread->u.fd, SMTP_SEND_CMD, strlen(SMTP_SEND_CMD), 0)
+                   == -1)
+                       smtp_arg->stage = ERROR;
+               break;
+
+       case QUIT:
+               if (send(thread->u.fd, SMTP_QUIT_CMD, strlen(SMTP_QUIT_CMD), 0)
+                   == -1)
+                       smtp_arg->stage = ERROR;
+               break;
+
+       case ERROR:
+               DBG("Can not send data to remote SMTP server [%s:%d].",
+                   inet_ntop2(conf_data->smtp_server), SMTP_PORT);
+               /* we just cleanup the room */
+               free_smtp_all(smtp_arg);
+               close(thread->u.fd);
+               FREE(buffer);
+               return 0;
+               break;
+       }
+
+// printf("Sending : %s", buffer);
+
+       /* Registering next smtp command processing thread */
+       thread_add_read(thread->master, smtp_read_cmd_thread, smtp_arg,
+                       thread->u.fd, conf_data->smtp_connection_to);
+
+       FREE(buffer);
+       return 0;
+}
+
+/* SMTP checkers threads */
+static int
+smtp_check_thread(thread * thread)
+{
+       smtp_thread_arg *smtp_arg;
+       int status;
+
+       smtp_arg = THREAD_ARG(thread);
+
+       status =
+           tcp_socket_state(thread->u.fd, thread, conf_data->smtp_server,
+                            htons(SMTP_PORT)
+                            , smtp_check_thread);
+
+       switch (status) {
+       case connect_error:
+               DBG("Error connecting SMTP server [%s:%d].",
+                   inet_ntop2(conf_data->smtp_server), SMTP_PORT);
+               free_smtp_all(smtp_arg);
+               break;
+
+       case connect_timeout:
+               DBG("Timeout writing data to SMTP server [%s:%d].",
+                   inet_ntop2(conf_data->smtp_server), SMTP_PORT);
+               free_smtp_all(smtp_arg);
+               break;
+
+       case connect_success:
+               /* Remote SMTP server is connected.
+                * Register the next step thread smtp_cmd_thread.
+                */
+               DBG("Remote SMTP server [%s:%d] connected.",
+                   inet_ntop2(conf_data->smtp_server), SMTP_PORT);
+               thread_add_write(thread->master, smtp_send_cmd_thread, smtp_arg,
+                                thread->u.fd, conf_data->smtp_connection_to);
+               break;
+       }
+
+       return 0;
+}
+
+static int
+smtp_connect_thread(thread * thread)
+{
+       smtp_thread_arg *smtp_arg;
+       enum connect_result status;
+       int fd;
+
+       smtp_arg = THREAD_ARG(thread);
+
+       /* Return if no smtp server is defined */
+       if (conf_data->smtp_server == 0) {
+               free_smtp_all(smtp_arg);
+               return 0;
+       }
+
+       if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+               DBG("SMTP connect fail to create socket.");
+               return 0;
+       }
+
+       status = tcp_connect(fd, conf_data->smtp_server, htons(SMTP_PORT));
+
+       switch (status) {
+       case connect_error:
+               DBG("SMTP connection ERROR to [%s:%d].",
+                   inet_ntop2(conf_data->smtp_server), SMTP_PORT);
+               free_smtp_all(smtp_arg);
+               close(fd);
+               return 0;
+               break;
+
+       case connect_timeout:
+               DBG("Timeout connecting SMTP server [%s:%d].",
+                   inet_ntop2(conf_data->smtp_server), SMTP_PORT);
+               free_smtp_all(smtp_arg);
+               close(fd);
+               return 0;
+               break;
+
+       case connect_success:
+               DBG("SMTP connection SUCCESS to [%s:%d].",
+                   inet_ntop2(conf_data->smtp_server), SMTP_PORT);
+               break;
+
+               /* Checking non-blocking connect, we wait until socket is writable */
+       case connect_in_progress:
+               DBG("SMTP connection to [%s:%d] now IN_PROGRESS.",
+                   inet_ntop2(conf_data->smtp_server), SMTP_PORT);
+               break;
+       }
+
+       /* connection have succeeded or still in progress */
+       thread_add_write(thread->master, smtp_check_thread, smtp_arg, fd,
+                        conf_data->smtp_connection_to);
+       return 1;
+}
+
+void
+smtp_alert(thread_master * master, real_server * rs, vrrp_rt * vrrp,
+          const char *subject, const char *body)
+{
+       smtp_thread_arg *smtp_arg;
+
+       /* Only send mail if email specified */
+       if (!LIST_ISEMPTY(conf_data->email)) {
+               /* allocate & initialize smtp argument data structure */
+               smtp_arg = (smtp_thread_arg *) MALLOC(sizeof (smtp_thread_arg));
+               smtp_arg->subject = (char *) MALLOC(MAX_HEADERS_LENGTH);
+               smtp_arg->body = (char *) MALLOC(MAX_BODY_LENGTH);
+               smtp_arg->buffer = (char *) MALLOC(SMTP_BUFFER_MAX);
+
+               smtp_arg->stage = CONNECTION;   /* first smtp command set to HELO */
+
+               /* format subject if rserver is specified */
+               if (rs)
+                       snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH,
+                                "[%s] Realserver %s:%d - %s",
+                                conf_data->lvs_id, inet_ntop2(SVR_IP(rs))
+                                , ntohs(SVR_PORT(rs))
+                                , subject);
+               else if (vrrp)
+                       snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH,
+                                "[%s] VRRP Instance %s - %s",
+                                conf_data->lvs_id, vrrp->iname, subject);
+               else if (conf_data->lvs_id)
+                       snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH,
+                                "[%s] %s", conf_data->lvs_id, subject);
+               else
+                       snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH, "%s",
+                                subject);
+
+               strncpy(smtp_arg->body, body, MAX_BODY_LENGTH);
+
+               thread_add_event(master, smtp_connect_thread, smtp_arg, 0);
+       }
+}
similarity index 57%
rename from timer.c
rename to keepalived/core/timer.c
index 3ed3b09..3e2b001 100644 (file)
--- a/timer.c
@@ -5,7 +5,7 @@
  * 
  * Part:        Timer manipulations.
  *  
- * Version:     $Id: timer.c,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: timer.c,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
 #include "timer.h"
 
 /* set a timer to a specific value */
-TIMEVAL timer_dup(TIMEVAL b)
+TIMEVAL
+timer_dup(TIMEVAL b)
 {
-  TIMEVAL a;
+       TIMEVAL a;
 
-  TIMER_RESET(a);
-  a.tv_sec  = b.tv_sec;
-  a.tv_usec = b.tv_usec;
-  return a;
+       TIMER_RESET(a);
+       a.tv_sec = b.tv_sec;
+       a.tv_usec = b.tv_usec;
+       return a;
 }
 
 /* timer compare */
-int timer_cmp(TIMEVAL a, TIMEVAL b)
+int
+timer_cmp(TIMEVAL a, TIMEVAL b)
 {
-  if (a.tv_sec > b.tv_sec)
-    return 1;
-  if (a.tv_sec < b.tv_sec)
-    return -1;
-  if (a.tv_usec > b.tv_usec)
-    return 1;
-  if (a.tv_usec < b.tv_usec)
-    return -1;
-  return 0;
+       if (a.tv_sec > b.tv_sec)
+               return 1;
+       if (a.tv_sec < b.tv_sec)
+               return -1;
+       if (a.tv_usec > b.tv_usec)
+               return 1;
+       if (a.tv_usec < b.tv_usec)
+               return -1;
+       return 0;
 }
 
 /* timer sub */
-TIMEVAL timer_sub(TIMEVAL a, TIMEVAL b)
+TIMEVAL
+timer_sub(TIMEVAL a, TIMEVAL b)
 {
-  TIMEVAL ret;
+       TIMEVAL ret;
 
-  TIMER_RESET(ret);
-  ret.tv_usec = a.tv_usec - b.tv_usec;
-  ret.tv_sec  = a.tv_sec - b.tv_sec;
+       TIMER_RESET(ret);
+       ret.tv_usec = a.tv_usec - b.tv_usec;
+       ret.tv_sec = a.tv_sec - b.tv_sec;
 
-  if (ret.tv_usec < 0) {
-    ret.tv_usec += TIMER_HZ;
-    ret.tv_sec--;
-  }
+       if (ret.tv_usec < 0) {
+               ret.tv_usec += TIMER_HZ;
+               ret.tv_sec--;
+       }
 
-  return ret;
+       return ret;
 }
 
 /* current time */
-TIMEVAL timer_now(void)
+TIMEVAL
+timer_now(void)
 {
-  TIMEVAL timer_now;
+       TIMEVAL timer_now;
 
-  /* init timer */
-  TIMER_RESET(timer_now);
-  gettimeofday(&timer_now, NULL);
+       /* init timer */
+       TIMER_RESET(timer_now);
+       gettimeofday(&timer_now, NULL);
 
-  return timer_now;
+       return timer_now;
 }
 
 /* timer sub from current time */
-TIMEVAL timer_sub_now(TIMEVAL a)
+TIMEVAL
+timer_sub_now(TIMEVAL a)
 {
-  return timer_sub(timer_now(), a);
+       return timer_sub(timer_now(), a);
 }
diff --git a/keepalived/core/utils.c b/keepalived/core/utils.c
new file mode 100644 (file)
index 0000000..9c8a812
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * 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:        General program utils.
+ *
+ * Version:     $Id: utils.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "utils.h"
+
+/* Display a buffer into a HEXA formated output */
+void
+print_buffer(int count, char *buff)
+{
+       int i, j, c;
+       int printnext = 1;
+
+       if (count % 16)
+               c = count + (16 - count % 16);
+       else
+               c = count;
+
+       for (i = 0; i < c; i++) {
+               if (printnext) {
+                       printnext--;
+                       printf("%.4x ", i & 0xffff);
+               }
+               if (i < count)
+                       printf("%3.2x", buff[i] & 0xff);
+               else
+                       printf("   ");
+               if (!((i + 1) % 8)) {
+                       if ((i + 1) % 16)
+                               printf(" -");
+                       else {
+                               printf("   ");
+                               for (j = i - 15; j <= i; j++)
+                                       if (j < count) {
+                                               if ((buff[j] & 0xff) >= 0x20
+                                                   && (buff[j] & 0xff) <= 0x7e)
+                                                       printf("%c",
+                                                              buff[j] & 0xff);
+                                               else
+                                                       printf(".");
+                                       } else
+                                               printf(" ");
+                               printf("\n");
+                               printnext = 1;
+                       }
+               }
+       }
+}
+
+/* IP network to ascii representation */
+char *
+inet_ntop2(uint32_t ip)
+{
+       static char buf[16];
+       unsigned char *bytep;
+
+       bytep = (unsigned char *) &(ip);
+       sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]);
+       return buf;
+}
+
+/*
+ * IP network to ascii representation. To use
+ * for multiple IP address convertion into the same call.
+ */
+char *
+inet_ntoa2(uint32_t ip, char *buf)
+{
+       unsigned char *bytep;
+
+       bytep = (unsigned char *) &(ip);
+       sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]);
+       return buf;
+}
+
+/* IP string to network mask representation */
+uint8_t
+inet_stom(char *addr)
+{
+       uint8_t mask = 32;
+       char *cp = addr;
+
+       if (!strstr(addr, "/"))
+               return mask;
+       while (*cp != '/' && *cp != '\0')
+               cp++;
+       if (*cp == '/')
+               return atoi(++cp);
+       return mask;
+}
+
+/*
+ * IP string to network representation
+ * Highly inspired from Paul Vixie code.
+ */
+int
+inet_ston(const char *addr, uint32_t * dst)
+{
+       static char digits[] = "0123456789";
+       int saw_digit, octets, ch;
+       u_char tmp[INADDRSZ], *tp;
+
+       saw_digit = 0;
+       octets = 0;
+       *(tp = tmp) = 0;
+
+       while ((ch = *addr++) != '\0' && ch != '/') {
+               const char *pch;
+               if ((pch = strchr(digits, ch)) != NULL) {
+                       u_int new = *tp * 10 + (pch - digits);
+                       if (new > 255)
+                               return 0;
+                       *tp = new;
+                       if (!saw_digit) {
+                               if (++octets > 4)
+                                       return 0;
+                               saw_digit = 1;
+                       }
+               } else if (ch == '.' && saw_digit) {
+                       if (octets == 4)
+                               return 0;
+                       *++tp = 0;
+                       saw_digit = 0;
+               } else
+                       return 0;
+       }
+
+       if (octets < 4)
+               return 0;
+
+       memcpy(dst, tmp, INADDRSZ);
+       return 1;
+}
similarity index 51%
rename from vector.c
rename to keepalived/core/vector.c
index c012e82..677d02a 100644 (file)
--- a/vector.c
@@ -5,7 +5,7 @@
  * 
  * Part:        Vector structure manipulation.
  *  
- * Version:     $Id: vector.c,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: vector.c,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
  * Initialize vector struct.
  * allocalted 'size' slot elements then return vector.
  */
-vector vector_alloc(void)
+vector
+vector_alloc(void)
 {
-  vector v = (vector)MALLOC(sizeof(struct _vector));
-  return v;
+       vector v = (vector) MALLOC(sizeof (struct _vector));
+       return v;
 }
 
 /* allocated one slot */
-void vector_alloc_slot(vector v)
+void
+vector_alloc_slot(vector v)
 {
-  v->allocated += VECTOR_DEFAULT_SIZE;
-  if (v->slot)
-    v->slot = REALLOC(v->slot, sizeof(void *) * v->allocated);
-  else
-    v->slot = (void *)MALLOC(sizeof(void *) * v->allocated);
+       v->allocated += VECTOR_DEFAULT_SIZE;
+       if (v->slot)
+               v->slot = REALLOC(v->slot, sizeof (void *) * v->allocated);
+       else
+               v->slot = (void *) MALLOC(sizeof (void *) * v->allocated);
 }
 
 /* Free memory vector allocation */
-void vector_free(vector v)
+void
+vector_free(vector v)
 {
-  FREE(v->slot);
-  FREE(v);
+       FREE(v->slot);
+       FREE(v);
 }
-void free_strvec(vector strvec)
+
+void
+free_strvec(vector strvec)
 {
-  int i;
-  char *str;
+       int i;
+       char *str;
 
-  if (!strvec)
-    return;
+       if (!strvec)
+               return;
 
-  for (i=0; i < VECTOR_SIZE(strvec); i++)
-    if ((str = VECTOR_SLOT(strvec, i)) != NULL)
-      FREE(str);
+       for (i = 0; i < VECTOR_SIZE(strvec); i++)
+               if ((str = VECTOR_SLOT(strvec, i)) != NULL)
+                       FREE(str);
 
-  vector_free(strvec);
+       vector_free(strvec);
 }
 
 /* Set a vector slot value */
-void vector_set_slot(vector v, void *value)
+void
+vector_set_slot(vector v, void *value)
 {
-  unsigned int i = v->allocated-1;
+       unsigned int i = v->allocated - 1;
 
-  v->slot[i] = value;
+       v->slot[i] = value;
 }
 
 /* dump vector slots */
-void vector_dump(vector v)
+void
+vector_dump(vector v)
 {
-  int i;
+       int i;
 
-  printf("Vector Size : %d\n", v->allocated);
+       printf("Vector Size : %d\n", v->allocated);
 
-  for (i = 0; i < v->allocated; i++)
-    if (v->slot[i] != NULL)
-      printf("  Slot [%d]: %p\n", i, VECTOR_SLOT(v, i));
+       for (i = 0; i < v->allocated; i++)
+               if (v->slot[i] != NULL)
+                       printf("  Slot [%d]: %p\n", i, VECTOR_SLOT(v, i));
 }
 
-void dump_strvec(vector strvec)
+void
+dump_strvec(vector strvec)
 {
-  int i;
-  char *str;
+       int i;
+       char *str;
 
-  if (!strvec)
-    return;
+       if (!strvec)
+               return;
 
-  printf("String Vector : ");
+       printf("String Vector : ");
 
-  for (i = 0; i < VECTOR_SIZE(strvec); i++) {
-    str = VECTOR_SLOT(strvec, i);
-    printf("[%i]=%s ", i, str);
-  }
-  printf("\n");
+       for (i = 0; i < VECTOR_SIZE(strvec); i++) {
+               str = VECTOR_SLOT(strvec, i);
+               printf("[%i]=%s ", i, str);
+       }
+       printf("\n");
 }
similarity index 95%
rename from etc/init.d/keepalived.init
rename to keepalived/etc/init.d/keepalived.init
index 2e321f8..8a0431a 100755 (executable)
@@ -5,7 +5,7 @@
 # processname: keepalived
 # pidfile: /var/run/keepalived.pid
 # config: /etc/keepalived/keepalived.conf
-# chkconfig: 2345 92 40
+# chkconfig: 2345 92 08
 # description: Start and stop Keepalived
 
 # Global definitions
similarity index 94%
rename from etc/keepalived/keepalived.conf
rename to keepalived/etc/keepalived/keepalived.conf
index c016d36..72f0000 100644 (file)
@@ -1,4 +1,4 @@
-# Configuration File for keepalived
+! Configuration File for keepalived
 
 global_defs {
    notification_email {
@@ -12,13 +12,6 @@ global_defs {
    lvs_id LVS_DEVEL
 }
 
-!SSL {
-!  password password
-!  ca /etc/keepalived/root.pem
-!  certificate /etc/keepalived/dh1024.pem
-!  key /etc/keepalived/client.pem
-!}
-
 vrrp_instance VI_1 {
     state MASTER
     interface eth0
@@ -26,7 +19,7 @@ vrrp_instance VI_1 {
     priority 100
     advert_int 1
     authentication {
-        auth_type AH
+        auth_type PASS
         auth_pass 1111
     }
     virtual_ipaddress {
diff --git a/keepalived/healthcheck/Makefile.in b/keepalived/healthcheck/Makefile.in
new file mode 100644 (file)
index 0000000..c3c6017
--- /dev/null
@@ -0,0 +1,39 @@
+# Makefile
+#
+# Keepalived OpenSource project.
+#
+# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
+
+KERNEL   = @KERN@
+CC      = @CC@
+CI_LINUX = @CI_LINUX@
+ifeq ($(CI_LINUX),_WITH_CI_LINUX_)
+CI_LINUX_OBJ = check_ci.o
+CIFLAGS = -D$(CI_LINUX)
+endif
+INCLUDES = -I../include
+CFLAGS  = @CFLAGS@ $(INCLUDES) \
+          -Wall -Wunused -Wstrict-prototypes
+DEFS    = -D$(KERNEL) -D@IPVS_SUPPORT@ -D@IPVS_SYNCD@ @DFLAGS@ $(CIFLAGS)
+COMPILE         = $(CC) $(CFLAGS) $(DEFS)
+
+OBJS =         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
diff --git a/keepalived/healthcheck/check_api.c b/keepalived/healthcheck/check_api.c
new file mode 100644 (file)
index 0000000..9316cd9
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * 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:        Checkers registration.
+ *
+ * Version:     $Id: check_api.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "check_api.h"
+#include "parser.h"
+#include "memory.h"
+#include "utils.h"
+#include "check_misc.h"
+#include "check_tcp.h"
+#include "check_http.h"
+#include "check_ssl.h"
+#ifdef _WITH_CI_LINUX_
+#include "check_ci.h"
+#endif
+
+extern thread_master *master;
+extern data *conf_data;
+
+/* free checker data */
+static void
+free_checker(void *data)
+{
+       checker *checker = data;
+       (*checker->free) (checker);
+}
+
+/* dump checker data */
+static void
+dump_checker(void *data)
+{
+       checker *checker = data;
+       syslog(LOG_INFO, " %s:%d", inet_ntop2(CHECKER_RIP(checker))
+              , ntohs(CHECKER_RPORT(checker)));
+       (*checker->dump) (checker);
+}
+
+/* init the global checkers queue */
+void
+init_checkers_queue(void)
+{
+       checkers_queue = alloc_list(free_checker, dump_checker);
+}
+
+/* Queue a checker to the checkers_queue */
+void
+queue_checker(void (*free) (void *), void (*dump) (void *)
+             , int (*launch) (struct _thread *)
+             , void *data)
+{
+       virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+       real_server *rs = LIST_TAIL_DATA(vs->rs);
+       checker *chk = (checker *) MALLOC(sizeof (checker));
+
+       chk->free = free;
+       chk->dump = dump;
+       chk->launch = launch;
+       chk->vs = vs;
+       chk->rs = rs;
+       chk->data = data;
+       chk->enabled = (vs->vfwmark) ? 1 : 0;
+
+       /* queue the checker */
+       list_add(checkers_queue, chk);
+}
+
+/* dump the checkers_queue */
+void
+dump_checkers_queue(void)
+{
+       if (!LIST_ISEMPTY(checkers_queue)) {
+               syslog(LOG_INFO, "------< Health checkers >------");
+               dump_list(checkers_queue);
+       }
+}
+
+/* release the checkers_queue */
+void
+free_checkers_queue(void)
+{
+       free_list(checkers_queue);
+}
+
+/* register the checker to the global I/O scheduler */
+void
+register_checkers_thread(void)
+{
+       checker *checker;
+       element e;
+
+       for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) {
+               checker = ELEMENT_DATA(e);
+               thread_add_timer(master, checker->launch, checker,
+                                BOOTSTRAP_DELAY);
+       }
+}
+
+/* Sync checkers activity with netlink kernel reflection */
+void
+update_checker_activity(uint32_t address, int enable)
+{
+       checker *checker;
+       element e;
+
+       /* Processing Healthcheckers queue */
+       if (!LIST_ISEMPTY(checkers_queue))
+               for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) {
+                       checker = ELEMENT_DATA(e);
+                       if (CHECKER_VIP(checker) == address) {
+                               if (!CHECKER_ENABLED(checker) && enable) {
+                                       syslog(LOG_INFO,
+                                              "Netlink reflector reports IP %s added",
+                                              inet_ntop2(address));
+                                       syslog(LOG_INFO,
+                                              "Activating healtchecker for VIP %s",
+                                              inet_ntop2(address));
+                               }
+                               if (CHECKER_ENABLED(checker) && !enable) {
+                                       syslog(LOG_INFO,
+                                              "Netlink reflector reports IP %s removed",
+                                              inet_ntop2(address));
+                                       syslog(LOG_INFO,
+                                              "Suspending healtchecker for VIP %s",
+                                              inet_ntop2(address));
+                               }
+                               checker->enabled = enable;
+                       }
+               }
+}
+
+/* Install checkers keywords */
+void
+install_checkers_keyword(void)
+{
+       install_misc_check_keyword();
+       install_tcp_check_keyword();
+       install_http_check_keyword();
+       install_ssl_check_keyword();
+#ifdef _WITH_CI_LINUX_
+       install_ci_check_keyword();
+#endif
+}
diff --git a/keepalived/healthcheck/check_ci.c b/keepalived/healthcheck/check_ci.c
new file mode 100644 (file)
index 0000000..63544a3
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * 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:        CI-LINUX checker. Integration to Compaq Cluster Infrastructure.
+ *
+ * Version:     $Id: check_ci.c,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Aneesh Kumar K.V, <aneesh.kumar@digital.com>
+ *
+ *              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.
+ */
+
+#include "check_ci.h"
+#include "check_api.h"
+#include "memory.h"
+#include "parser.h"
+#include "smtp.h"
+#include "ipwrapper.h"
+
+/* CI nodemap declaration */
+static nodenum_ip_map_t *nodemap;
+
+/* Configuration stream handling */
+void
+free_ci_check(void *data)
+{
+       if (nodemap) {
+               FREE(nodemap);
+               nodemap = NULL;
+       }
+}
+void
+dump_ci_check(void *data)
+{
+       syslog(LOG_INFO, "   Keepalive method = CI-LINUX");
+}
+
+void
+ci_get_handler(vector strvec)
+{
+       int size = sizeof (nodenum_ip_map_t) * cluster_maxnodes() + 1;
+       nodemap = (nodenum_ip_map_t *) ALLOC(size);
+
+       /*
+        * If we can not initialize node map we don t queue a new checker.
+        * The default action if so is:
+        *   The realserver activity will not be monitored by the CI-LINUX
+        *   Healchecker. This mean that this realserver will be present into
+        *   LVS topology even if it is failing.
+        */
+       if (initialize_nodemap(nodemap) < 0) {
+               syslog(LOG_ERR,
+                      "[CI-LINUX] Failed to initialize the node map from %s",
+                      CLUSTERTAB);
+       } else
+               queue_checker(free_ci_check, dump_ci_check, ci_check_thread,
+                             NULL);
+}
+
+void
+install_ci_check_keyword(void)
+{
+       install_keyword("CI-LINUX", &ci_get_handler);
+}
+
+int
+initialize_nodemap(nodenum_ip_map_t * nodemap)
+{
+       FILE *fp;
+       char buf[BUFFSIZE];
+       int node_number;
+
+       if ((fp = fopen(CLUSTERTAB, "r")) == NULL)
+               return -1;
+
+       while (fscanf(fp, "%s", buf) != EOF) {
+               if (buf[0] == '#') {
+                       if (fscanf(fp, "%[^\n]", buf) == EOF) {
+                               syslog(LOG_ERR,
+                                      "[CI-LINUX] %s File Format Error",
+                                      CLUSTERTAB);
+                               return -1;
+                       }
+                       bzero(buf, BUFFSIZE);
+                       continue;
+               }
+               node_number = atoi(buf);
+               if (node_number > cluster_maxnodes()) {
+                       syslog(LOG_ERR,
+                              "[CI-LINUX] Node number greater than MAX node num\n");
+                       return -1;
+               }
+               if (fscanf(fp, "%s", buf) == EOF) {
+                       syslog(LOG_ERR, "[CI-LINUX] %s File Format Error",
+                              CLUSTERTAB);
+                       return -1;
+               }
+               inet_ston(buf, &nodemap[node_number].addr_ip);
+               if (fscanf(fp, "%[^\n]", buf) == EOF) {
+                       syslog(LOG_ERR, "[CI-LINUX] %s File Format Error",
+                              CLUSTERTAB);
+                       return -1;
+               }
+               bzero(buf, BUFFSIZE);
+       }
+       return 1;
+}
+
+clusternode_t
+address_to_nodenum(uint32_t addr_ip)
+{
+       int i;
+       int max_nodes = cluster_maxnodes();
+
+       for (i = 1; i <= max_nodes; i++) {
+               if (nodemap[i].addr_ip == addr_ip)
+                       return i;
+       }
+       return 0;               /* Not a valid node */
+}
+
+int
+nodestatus(uint32_t addr_ip)
+{
+       int node_num;
+       clusternode_info_t ni;
+
+       if ((node_num = address_to_nodenum(addr_ip)) == 0)
+               return UNKNOWN_NODE;
+
+       if (clusternode_info(node_num, sizeof (ni), &ni) >= 0)
+               /*
+                * I am insterested only in two state
+                * either fully up or down.
+                */
+               return (ni.node_state == CLUSTERNODE_UP) ? UP : DOWN;
+       else
+               syslog(LOG_ERR,
+                      "[CI-LINUX] Error in getting the cluster information");
+
+       return UNKNOWN_NODE;
+}
+
+/* Cluster Infrastructure checker thread */
+int
+ci_check_thread(thread * thread)
+{
+       checker *checker = THREAD_ARG(thread);
+       int status;
+
+       /*
+        * Register a new checker thread & return
+        * if checker is disabled
+        */
+       if (!CHECKER_ENABLED(checker)) {
+               thread_add_timer(thread->master, ci_check_thread, checker,
+                                checker->vs->delay_loop);
+               return 0;
+       }
+
+       /* Check the CI node status */
+       status = nodestatus(CHECKER_RIP(checker));
+
+       switch (status) {
+       case UP:
+               if (!ISALIVE(checker->rs)) {
+                       smtp_alert(thread->master, checker->rs, NULL, "UP",
+                                  "=> CI-Linux  CHECK succeed on service <=\n\n");
+                       perform_svr_state(UP, checker->vs, checker->rs);
+               }
+               break;
+       case DOWN:
+               if (ISALIVE(checker->rs)) {
+                       smtp_alert(thread->master, checker->rs, NULL, "DOWN",
+                                  "=> CI-Linux CHECK failed on service <=\n\n");
+                       perform_svr_state(DOWN, checker->vs, checker->rs);
+               }
+               break;
+       default:
+               syslog(LOG_ERR, "[CI-LINUX] Unknown node status");
+       }
+
+       /* Register the next check */
+       thread_add_timer(thread->master, ci_check_thread, checker,
+                        checker->vs->delay_loop);
+       return 0;
+}
diff --git a/keepalived/healthcheck/check_http.c b/keepalived/healthcheck/check_http.c
new file mode 100644 (file)
index 0000000..1507c52
--- /dev/null
@@ -0,0 +1,738 @@
+/*
+ * 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:        WEB CHECK. Common HTTP/SSL checker primitives.
+ *
+ * Version:     $Id: check_http.c,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.net>
+ *
+ *              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.
+ */
+
+#include <openssl/err.h>
+#include "check_http.h"
+#include "check_ssl.h"
+#include "check_api.h"
+#include "memory.h"
+#include "parser.h"
+#include "utils.h"
+
+int http_connect_thread(thread *);
+
+/* Configuration stream handling */
+void
+free_url(void *data)
+{
+       url *url = data;
+       FREE(url->path);
+       FREE(url->digest);
+       FREE(url);
+}
+
+void
+dump_url(void *data)
+{
+       url *url = data;
+       syslog(LOG_INFO, "   Checked url = %s, digest = %s", url->path,
+              url->digest);
+}
+
+void
+free_http_get_check(void *data)
+{
+       http_get_checker *http_get_chk = CHECKER_DATA(data);
+
+       free_list(http_get_chk->url);
+       FREE(http_get_chk->arg);
+       FREE(http_get_chk);
+       FREE(data);
+}
+
+void
+dump_http_get_check(void *data)
+{
+       http_get_checker *http_get_chk = CHECKER_DATA(data);
+
+       if (http_get_chk->proto == PROTO_HTTP)
+               syslog(LOG_INFO, "   Keepalive method = HTTP_GET");
+       else
+               syslog(LOG_INFO, "   Keepalive method = SSL_GET");
+       if (http_get_chk->connection_port)
+               syslog(LOG_INFO, "   Connection port = %d",
+                      ntohs(http_get_chk->connection_port));
+       syslog(LOG_INFO, "   Connection timeout = %d",
+              http_get_chk->connection_to);
+       syslog(LOG_INFO, "   Nb get retry = %d", http_get_chk->nb_get_retry);
+       syslog(LOG_INFO, "   Delay before retry = %d",
+              http_get_chk->delay_before_retry);
+       dump_list(http_get_chk->url);
+}
+static http_get_checker *
+alloc_http_get(char *proto)
+{
+       http_get_checker *http_get_chk;
+
+       http_get_chk = (http_get_checker *) MALLOC(sizeof (http_get_checker));
+       http_get_chk->arg = (http_arg *) MALLOC(sizeof (http_arg));
+       http_get_chk->proto =
+           (!strcmp(proto, "HTTP_GET")) ? PROTO_HTTP : PROTO_SSL;
+       http_get_chk->url = alloc_list(free_url, dump_url);
+
+       return http_get_chk;
+}
+
+void
+http_get_handler(vector strvec)
+{
+       http_get_checker *http_get_chk;
+       char *str = VECTOR_SLOT(strvec, 0);
+
+       /* queue new checker */
+       http_get_chk = alloc_http_get(str);
+       queue_checker(free_http_get_check, dump_http_get_check,
+                     http_connect_thread, http_get_chk);
+}
+
+void
+connect_p_handler(vector strvec)
+{
+       http_get_checker *http_get_chk = CHECKER_GET();
+       http_get_chk->connection_port = htons(CHECKER_VALUE_INT(strvec));
+}
+
+void
+connect_to_handler(vector strvec)
+{
+       http_get_checker *http_get_chk = CHECKER_GET();
+       http_get_chk->connection_to = CHECKER_VALUE_INT(strvec);
+}
+
+void
+nb_get_retry_handler(vector strvec)
+{
+       http_get_checker *http_get_chk = CHECKER_GET();
+       http_get_chk->nb_get_retry = CHECKER_VALUE_INT(strvec);
+}
+
+void
+delay_before_retry_handler(vector strvec)
+{
+       http_get_checker *http_get_chk = CHECKER_GET();
+       http_get_chk->delay_before_retry = CHECKER_VALUE_INT(strvec);
+}
+
+void
+url_handler(vector strvec)
+{
+       http_get_checker *http_get_chk = CHECKER_GET();
+       url *new;
+
+       /* allocate the new URL */
+       new = (url *) MALLOC(sizeof (url));
+
+       list_add(http_get_chk->url, new);
+}
+
+void
+path_handler(vector strvec)
+{
+       http_get_checker *http_get_chk = CHECKER_GET();
+       url *url = LIST_TAIL_DATA(http_get_chk->url);
+
+       url->path = CHECKER_VALUE_STRING(strvec);
+}
+
+void
+digest_handler(vector strvec)
+{
+       http_get_checker *http_get_chk = CHECKER_GET();
+       url *url = LIST_TAIL_DATA(http_get_chk->url);
+
+       url->digest = CHECKER_VALUE_STRING(strvec);
+}
+
+void
+install_http_check_keyword(void)
+{
+       install_keyword("HTTP_GET", &http_get_handler);
+       install_sublevel();
+       install_keyword("connect_port", &connect_p_handler);
+       install_keyword("connect_timeout", &connect_to_handler);
+       install_keyword("nb_get_retry", &nb_get_retry_handler);
+       install_keyword("delay_before_retry", &delay_before_retry_handler);
+       install_keyword("url", &url_handler);
+       install_sublevel();
+       install_keyword("path", &path_handler);
+       install_keyword("digest", &digest_handler);
+       install_sublevel_end();
+       install_sublevel_end();
+}
+
+/* a little code duplication :/ */
+void
+install_ssl_check_keyword(void)
+{
+       install_keyword("SSL_GET", &http_get_handler);
+       install_sublevel();
+       install_keyword("connect_port", &connect_p_handler);
+       install_keyword("connect_timeout", &connect_to_handler);
+       install_keyword("nb_get_retry", &nb_get_retry_handler);
+       install_keyword("delay_before_retry", &delay_before_retry_handler);
+       install_keyword("url", &url_handler);
+       install_sublevel();
+       install_keyword("path", &path_handler);
+       install_keyword("digest", &digest_handler);
+       install_sublevel_end();
+       install_sublevel_end();
+}
+
+/* 
+ * The global design of this checker is the following :
+ * 
+ * - All the actions are done asynchronously.
+ * - All the actions handle timeout connection.
+ * - All the actions handle error from low layer to upper
+ *   layers.
+ * 
+ * The global synopsis of the inter-thread-call is :
+ *     
+ *     http_connect_thread (handle layer4 connect)
+ *            v
+ *     http_check_thread (handle SSL connect)
+ *            v
+ *     http_request_thread (send SSL GET request)
+ *            v
+ *     http_response_thread (initialize read stream step)
+ *         /             \
+ *        /               \
+ *       v                 v
+ *  http_read_thread   ssl_read_thread (perform HTTP|SSL stream)
+ *       v              v
+ *     http_handle_response (next checker thread registration)
+ */
+
+uint16_t
+get_service_port(checker * checker)
+{
+       http_get_checker *http_get_check = CHECKER_ARG(checker);
+       uint16_t addr_port;
+
+       /*
+        *  Set the remote connection port.
+        *  If a specific checker port is specified, we used this.
+        *  If we are balancing all services (host rather than service),
+        *  then assume we want to use default ports for HTTP or HTTPS.
+        *  Known as 'Layer3 stickyness'.
+        */
+       addr_port = CHECKER_RPORT(checker);
+       if (!addr_port)
+               addr_port =
+                   htons((http_get_check->proto == PROTO_SSL) ? 443 : 80);
+       if (http_get_check->connection_port)
+               addr_port = http_get_check->connection_port;
+       return addr_port;
+}
+
+/*
+ * Simple epilog functions. Handling event timeout.
+ * Finish the checker with memory managment or url rety check.
+ *
+ * c == 0 => reset to 0 retry_it counter
+ * t == 0 => reset to 0 url_it counter
+ * method == 1 => register a new checker thread
+ * method == 2 => register a retry on url checker thread
+ */
+int
+epilog(thread * thread, int method, int t, int c)
+{
+       checker *checker = THREAD_ARG(thread);
+       http_get_checker *http_get_check = CHECKER_ARG(checker);
+       http_arg *http_arg = HTTP_ARG(http_get_check);
+       REQ *req = HTTP_REQ(http_arg);
+       int delay = 0;
+
+       if (method) {
+               http_arg->url_it += t ? t : -http_arg->url_it;
+               http_arg->retry_it += c ? c : -http_arg->retry_it;
+       }
+
+       /* register next timer thread */
+       switch (method) {
+       case 1:
+               if (req)
+                       delay = checker->vs->delay_loop;
+               else
+                       delay =
+                           checker->vs->delay_loop -
+                           http_get_check->delay_before_retry;
+               break;
+       case 2:
+               delay = http_get_check->delay_before_retry;
+               break;
+       }
+
+       /* If req == NULL, fd is not created */
+       if (req) {
+               if (req->ssl)
+                       SSL_free(req->ssl);
+               if (req->buffer)
+                       FREE(req->buffer);
+               FREE(req);
+               close(thread->u.fd);
+       }
+
+       /* Register next checker thread */
+       thread_add_timer(thread->master, http_connect_thread, checker, delay);
+       return 0;
+}
+
+int
+timeout_epilog(thread * thread, char *smtp_msg, char *debug_msg)
+{
+       checker *checker = THREAD_ARG(thread);
+       http_get_checker *http_get_check = CHECKER_ARG(checker);
+       http_arg *http_arg = HTTP_ARG(http_get_check);
+#ifdef _DEBUG_
+       uint16_t addr_port = get_service_port(checker);
+#endif
+
+       /*
+        * The get retry implementation mean that we retry performing
+        * a GET on the same url until the remote web server return 
+        * html buffer. This is sometime needed with some applications
+        * servers.
+        */
+       if (++http_arg->retry_it <= http_get_check->nb_get_retry) {
+               DBG("Retry %s server [%s:%d] after %d retry.",
+                   debug_msg, inet_ntop2(CHECKER_RIP(checker)),
+                   ntohs(addr_port), http_arg->retry_it - 1);
+               return epilog(thread, 2, 0, 1);
+
+       } else {
+               if (checker->rs)
+                       DBG("Timeout %s server [%s:%d].",
+                           debug_msg, inet_ntop2(CHECKER_RIP(checker)),
+                           ntohs(addr_port));
+               /* check if server is currently alive */
+               if (ISALIVE(checker->rs)) {
+                       smtp_alert(thread->master, checker->rs, NULL, "DOWN",
+                                  smtp_msg);
+                       perform_svr_state(DOWN, checker->vs, checker->rs);
+               }
+
+               return epilog(thread, 1, 0, 0);
+       }
+
+       return 0;
+}
+
+/* HTML stream parser primitives */
+/* simple function returning a pointer to the html buffer begin */
+char *
+extract_html(char *buffer, int size_buffer)
+{
+       char *end = buffer + size_buffer;
+
+       while (buffer < end &&
+              !(*buffer++ == '\n' &&
+                (*buffer == '\n' || (*buffer++ == '\r' && *buffer == '\n')))) ;
+
+       if (*buffer == '\n')
+               return buffer + 1;
+       return NULL;
+}
+
+/* return the url pointer of the current url iterator  */
+url *
+fetch_next_url(http_get_checker * http_get_check)
+{
+       http_arg *http_arg = HTTP_ARG(http_get_check);
+
+       return list_element(http_get_check->url, http_arg->url_it);
+}
+
+/* Handle response */
+int
+http_handle_response(thread * thread, unsigned char digest[16]
+                    , int empty_buffer)
+{
+       checker *checker = THREAD_ARG(thread);
+       http_get_checker *http_get_check = CHECKER_ARG(checker);
+#ifdef _DEBUG_
+       uint16_t addr_port = get_service_port(checker);
+       http_arg *http_arg = HTTP_ARG(http_get_check);
+#endif
+       int r, di = 0;
+       unsigned char *digest_tmp;
+       url *fetched_url;
+
+       if (empty_buffer) {
+               return timeout_epilog(thread, "=> CHECK failed on service"
+                                     " : empty buffer received <=\n\n",
+                                     "Read, no data received from ");
+       } else {
+               /* Compute MD5SUM */
+               digest_tmp = (char *) MALLOC(MD5_BUFFER_LENGTH + 1);
+               for (di = 0; di < 16; di++)
+                       sprintf(digest_tmp + 2 * di, "%02x", digest[di]);
+
+               fetched_url = fetch_next_url(http_get_check);
+
+               DBG("MD5SUM to [%s:%d] url(%d) = [%s].",
+                   inet_ntop2(CHECKER_RIP(checker)), ntohs(addr_port),
+                   http_arg->url_it + 1, digest_tmp);
+
+               r = strcmp(fetched_url->digest, digest_tmp);
+               FREE(digest_tmp);
+
+               if (r) {
+                       DBG("MD5 digest error to [%s:%d] url(%d)"
+                           ", expecting MD5SUM [%s].",
+                           inet_ntop2(CHECKER_RIP(checker)),
+                           ntohs(addr_port), http_arg->url_it + 1,
+                           fetched_url->digest);
+
+                       /* check if server is currently alive */
+                       if (ISALIVE(checker->rs)) {
+                               smtp_alert(thread->master, checker->rs, NULL,
+                                          "DOWN",
+                                          "=> CHECK failed on service"
+                                          " : MD5 digest mismatch <=\n\n");
+                               perform_svr_state(DOWN, checker->vs,
+                                                 checker->rs);
+                       }
+                       return epilog(thread, 1, 0, 0);
+               } else {
+                       DBG("MD5 digest success to [%s:%d] url(%d).",
+                           inet_ntop2(CHECKER_RIP(checker)), ntohs(addr_port),
+                           http_arg->url_it + 1);
+                       return epilog(thread, 1, 1, 0) + 1;
+               }
+       }
+       return epilog(thread, 0, 0, 0) + 1;
+}
+
+/* Asynchronous HTTP stream reader */
+int
+http_read_thread(thread * thread)
+{
+       checker *checker = THREAD_ARG(thread);
+       http_get_checker *http_get_check = CHECKER_ARG(checker);
+       http_arg *http_arg = HTTP_ARG(http_get_check);
+       REQ *req = HTTP_REQ(http_arg);
+#ifdef _DEBUG_
+       uint16_t addr_port = get_service_port(checker);
+#endif
+       unsigned char digest[16];
+       int r = 0;
+
+       /* Handle read timeout */
+       if (thread->type == THREAD_READ_TIMEOUT)
+               return timeout_epilog(thread, "=> HTTP CHECK failed on service"
+                                     " : recevice data <=\n\n", "HTTP read");
+
+       /* read the HTTP stream */
+       r = read(thread->u.fd, req->buffer + req->len,
+                MAX_BUFFER_LENGTH - req->len);
+
+       if (r == -1 || r == 0) {        /* -1:error , 0:EOF */
+
+               /* All the HTTP stream has been parsed */
+               MD5_Final(digest, &req->context);
+
+               if (r == -1) {
+                       /* We have encourred a real read error */
+                       DBG("Read error with server [%s:%d]: %s",
+                           inet_ntop2(CHECKER_RIP(checker)), ntohs(addr_port),
+                           strerror(errno));
+                       if (ISALIVE(checker->rs)) {
+                               smtp_alert(thread->master, checker->rs, NULL,
+                                          "DOWN",
+                                          "=> HTTP CHECK failed on service"
+                                          " : cannot receive data <=\n\n");
+                               perform_svr_state(DOWN, checker->vs,
+                                                 checker->rs);
+                       }
+                       return epilog(thread, 1, 0, 0);
+               }
+
+               /* Handle response stream */
+               http_handle_response(thread, digest, (!req->extracted) ? 1 : 0);
+
+       } else {
+
+               req->len += r;
+               if (!req->extracted) {
+                       if ((req->extracted =
+                            extract_html(req->buffer, req->len))) {
+                               r = req->len - (req->extracted - req->buffer);
+                               if (r) {
+                                       memcpy(req->buffer, req->extracted, r);
+                                       MD5_Update(&req->context, req->buffer,
+                                                  r);
+                                       r = 0;
+                               }
+                               req->len = r;
+                       } else {
+                               /* minimize buffer using no 2*CR/LF found yet */
+                               if (req->len > 3) {
+                                       memcpy(req->buffer,
+                                              req->buffer + req->len - 3, 3);
+                                       req->len = 3;
+                               }
+                       }
+               } else {
+                       if (req->len) {
+                               MD5_Update(&req->context, req->buffer,
+                                          req->len);
+                               req->len = 0;
+                       }
+               }
+
+               /*
+                * Register next http stream reader.
+                * Register itself to not perturbe global I/O multiplexer.
+                */
+               thread_add_read(thread->master, http_read_thread, checker,
+                               thread->u.fd, http_get_check->connection_to);
+       }
+
+       return 0;
+}
+
+/*
+ * Read get result from the remote web server.
+ * Apply trigger check to this result.
+ */
+int
+http_response_thread(thread * thread)
+{
+       checker *checker = THREAD_ARG(thread);
+       http_get_checker *http_get_check = CHECKER_ARG(checker);
+       http_arg *http_arg = HTTP_ARG(http_get_check);
+       REQ *req = HTTP_REQ(http_arg);
+
+       /* Handle read timeout */
+       if (thread->type == THREAD_READ_TIMEOUT)
+               return timeout_epilog(thread, "=> CHECK failed on service"
+                                     " : recevice data <=\n\n", "WEB read");
+
+       /* Allocate & clean the get buffer */
+       req->buffer = (char *) MALLOC(MAX_BUFFER_LENGTH);
+       req->extracted = NULL;
+       req->len = 0;
+       req->error = 0;
+       MD5_Init(&req->context);
+
+       /* Register asynchronous http/ssl read thread */
+       if (http_get_check->proto == PROTO_SSL)
+               thread_add_read(thread->master, ssl_read_thread, checker,
+                               thread->u.fd, http_get_check->connection_to);
+       else
+               thread_add_read(thread->master, http_read_thread, checker,
+                               thread->u.fd, http_get_check->connection_to);
+       return 0;
+}
+
+/* remote Web server is connected, send it the get url query.  */
+int
+http_request_thread(thread * thread)
+{
+       checker *checker = THREAD_ARG(thread);
+       http_get_checker *http_get_check = CHECKER_ARG(checker);
+       http_arg *http_arg = HTTP_ARG(http_get_check);
+       REQ *req = HTTP_REQ(http_arg);
+       uint16_t addr_port = get_service_port(checker);
+       char *vhost = CHECKER_VHOST(checker);
+       char *str_request;
+       url *fetched_url;
+       int ret = 0;
+
+       /* Handle read timeout */
+       if (thread->type == THREAD_WRITE_TIMEOUT)
+               return timeout_epilog(thread, "=> CHECK failed on service"
+                                     " : read timeout <=\n\n",
+                                     "Web read, timeout");
+
+       /* Allocate & clean the GET string */
+       str_request = (char *) MALLOC(GET_REQUEST_BUFFER_LENGTH);
+
+       fetched_url = fetch_next_url(http_get_check);
+       snprintf(str_request, GET_REQUEST_BUFFER_LENGTH, REQUEST_TEMPLATE,
+                fetched_url->path,
+                (vhost) ? vhost : inet_ntop2(CHECKER_RIP(checker))
+                , ntohs(addr_port));
+       DBG("Processing url(%d) of [%s:%d].",
+           http_arg->url_it + 1, inet_ntop2(CHECKER_RIP(checker)),
+           ntohs(addr_port));
+
+       /* Send the GET request to remote Web server */
+       if (http_get_check->proto == PROTO_SSL)
+               ret =
+                   ssl_send_request(req->ssl, str_request,
+                                    strlen(str_request));
+       else
+               ret =
+                   (send(thread->u.fd, str_request, strlen(str_request), 0) !=
+                    -1) ? 1 : 0;
+
+       FREE(str_request);
+
+       if (!ret) {
+               syslog(LOG_INFO, "Cannot send get request to [%s:%d].",
+                      inet_ntop2(CHECKER_RIP(checker))
+                      , ntohs(addr_port));
+
+               /* check if server is currently alive */
+               if (ISALIVE(checker->rs)) {
+                       smtp_alert(thread->master, checker->rs, NULL, "DOWN",
+                                  "=> CHECK failed on service"
+                                  " : cannot send data <=\n\n");
+                       perform_svr_state(DOWN, checker->vs, checker->rs);
+               }
+               return epilog(thread, 1, 0, 0);
+       }
+
+       /* Register read timeouted thread */
+       thread_add_read(thread->master, http_response_thread, checker,
+                       thread->u.fd, http_get_check->connection_to);
+       return 1;
+}
+
+/* WEB checkers threads */
+int
+http_check_thread(thread * thread)
+{
+       checker *checker = THREAD_ARG(thread);
+       http_get_checker *http_get_check = CHECKER_ARG(checker);
+       uint16_t addr_port = get_service_port(checker);
+#ifdef _DEBUG_
+       http_arg *http_arg = HTTP_ARG(http_get_check);
+       REQ *req = HTTP_REQ(http_arg);
+#endif
+       int ret = 1;
+       int status;
+
+       status = tcp_socket_state(thread->u.fd, thread, CHECKER_RIP(checker)
+                                 , addr_port, http_check_thread);
+       switch (status) {
+       case connect_error:
+               DBG("Error connecting server [%s:%d].",
+                   inet_ntop2(CHECKER_RIP(checker)), ntohs(addr_port));
+               /* check if server is currently alive */
+               if (ISALIVE(checker->rs)) {
+                       smtp_alert(thread->master, checker->rs, NULL, "DOWN",
+                                  "=> CHECK failed on service"
+                                  " : connection error <=\n\n");
+                       perform_svr_state(DOWN, checker->vs, checker->rs);
+               }
+               return epilog(thread, 1, 0, 0);
+               break;
+
+       case connect_timeout:
+               return timeout_epilog(thread, "==> CHECK failed on service"
+                                     " : connection timeout <=\n\n",
+                                     "connect, timeout");
+               break;
+
+       case connect_success:{
+                       if (http_get_check->proto == PROTO_SSL)
+                               ret = ssl_connect(thread);
+
+                       if (ret) {
+                               /* Remote WEB server is connected.
+                                * Register the next step thread ssl_request_thread.
+                                */
+                               DBG("Remote Web server [%s:%d] connected.",
+                                   inet_ntop2(CHECKER_RIP(checker)),
+                                   ntohs(addr_port));
+                               thread_add_write(thread->master,
+                                                http_request_thread, checker,
+                                                thread->u.fd,
+                                                http_get_check->connection_to);
+                       } else {
+                               DBG("Connection trouble to: [%s:%d].",
+                                   inet_ntop2(CHECKER_RIP(checker)),
+                                   ntohs(addr_port));
+#ifdef _DEBUG_
+                               if (http_get_check->proto == PROTO_SSL)
+                                       ssl_printerr(SSL_get_error
+                                                    (req->ssl, ret));
+#endif
+                               return epilog(thread, 1, 0, 0);
+                       }
+               }
+               break;
+       }
+
+       return 0;
+}
+
+int
+http_connect_thread(thread * thread)
+{
+       checker *checker = THREAD_ARG(thread);
+       http_get_checker *http_get_check = CHECKER_ARG(checker);
+       http_arg *http_arg = HTTP_ARG(http_get_check);
+       uint16_t addr_port = get_service_port(checker);
+       url *fetched_url;
+       enum connect_result status;
+       int fd;
+
+       /*
+        * Register a new checker thread & return
+        * if checker is disabled
+        */
+       if (!CHECKER_ENABLED(checker)) {
+               thread_add_timer(thread->master, http_connect_thread, checker,
+                                checker->vs->delay_loop);
+               return 0;
+       }
+
+       /* Find eventual url end */
+       fetched_url = fetch_next_url(http_get_check);
+
+       if (!fetched_url) {
+               /* All the url have been successfully checked.
+                * Check completed.
+                * check if server is currently alive.
+                */
+               if (!ISALIVE(checker->rs)) {
+                       smtp_alert(thread->master, checker->rs, NULL, "UP",
+                                  "=> CHECK succeed on service <=\n\n");
+                       perform_svr_state(UP, checker->vs, checker->rs);
+                       DBG("Remote Web server [%s:%d] succeed on service.",
+                           inet_ntop2(CHECKER_RIP(checker)),
+                           ntohs(addr_port));
+               }
+               http_arg->req = NULL;
+               return epilog(thread, 1, 0, 0) + 1;
+       }
+
+       /* Allocate & clean request struct */
+       http_arg->req = (REQ *) MALLOC(sizeof (REQ));
+
+       if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+               DBG("WEB connection fail to create socket.");
+               return 0;
+       }
+
+       status = tcp_connect(fd, CHECKER_RIP(checker), addr_port);
+
+       /* handle tcp connection status & register check worker thread */
+       tcp_connection_state(fd, status, thread, http_check_thread,
+                            http_get_check->connection_to);
+       return 0;
+}
diff --git a/keepalived/healthcheck/check_misc.c b/keepalived/healthcheck/check_misc.c
new file mode 100644 (file)
index 0000000..8eed2f9
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * 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:        MISC CHECK. Perform a system call to run an extra
+ *              system prog or script.
+ *
+ * Version:     $Id: check_misc.c,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
+ *
+ *              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.
+ */
+
+#include "check_misc.h"
+#include "check_api.h"
+#include "memory.h"
+#include "ipwrapper.h"
+#include "smtp.h"
+#include "utils.h"
+#include "parser.h"
+#include "daemon.h"
+
+int misc_check_thread(thread *);
+
+/* Configuration stream handling */
+void
+free_misc_check(void *data)
+{
+       misc_checker *misc_chk = CHECKER_DATA(data);
+
+       FREE(misc_chk->path);
+       FREE(misc_chk);
+       FREE(data);
+}
+
+void
+dump_misc_check(void *data)
+{
+       misc_checker *misc_chk = CHECKER_DATA(data);
+
+       syslog(LOG_INFO, "   Keepalive method = MISC_CHECK");
+       syslog(LOG_INFO, "   script = %s", misc_chk->path);
+}
+
+void
+misc_check_handler(vector strvec)
+{
+       misc_checker *misc_chk = (misc_checker *) MALLOC(sizeof (misc_checker));
+
+       /* queue new checker */
+       queue_checker(free_misc_check, dump_misc_check, misc_check_thread,
+                     misc_chk);
+}
+
+void
+misc_path_handler(vector strvec)
+{
+       misc_checker *misc_chk = CHECKER_GET();
+
+       misc_chk->path = CHECKER_VALUE_STRING(strvec);
+}
+
+void
+install_misc_check_keyword(void)
+{
+       install_keyword("MISC_CHECK", &misc_check_handler);
+       install_sublevel();
+       install_keyword("misc_path", &misc_path_handler);
+       install_sublevel_end();
+}
+
+int
+misc_check_call(char *cmdline)
+{
+       int retval;
+
+       retval = system(cmdline);
+
+       if (retval == 127) {
+               /* couldn't exec command */
+               DBG("Couldn't exec command: %s", cmdline);
+       } else if (retval == -1) {
+               /* other error */
+               DBG("Error exec-ing command: %s", cmdline);
+       } else {
+               /* everything is good */
+               DBG("Successfully exec command: %s retval is %d",
+                   cmdline, retval);
+       }
+
+       return retval;
+}
+
+int
+misc_check_thread(thread * thread)
+{
+       checker *checker;
+       misc_checker *misc_chk;
+       int status;
+
+       checker = THREAD_ARG(thread);
+       misc_chk = CHECKER_ARG(checker);
+
+       /* Register next timer checker */
+       thread_add_timer(thread->master, misc_check_thread, checker,
+                        checker->vs->delay_loop);
+       /*
+        * Register a new checker thread & return
+        * if checker is disabled
+        */
+       if (!CHECKER_ENABLED(checker))
+               return 0;
+
+       /* Daemonization to not degrade our scheduling timer */
+       if (xdaemon(0, 0, 1))
+               return 0x80000000;
+
+       status = misc_check_call(misc_chk->path);
+
+       if (status >= 0) {      /* script error assumed  not an svr error */
+               if (status == 0) {
+                       /* everything is good */
+                       if (!checker->rs->alive) {
+                               smtp_alert(thread->master, checker->rs, NULL,
+                                          "UP",
+                                          "=> MISC CHECK succeed on service <=\n\n");
+                               perform_svr_state(UP, checker->vs, checker->rs);
+                       }
+               } else {
+                       if (checker->rs->alive) {
+                               smtp_alert(thread->master, checker->rs, NULL,
+                                          "DOWN",
+                                          "=> MISC CHECK failed on service <=\n\n");
+                               perform_svr_state(DOWN, checker->vs,
+                                                 checker->rs);
+                       }
+               }
+       }
+
+       exit(0);
+}
diff --git a/keepalived/healthcheck/check_ssl.c b/keepalived/healthcheck/check_ssl.c
new file mode 100644 (file)
index 0000000..73d630d
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * 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:        SSL GET CHECK. Perform an ssl get query to a specified
+ *              url, compute a MD5 over this result and match it to the
+ *              expected value.
+ *
+ * Version:     $Id: check_ssl.c,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.net>
+ *
+ *              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.
+ */
+
+#include <openssl/err.h>
+#include "check_ssl.h"
+#include "check_api.h"
+#include "memory.h"
+#include "parser.h"
+#include "smtp.h"
+#include "utils.h"
+
+extern data *conf_data;
+
+/* SSL primitives */
+/* Free an SSL context */
+void
+clear_ssl(SSL_DATA * ssl)
+{
+       if (ssl)
+               if (ssl->ctx)
+                       SSL_CTX_free(ssl->ctx);
+}
+
+/* PEM password callback function */
+static int
+password_cb(char *buf, int num, int rwflag, void *userdata)
+{
+       SSL_DATA *ssl = (SSL_DATA *) userdata;
+       unsigned int plen = strlen(ssl->password);
+
+       if (num < plen + 1)
+               return (0);
+
+       strncpy(buf, ssl->password, plen);
+       return (plen);
+}
+
+/* Inititalize global SSL context */
+static BIO *bio_err = 0;
+static int
+build_ssl_ctx(void)
+{
+       SSL_DATA *ssl;
+
+       /* Library initialization */
+       SSL_library_init();
+
+       SSL_load_error_strings();
+       bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
+
+       if (!conf_data->ssl)
+               ssl = (SSL_DATA *) MALLOC(sizeof (ssl_data));
+       else
+               ssl = conf_data->ssl;
+
+       /* Initialize SSL context for SSL v2/3 */
+       ssl->meth = SSLv23_method();
+       ssl->ctx = SSL_CTX_new(ssl->meth);
+
+       /* return for autogen context */
+       if (!conf_data->ssl) {
+               conf_data->ssl = ssl;
+               goto end;
+       }
+
+       /* Load our keys and certificates */
+       if (conf_data->ssl->keyfile)
+               if (!
+                   (SSL_CTX_use_certificate_chain_file
+                    (ssl->ctx, conf_data->ssl->keyfile))) {
+                       syslog(LOG_INFO,
+                              "SSL error : Cant load certificate file...");
+                       return 0;
+               }
+
+       /* Handle password callback using userdata ssl */
+       if (conf_data->ssl->password) {
+               SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx,
+                                                      conf_data->ssl);
+               SSL_CTX_set_default_passwd_cb(ssl->ctx, password_cb);
+       }
+
+       if (conf_data->ssl->keyfile)
+               if (!
+                   (SSL_CTX_use_PrivateKey_file
+                    (ssl->ctx, conf_data->ssl->keyfile, SSL_FILETYPE_PEM))) {
+                       syslog(LOG_INFO, "SSL error : Cant load key file...");
+                       return 0;
+               }
+
+       /* Load the CAs we trust */
+       if (conf_data->ssl->cafile)
+               if (!
+                   (SSL_CTX_load_verify_locations
+                    (ssl->ctx, conf_data->ssl->cafile, 0))) {
+                       syslog(LOG_INFO, "SSL error : Cant load CA file...");
+                       return 0;
+               }
+
+      end:
+#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
+       SSL_CTX_set_verify_depth(ssl->ctx, 1);
+#endif
+
+       return 1;
+}
+
+/*
+ * Initialize the SSL context, with or without specific
+ * configuration files.
+ */
+int
+init_ssl_ctx(void)
+{
+       SSL_DATA *ssl = conf_data->ssl;
+
+       if (!build_ssl_ctx()) {
+               syslog(LOG_INFO, "Error Initialize SSL, ctx Instance");
+               syslog(LOG_INFO, "  SSL  keyfile:%s", ssl->keyfile);
+               syslog(LOG_INFO, "  SSL password:%s", ssl->password);
+               syslog(LOG_INFO, "  SSL   cafile:%s", ssl->cafile);
+               syslog(LOG_INFO, "Terminate...\n");
+               clear_ssl(ssl);
+               return 0;
+       }
+       return 1;
+}
+
+/* Display SSL error to readable string */
+int
+ssl_printerr(int err)
+{
+       unsigned long extended_error = 0;
+       char *ssl_strerr;
+
+       switch (err) {
+       case SSL_ERROR_ZERO_RETURN:
+               DBG("  SSL error: (zero return)");
+               break;
+       case SSL_ERROR_WANT_READ:
+               DBG("  SSL error: (read error)");
+               break;
+       case SSL_ERROR_WANT_WRITE:
+               DBG("  SSL error: (write error)");
+               break;
+       case SSL_ERROR_WANT_CONNECT:
+               DBG("  SSL error: (connect error)");
+               break;
+       case SSL_ERROR_WANT_X509_LOOKUP:
+               DBG("  SSL error: (X509 lookup error)");
+               break;
+       case SSL_ERROR_SYSCALL:
+               DBG("  SSL error: (syscall error)");
+               break;
+       case SSL_ERROR_SSL:{
+                       ssl_strerr = (char *) MALLOC(500);
+
+                       extended_error = ERR_get_error();
+                       ERR_error_string(extended_error, ssl_strerr);
+                       DBG("  SSL error: (%s)", ssl_strerr);
+                       FREE(ssl_strerr);
+                       break;
+               }
+       }
+       return 0;
+}
+
+int
+ssl_connect(thread * thread)
+{
+       checker *checker = THREAD_ARG(thread);
+       http_get_checker *http_get_check = CHECKER_ARG(checker);
+       http_arg *http_arg = HTTP_ARG(http_get_check);
+       REQ *req = HTTP_REQ(http_arg);
+
+       req->ssl = SSL_new(conf_data->ssl->ctx);
+       req->bio = BIO_new_socket(thread->u.fd, BIO_NOCLOSE);
+       SSL_set_bio(req->ssl, req->bio, req->bio);
+
+       return (SSL_connect(req->ssl) > 0) ? 1 : 0;
+}
+
+int
+ssl_send_request(SSL * ssl, char *str_request, int request_len)
+{
+       int err, r = 0;
+
+       while (1) {
+               err = 1;
+               r = SSL_write(ssl, str_request, request_len);
+               if (SSL_ERROR_NONE != SSL_get_error(ssl, r))
+                       break;
+               err++;
+               if (request_len != r)
+                       break;
+               err++;
+               break;
+       }
+
+       return (err == 3) ? 1 : 0;
+}
+
+/* Asynchronous SSL stream reader */
+int
+ssl_read_thread(thread * thread)
+{
+       checker *checker = THREAD_ARG(thread);
+       http_get_checker *http_get_check = CHECKER_ARG(checker);
+       http_arg *http_arg = HTTP_ARG(http_get_check);
+       REQ *req = HTTP_REQ(http_arg);
+       unsigned char digest[16];
+       int r = 0;
+
+       /* Handle read timeout */
+       if (thread->type == THREAD_READ_TIMEOUT && !req->extracted)
+               return timeout_epilog(thread, "=> SSL CHECK failed on service"
+                                     " : recevice data <=\n\n", "SSL read");
+
+       /* read the SSL stream */
+       r = SSL_read(req->ssl, req->buffer + req->len,
+                    MAX_BUFFER_LENGTH - req->len);
+       req->error = SSL_get_error(req->ssl, r);
+
+       if (req->error) {
+
+               /* All the SSL streal has been parsed */
+               MD5_Final(digest, &req->context);
+               SSL_set_quiet_shutdown(req->ssl, 1);
+
+               r = (req->error ==
+                    SSL_ERROR_ZERO_RETURN) ? SSL_shutdown(req->ssl) : 0;
+
+               if (r && !req->extracted) {
+                       /* check if server is currently alive */
+                       if (ISALIVE(checker->rs)) {
+                               smtp_alert(thread->master, checker->rs, NULL,
+                                          "DOWN",
+                                          "=> SSL CHECK failed on service"
+                                          " : cannot receive data <=\n\n");
+                               perform_svr_state(DOWN, checker->vs,
+                                                 checker->rs);
+                       }
+                       return epilog(thread, 1, 0, 0);
+               }
+
+               /* Handle response stream */
+               http_handle_response(thread, digest, (!req->extracted) ? 1 : 0);
+
+       } else if (r > 0 && req->error == 0) {
+
+               req->len += r;
+               if (!req->extracted) {
+                       if ((req->extracted =
+                            extract_html(req->buffer, req->len))) {
+                               r = req->len - (req->extracted - req->buffer);
+                               if (r) {
+                                       memcpy(req->buffer, req->extracted, r);
+                                       MD5_Update(&req->context, req->buffer,
+                                                  r);
+                                       r = 0;
+                               }
+                               req->len = r;
+                       } else {
+                               /* minimize buffer using no 2*CR/LF found yet */
+                               if (req->len > 3) {
+                                       memcpy(req->buffer,
+                                              req->buffer + req->len - 3, 3);
+                                       req->len = 3;
+                               }
+                       }
+               } else {
+                       if (req->len) {
+                               MD5_Update(&req->context, req->buffer,
+                                          req->len);
+                               req->len = 0;
+                       }
+               }
+
+               /*
+                * Register next ssl stream reader.
+                * Register itself to not perturbe global I/O multiplexer.
+                */
+               thread_add_read(thread->master, ssl_read_thread, checker,
+                               thread->u.fd, http_get_check->connection_to);
+       }
+
+       return 0;
+}
diff --git a/keepalived/healthcheck/check_tcp.c b/keepalived/healthcheck/check_tcp.c
new file mode 100644 (file)
index 0000000..d24a5d0
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * 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:        TCP checker.
+ *
+ * Version:     $Id: check_tcp.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "check_tcp.h"
+#include "check_api.h"
+#include "memory.h"
+#include "ipwrapper.h"
+#include "layer4.h"
+#include "smtp.h"
+#include "utils.h"
+#include "parser.h"
+
+int tcp_connect_thread(thread *);
+
+/* Configuration stream handling */
+void
+free_tcp_check(void *data)
+{
+       tcp_checker *tcp_chk = CHECKER_DATA(data);
+
+       FREE(tcp_chk);
+       FREE(data);
+}
+
+void
+dump_tcp_check(void *data)
+{
+       tcp_checker *tcp_chk = CHECKER_DATA(data);
+
+       syslog(LOG_INFO, "   Keepalive method = TCP_CHECK");
+       if (tcp_chk->connection_port)
+               syslog(LOG_INFO, "   Connection port = %d",
+                      ntohs(tcp_chk->connection_port));
+       syslog(LOG_INFO, "   Connection timeout = %d", tcp_chk->connection_to);
+}
+
+void
+tcp_check_handler(vector strvec)
+{
+       tcp_checker *tcp_chk = (tcp_checker *) MALLOC(sizeof (tcp_checker));
+
+       /* queue new checker */
+       queue_checker(free_tcp_check, dump_tcp_check, tcp_connect_thread,
+                     tcp_chk);
+}
+
+void
+connect_port_handler(vector strvec)
+{
+       tcp_checker *tcp_chk = CHECKER_GET();
+       tcp_chk->connection_port = htons(CHECKER_VALUE_INT(strvec));
+}
+
+void
+connect_timeout_handler(vector strvec)
+{
+       tcp_checker *tcp_chk = CHECKER_GET();
+       tcp_chk->connection_to = CHECKER_VALUE_INT(strvec);
+}
+
+void
+install_tcp_check_keyword(void)
+{
+       install_keyword("TCP_CHECK", &tcp_check_handler);
+       install_sublevel();
+       install_keyword("connect_port", &connect_port_handler);
+       install_keyword("connect_timeout", &connect_timeout_handler);
+       install_sublevel_end();
+}
+
+int
+tcp_check_thread(thread * thread)
+{
+       checker *checker;
+       tcp_checker *tcp_check;
+       uint16_t addr_port;
+       int status;
+
+       checker = THREAD_ARG(thread);
+       tcp_check = CHECKER_ARG(checker);
+
+       addr_port = CHECKER_RPORT(checker);
+       if (tcp_check->connection_port)
+               addr_port = tcp_check->connection_port;
+       status = tcp_socket_state(thread->u.fd, thread, CHECKER_RIP(checker)
+                                 , addr_port, tcp_check_thread);
+
+       /* If status = connect_success, TCP connection to remote host is established.
+        * Otherwise we have a real connection error or connection timeout.
+        */
+       if (status == connect_success) {
+               DBG("TCP connection to [%s:%d] success.",
+                   inet_ntop2(CHECKER_RIP(checker)), ntohs(addr_port));
+               close(thread->u.fd);
+
+               if (!ISALIVE(checker->rs)) {
+                       smtp_alert(thread->master, checker->rs, NULL, "UP",
+                                  "=> TCP CHECK succeed on service <=\n\n");
+                       perform_svr_state(UP, checker->vs, checker->rs);
+               }
+
+       } else {
+               DBG("TCP connection to [%s:%d] failed !!!",
+                   inet_ntop2(CHECKER_RIP(checker)), ntohs(addr_port));
+
+               if (ISALIVE(checker->rs)) {
+                       smtp_alert(thread->master, checker->rs, NULL, "DOWN",
+                                  "=> TCP CHECK failed on service <=\n\n");
+                       perform_svr_state(DOWN, checker->vs, checker->rs);
+               }
+
+       }
+
+       /* Register next timer checker */
+       if (status != connect_in_progress)
+               thread_add_timer(thread->master, tcp_connect_thread, checker,
+                                checker->vs->delay_loop);
+       return 0;
+}
+
+int
+tcp_connect_thread(thread * thread)
+{
+       checker *checker;
+       tcp_checker *tcp_check;
+       int fd;
+       uint16_t addr_port;
+       int status;
+
+       checker = THREAD_ARG(thread);
+       tcp_check = CHECKER_ARG(checker);
+
+       /*
+        * Register a new checker thread & return
+        * if checker is disabled
+        */
+       if (!CHECKER_ENABLED(checker)) {
+               thread_add_timer(thread->master, tcp_connect_thread, checker,
+                                checker->vs->delay_loop);
+               return 0;
+       }
+
+       if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+               DBG("TCP connect fail to create socket.");
+               return 0;
+       }
+
+       addr_port = CHECKER_RPORT(checker);
+       if (tcp_check->connection_port)
+               addr_port = tcp_check->connection_port;
+       status = tcp_connect(fd, CHECKER_RIP(checker), addr_port);
+
+       /* handle tcp connection status & register check worker thread */
+       tcp_connection_state(fd, status, thread, tcp_check_thread,
+                            tcp_check->connection_to);
+       return 0;
+}
diff --git a/keepalived/healthcheck/ipfwwrapper.c b/keepalived/healthcheck/ipfwwrapper.c
new file mode 100644 (file)
index 0000000..407adad
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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:        IPFW Kernel wrapper. Use Rusty firewall manipulation
+ *              library to add/remove server MASQ rules to the kernel 
+ *              firewall framework.
+ *
+ * Version:     $Id: ipfwwrapper.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "ipfwwrapper.h"
+#include "utils.h"
+
+int
+ipfw_cmd(int cmd, virtual_server * vs, real_server * rs)
+{
+       struct ip_fwuser ctl;
+       int ret = 1;
+
+       memset(&ctl, 0, sizeof (struct ip_fwuser));
+
+       /* Create the firewall MASQ rule */
+       strncpy(ctl.label, IP_FW_LABEL_MASQUERADE, IP_FW_MAX_LABEL_LENGTH);
+       ctl.ipfw.fw_proto = vs->service_type;
+
+       /* compute the source ip address */
+       ctl.ipfw.fw_src.s_addr = SVR_IP(rs) & vs->nat_mask;
+       ctl.ipfw.fw_smsk.s_addr = vs->nat_mask;
+
+       ctl.ipfw.fw_spts[0] = ctl.ipfw.fw_spts[1] = htons(SVR_PORT(rs));
+       ctl.ipfw.fw_dpts[0] = 0x0000;
+       ctl.ipfw.fw_dpts[1] = 0xFFFF;
+       ctl.ipfw.fw_tosand = 0xFF;
+       ctl.ipfw.fw_tosxor = 0x00;
+
+       if (cmd & IP_FW_CMD_ADD) {
+               ipfwc_delete_entry(IP_FW_LABEL_FORWARD, &ctl);
+               if (!(errno & EINVAL)) {
+                       DBG("ipfw_cmd : MASQ firewall rule [%s:%d] already exist.",
+                           inet_ntop2(SVR_IP(rs)), ntohs(SVR_PORT(rs)));
+               }
+               ret &= ipfwc_insert_entry(IP_FW_LABEL_FORWARD, &ctl, 1);
+       }
+
+       if (cmd & IP_FW_CMD_DEL)
+               ret &= ipfwc_delete_entry(IP_FW_LABEL_FORWARD, &ctl);
+
+       if (!ret) {
+               DBG("ipfw_cmd : firewall error (%s) processing [%s:%d] MASQ rule.",
+                   strerror(errno), inet_ntop2(SVR_IP(rs)), ntohs(SVR_PORT(rs)));
+               return IPFW_ERROR;
+       }
+
+       return IPFW_SUCCESS;
+}
diff --git a/keepalived/healthcheck/ipvswrapper.c b/keepalived/healthcheck/ipvswrapper.c
new file mode 100644 (file)
index 0000000..40cb12c
--- /dev/null
@@ -0,0 +1,289 @@
+/* 
+ * 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:        IPVS Kernel wrapper. Use setsockopt call to add/remove
+ *              server to/from the loadbalanced server pool.
+ *  
+ * Version:     $Id: ipvswrapper.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "ipvswrapper.h"
+#include "utils.h"
+
+#ifdef _KRNL_2_2_              /* KERNEL 2.2 LVS handling */
+
+int
+ipvs_syncd_cmd(int cmd, char *ifname, int state)
+{
+       syslog(LOG_INFO, "IPVS : Sync daemon not supported on kernel v2.2");
+       return IPVS_ERROR;
+}
+
+int
+ipvs_cmd(int cmd, virtual_server * vs, real_server * rs)
+{
+       struct ip_masq_ctl ctl;
+       int result = 0;
+       int sockfd;
+
+       memset(&ctl, 0, sizeof (struct ip_masq_ctl));
+
+       ctl.m_target = IP_MASQ_TARGET_VS;
+       ctl.m_cmd = cmd;
+       strncpy(ctl.m_tname, vs->sched, IP_MASQ_TNAME_MAX);
+       ctl.u.vs_user.weight = -1;
+       ctl.u.vs_user.masq_flags = vs->loadbalancing_kind;
+       ctl.u.vs_user.netmask = ((u_int32_t) 0xffffffff);
+       ctl.u.vs_user.protocol = vs->service_type;
+
+       if (!parse_timeout(vs->timeout_persistence, &ctl.u.vs_user.timeout))
+               syslog(LOG_INFO,
+                      "IPVS : Virtual service [%s:%d] illegal timeout.",
+                      inet_ntop2(SVR_IP(vs))
+                      , ntohs(SVR_PORT(vs)));
+       if (ctl.u.vs_user.timeout != 0 || vs->granularity_persistence)
+               ctl.u.vs_user.vs_flags = IP_VS_SVC_F_PERSISTENT;
+
+       /* VS specific */
+       if (vs->vfwmark) {
+               ctl.u.vs_user.vfwmark = vs->vfwmark;
+       } else {
+               ctl.u.vs_user.vaddr = SVR_IP(vs);
+               ctl.u.vs_user.vport = SVR_PORT(vs);
+       }
+
+       if (ctl.m_cmd == IP_MASQ_CMD_ADD || ctl.m_cmd == IP_MASQ_CMD_DEL)
+               if (vs->granularity_persistence)
+                       ctl.u.vs_user.netmask = vs->granularity_persistence;
+
+       /* SVR specific */
+       if (ctl.m_cmd == IP_MASQ_CMD_ADD_DEST
+           || ctl.m_cmd == IP_MASQ_CMD_DEL_DEST) {
+               ctl.u.vs_user.weight = rs->weight;
+               ctl.u.vs_user.daddr = SVR_IP(rs);
+               ctl.u.vs_user.dport = SVR_PORT(rs);
+       }
+
+       sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+       if (sockfd == -1) {
+               syslog(LOG_INFO,
+                      "IPVS : Can not initialize SOCK_RAW descriptor.");
+               return IPVS_ERROR;
+       }
+
+       result =
+           setsockopt(sockfd, IPPROTO_IP, IP_FW_MASQ_CTL, (char *) &ctl,
+                      sizeof (ctl));
+
+       if (errno == ESRCH) {
+               syslog(LOG_INFO, "IPVS : Virtual service [%s:%d] not defined.",
+                      inet_ntop2(SVR_IP(vs))
+                      , ntohs(SVR_PORT(vs)));
+               close(sockfd);
+               return IPVS_ERROR;
+       } else if (errno == EEXIST) {
+               if (rs)
+                       syslog(LOG_INFO,
+                              "IPVS : Destination already exists [%s:%d].",
+                              inet_ntop2(SVR_IP(rs))
+                              , ntohs(SVR_PORT(rs)));
+       } else if (errno == ENOENT) {
+               if (rs)
+                       syslog(LOG_INFO, "IPVS : No such destination [%s:%d].",
+                              inet_ntop2(SVR_IP(rs))
+                              , ntohs(SVR_PORT(rs)));
+       }
+
+       close(sockfd);
+       return IPVS_SUCCESS;
+}
+
+#else                          /* KERNEL 2.4 LVS handling */
+
+/* 2.4 prototypes */
+static int modprobe_ipvs(void);
+
+static int
+ipvs_talk(int cmd, struct ip_vs_rule_user *urule)
+{
+       int result;
+
+       /* Init IPVS kernel channel */
+       if (ipvs_init()) {
+               /* try to insmod the ip_vs module if ipvs_init failed */
+               if (modprobe_ipvs() || ipvs_init()) {
+                       syslog(LOG_INFO,
+                              "IPVS : Can't initialize ipvs: %s",
+                              ipvs_strerror(errno));
+                       return IPVS_ERROR;
+               }
+       }
+
+       result = ipvs_command(cmd, urule);
+       if (result)
+               syslog(LOG_INFO, "IPVS : %s", ipvs_strerror(errno));
+       ipvs_close();
+       return IPVS_SUCCESS;
+}
+
+int
+ipvs_syncd_cmd(int cmd, char *ifname, int state)
+{
+#ifdef _HAVE_IPVS_SYNCD_
+
+       struct ip_vs_rule_user urule;
+
+       memset(&urule, 0, sizeof (struct ip_vs_rule_user));
+
+       /* prepare user rule */
+       urule.state = state;
+       if (ifname != NULL)
+               strncpy(urule.mcast_ifn, ifname, IP_VS_IFNAME_MAXLEN);
+
+       /* Talk to the IPVS channel */
+       return ipvs_talk(cmd, &urule);
+
+#else
+       syslog(LOG_INFO, "IPVS : Sync daemon not supported");
+       return IPVS_ERROR;
+#endif
+}
+
+int
+ipvs_cmd(int cmd, virtual_server * vs, real_server * rs)
+{
+       struct ip_vs_rule_user urule;
+
+       memset(&urule, 0, sizeof (struct ip_vs_rule_user));
+
+       strncpy(urule.sched_name, vs->sched, IP_VS_SCHEDNAME_MAXLEN);
+       urule.weight = 1;
+       urule.conn_flags = vs->loadbalancing_kind;
+       urule.netmask = ((u_int32_t) 0xffffffff);
+       urule.protocol = vs->service_type;
+
+       if (!parse_timeout(vs->timeout_persistence, &urule.timeout))
+               syslog(LOG_INFO,
+                      "IPVS : Virtual service [%s:%d] illegal timeout.",
+                      inet_ntop2(SVR_IP(vs))
+                      , ntohs(SVR_PORT(vs)));
+       if (urule.timeout != 0 || vs->granularity_persistence)
+               urule.vs_flags = IP_VS_SVC_F_PERSISTENT;
+
+       /* VS specific */
+       if (vs->vfwmark) {
+               urule.vfwmark = vs->vfwmark;
+       } else {
+               urule.vaddr = SVR_IP(vs);
+               urule.vport = SVR_PORT(vs);
+       }
+
+       if (cmd == IP_VS_SO_SET_ADD || cmd == IP_VS_SO_SET_DEL)
+               if (vs->granularity_persistence)
+                       urule.netmask = vs->granularity_persistence;
+
+       /* SVR specific */
+       if (cmd == IP_VS_SO_SET_ADDDEST || cmd == IP_VS_SO_SET_DELDEST) {
+               urule.weight = rs->weight;
+               urule.daddr = SVR_IP(rs);
+               urule.dport = SVR_PORT(rs);
+       }
+
+       /* Talk to the IPVS channel */
+       return ipvs_talk(cmd, &urule);
+}
+
+#endif
+
+/*
+ * IPVS synchronization daemon state transition
+ */
+void
+ipvs_syncd_master(char *ifname)
+{
+       ipvs_syncd_cmd(IPVS_STOPDAEMON, ifname, IPVS_BACKUP);
+       ipvs_syncd_cmd(IPVS_STARTDAEMON, ifname, IPVS_MASTER);
+}
+
+void
+ipvs_syncd_backup(char *ifname)
+{
+       ipvs_syncd_cmd(IPVS_STOPDAEMON, ifname, IPVS_MASTER);
+       ipvs_syncd_cmd(IPVS_STARTDAEMON, ifname, IPVS_BACKUP);
+}
+
+/*
+ * Source code from the ipvsadm.c Wensong code
+ */
+
+int
+parse_timeout(char *buf, unsigned *timeout)
+{
+       int i;
+
+       if (buf == NULL) {
+               *timeout = IP_VS_TEMPLATE_TIMEOUT;
+               return 1;
+       }
+
+       if ((i = string_to_number(buf, 0, 86400 * 31)) == -1)
+               return 0;
+
+       *timeout = i * HZ;
+       return 1;
+}
+
+int
+string_to_number(const char *s, int min, int max)
+{
+       int number;
+       char *end;
+
+       number = (int) strtol(s, &end, 10);
+       if (*end == '\0' && end != s) {
+               /*
+                * We parsed a number, let's see if we want this.
+                * If max <= min then ignore ranges
+                */
+               if (max <= min || (min <= number && number <= max))
+                       return number;
+               else
+                       return -1;
+       } else
+               return -1;
+}
+
+static int modprobe_ipvs(void)
+{
+       char *argv[] = { "/sbin/modprobe", "-s", "-k", "--", "ip_vs", NULL };
+       int child;
+       int status;
+       int rc;
+
+       if (!(child = fork())) {
+               execv(argv[0], argv);
+               exit(1);
+       }
+
+       rc = waitpid(child, &status, 0);
+
+       if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+               return 1;
+       }
+
+       return 0;
+}
diff --git a/keepalived/healthcheck/ipwrapper.c b/keepalived/healthcheck/ipwrapper.c
new file mode 100644 (file)
index 0000000..0ee63ac
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * 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:        Manipulation functions for IPVS & IPFW wrappers.
+ *
+ * Version:     $id: ipwrapper.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "ipwrapper.h"
+#include "utils.h"
+
+extern data *conf_data;
+
+static int
+clear_service_rs(virtual_server * vs, list l)
+{
+       element e;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               if (!ipvs_cmd(LVS_CMD_DEL_DEST, vs, ELEMENT_DATA(e)))
+                       return 0;
+#ifdef _KRNL_2_2_
+               /* if we have a /32 mask, we create one nat rules per
+                * realserver.
+                */
+               if (vs->nat_mask == HOST_NETMASK)
+                       if (!ipfw_cmd(IP_FW_CMD_DEL, vs, ELEMENT_DATA(e)))
+                               return 0;
+#endif
+       }
+       return 1;
+}
+
+int
+clear_service_vs(virtual_server * vs)
+{
+       element e;
+       real_server_group *group;
+
+       /* Processing real server queue */
+       if (!LIST_ISEMPTY(vs->rs)) {
+               if (vs->s_svr) {
+                       if (vs->s_svr->alive)
+                               if (!ipvs_cmd(LVS_CMD_DEL_DEST, vs, vs->s_svr))
+                                       return 0;
+               } else if (!clear_service_rs(vs, vs->rs))
+                       return 0;
+       }
+
+       /* Processing real server group queue */
+       if (!LIST_ISEMPTY(vs->rs_group)) {
+               for (e = LIST_HEAD(vs->rs_group); e; ELEMENT_NEXT(e)) {
+                       group = ELEMENT_DATA(e);
+                       if (!clear_service_rs(vs, group->rs))
+                               return 0;
+               }
+       }
+
+       if (!ipvs_cmd(LVS_CMD_DEL, vs, NULL))
+               return 0;
+       return 1;
+}
+
+/* IPVS cleaner processing */
+int
+clear_services(void)
+{
+       element e;
+       list vs = conf_data->vs;
+       virtual_server *vsvr;
+       real_server *rsvr;
+
+       for (e = LIST_HEAD(vs); e; ELEMENT_NEXT(e)) {
+               vsvr = ELEMENT_DATA(e);
+               rsvr = ELEMENT_DATA(LIST_HEAD(vsvr->rs));
+               if (!clear_service_vs(vsvr))
+                       return 0;
+#ifdef _KRNL_2_2_
+               if (vsvr->nat_mask != HOST_NETMASK)
+                       if (!ipfw_cmd(IP_FW_CMD_DEL, vsvr, rsvr))
+                               return 0;
+#endif
+       }
+       return 1;
+}
+
+int
+all_realservers_down(virtual_server * vs)
+{
+       element e;
+       real_server *svr;
+
+       for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) {
+               svr = ELEMENT_DATA(e);
+               if (svr->alive)
+                       return 0;
+       }
+       return 1;
+}
+
+void
+perform_svr_state(int alive, virtual_server * vs, real_server * rs)
+{
+       char rsip[16], vsip[16];
+
+       if (!ISALIVE(rs) && alive) {
+
+               /* adding a server to the vs pool, if sorry server is flagged alive,
+                * we remove it from the vs pool.
+                */
+               if (vs->s_svr) {
+                       if (vs->s_svr->alive) {
+                               syslog(LOG_INFO,
+                                      "Removing sorry server [%s:%d] from VS [%s:%d]",
+                                      inet_ntoa2(SVR_IP(vs->s_svr), rsip)
+                                      , ntohs(SVR_PORT(vs->s_svr))
+                                      , inet_ntoa2(SVR_IP(vs), vsip)
+                                      , ntohs(SVR_PORT(vs)));
+
+                               vs->s_svr->alive = 0;
+                               ipvs_cmd(LVS_CMD_DEL_DEST, vs, vs->s_svr);
+#ifdef _KRNL_2_2_
+                               ipfw_cmd(IP_FW_CMD_DEL, vs, vs->s_svr);
+#endif
+                       }
+               }
+
+               rs->alive = alive;
+               syslog(LOG_INFO, "Adding service [%s:%d] to VS [%s:%d]",
+                      inet_ntoa2(SVR_IP(rs), rsip)
+                      , ntohs(SVR_PORT(rs))
+                      , inet_ntoa2(SVR_IP(vs), vsip)
+                      , ntohs(SVR_PORT(vs)));
+               ipvs_cmd(LVS_CMD_ADD_DEST, vs, rs);
+#ifdef _KRNL_2_2_
+               if (vs->nat_mask == HOST_NETMASK)
+                       ipfw_cmd(IP_FW_CMD_ADD, vs, rs);
+#endif
+
+       } else {
+
+               rs->alive = alive;
+               syslog(LOG_INFO, "Removing service [%s:%d] from VS [%s:%d]",
+                      inet_ntoa2(SVR_IP(rs), rsip)
+                      , ntohs(SVR_PORT(rs))
+                      , inet_ntoa2(SVR_IP(vs), vsip)
+                      , ntohs(SVR_PORT(vs)));
+
+               /* server is down, it is removed from the LVS realserver pool */
+               ipvs_cmd(LVS_CMD_DEL_DEST, vs, rs);
+
+#ifdef _KRNL_2_2_
+               if (vs->nat_mask == HOST_NETMASK)
+                       ipfw_cmd(IP_FW_CMD_DEL, vs, rs);
+#endif
+
+               /* if all the realserver pool is down, we add sorry server */
+               if (vs->s_svr && all_realservers_down(vs)) {
+                       syslog(LOG_INFO,
+                              "Adding sorry server [%s:%d] to VS [%s:%d]",
+                              inet_ntoa2(SVR_IP(vs->s_svr), rsip)
+                              , ntohs(SVR_PORT(vs->s_svr))
+                              , inet_ntoa2(SVR_IP(vs), vsip)
+                              , ntohs(SVR_PORT(vs)));
+
+                       /* the sorry server is now up in the pool, we flag it alive */
+                       vs->s_svr->alive = 1;
+                       ipvs_cmd(LVS_CMD_ADD_DEST, vs, vs->s_svr);
+
+#ifdef _KRNL_2_2_
+                       ipfw_cmd(IP_FW_CMD_ADD, vs, vs->s_svr);
+#endif
+               }
+
+       }
+}
+
+static int
+init_service_rs(virtual_server * vs, list l)
+{
+       element e;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               if (!ipvs_cmd(LVS_CMD_ADD_DEST, vs, ELEMENT_DATA(e)))
+                       return 0;
+#ifdef _KRNL_2_2_
+               /* if we have a /32 mask, we create one nat rules per
+                * realserver.
+                */
+               if (vs->nat_mask == HOST_NETMASK)
+                       if (!ipfw_cmd(IP_FW_CMD_ADD, vs, ELEMENT_DATA(e)))
+                               return 0;
+#endif
+       }
+       return 1;
+}
+
+int
+init_service_vs(virtual_server * vs)
+{
+       element e;
+       real_server_group *group;
+
+       /* Init the IPVS root */
+       if (!ipvs_cmd(LVS_CMD_ADD, vs, NULL))
+               return 0;
+
+       /* Processing real server queue */
+       if (!LIST_ISEMPTY(vs->rs))
+               if (!init_service_rs(vs, vs->rs))
+                       return 0;
+
+       /* Processing real server group queue */
+       if (!LIST_ISEMPTY(vs->rs_group)) {
+               for (e = LIST_HEAD(vs->rs_group); e; ELEMENT_NEXT(e)) {
+                       group = ELEMENT_DATA(e);
+                       if (!init_service_rs(vs, group->rs))
+                               return 0;
+               }
+       }
+       return 1;
+}
+
+int
+init_services(void)
+{
+       element e;
+       list vs = conf_data->vs;
+       virtual_server *vsvr;
+       real_server *rsvr;
+
+       for (e = LIST_HEAD(vs); e; ELEMENT_NEXT(e)) {
+               vsvr = ELEMENT_DATA(e);
+               rsvr = ELEMENT_DATA(LIST_HEAD(vsvr->rs));
+               if (!init_service_vs(vsvr))
+                       return 0;
+#ifdef _KRNL_2_2_
+               /* work if all realserver ip address are in the
+                * same network (it is assumed).
+                */
+               if (vsvr->nat_mask != HOST_NETMASK)
+                       if (!ipfw_cmd(IP_FW_CMD_ADD, vsvr, rsvr))
+                               return 0;
+#endif
+       }
+       return 1;
+}
similarity index 82%
rename from check_api.h
rename to keepalived/include/check_api.h
index ecc62ad..438c5ee 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Checkers arguments structures definitions.
  *
- * Version:     $Id: check_api.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: check_api.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 
 /* Checkers structure definition */
 typedef struct _checker {
-  void (*free) (void *);
-  void (*dump) (void *);
-  int (*launch)        (struct _thread *);
-  virtual_server       *vs;     /* pointer to the checker thread virtualserver */
-  real_server          *rs;     /* pointer to the checker thread realserver */
-  void                 *data;
-  int                  enabled; /* Activation flag */
+       void (*free) (void *);
+       void (*dump) (void *);
+       int (*launch) (struct _thread *);
+       virtual_server *vs;     /* pointer to the checker thread virtualserver */
+       real_server *rs;        /* pointer to the checker thread realserver */
+       void *data;
+       int enabled;            /* Activation flag */
 } checker;
 
 /* Checkers queue */
@@ -59,8 +59,8 @@ list checkers_queue;
 /* Prototypes definition */
 extern void init_checkers_queue(void);
 extern void queue_checker(void (*free) (void *), void (*dump) (void *)
-                                        , int (*launch) (struct _thread *)
-                                        , void *data);
+                         , int (*launch) (struct _thread *)
+                         , void *data);
 extern void dump_checkers_queue(void);
 extern void free_checkers_queue(void);
 extern void register_checkers_thread(void);
similarity index 86%
rename from check_ci.h
rename to keepalived/include/check_ci.h
index 8a16e60..29cae54 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_ci.c include file.
  *
- * Version:     $Id: check_ci.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: check_ci.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Aneesh Kumar K.V, <aneesh.kumar@digital.com>
@@ -27,7 +27,7 @@
 /* system includes */
 #include <signal.h>
 #include <pthread.h>
-#include <linux/cluster.h> /* Should change this to cluster.h alone */
+#include <linux/cluster.h>     /* Should change this to cluster.h alone */
 #include <syslog.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #define UNKNOWN_NODE 0
 
 typedef struct nodenum_ip_map {
-  uint32_t      addr_ip;
+       uint32_t addr_ip;
 } nodenum_ip_map_t;
 
 /* Prototypes defs */
-extern int initialize_nodemap(nodenum_ip_map_t *nodemap);
+extern int initialize_nodemap(nodenum_ip_map_t * nodemap);
 extern clusternode_t address_to_nodenum(uint32_t addr_ip);
 extern int nodestatus(uint32_t addr_ip);
 extern void install_ci_check_keyword(void);
-extern int ci_check_thread(thread *thread);
+extern int ci_check_thread(thread * thread);
 
 #endif
similarity index 70%
rename from check_http.h
rename to keepalived/include/check_http.h
index c2d1d2f..05a41e5 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_http.c include file.
  *
- * Version:     $Id: check_http.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: check_http.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Jan Holmberg, <jan@artech.net>
 /* Checker argument structure  */
 /* ssl specific thread arguments defs */
 typedef struct {
-  char  *buffer;
-  char  *extracted;
-  int   error;
-  int   len;
-  SSL   *ssl;
-  BIO   *bio;
-  MD5_CTX context;
+       char *buffer;
+       char *extracted;
+       int error;
+       int len;
+       SSL *ssl;
+       BIO *bio;
+       MD5_CTX context;
 } REQ;
 
 /* http specific thread arguments defs */
 typedef struct _http_arg {
-  int retry_it;         /* current number of get retry */
-  int url_it;           /* current url checked index */
-  REQ *req;             /* GET buffer and SSL args */
+       int retry_it;           /* current number of get retry */
+       int url_it;             /* current url checked index */
+       REQ *req;               /* GET buffer and SSL args */
 } http_arg;
 
 typedef struct _url {
-  char *path;
-  char *digest;
+       char *path;
+       char *digest;
 } url;
 typedef struct _http_get_checker {
-  int      proto;
-  uint16_t connection_port;
-  int      connection_to;
-  int      nb_get_retry;
-  int      delay_before_retry;
-  list     url;
-  http_arg *arg;
+       int proto;
+       uint16_t connection_port;
+       int connection_to;
+       int nb_get_retry;
+       int delay_before_retry;
+       list url;
+       http_arg *arg;
 } http_get_checker;
 
 /* global defs */
@@ -87,11 +87,10 @@ typedef struct _http_get_checker {
 
 /* Define prototypes */
 extern void install_http_check_keyword(void);
-extern int epilog(thread *thread, int metod, int t, int c);
-extern int timeout_epilog(thread *thread, char *smtp_msg, char *debug_msg);
+extern int epilog(thread * thread, int metod, int t, int c);
+extern int timeout_epilog(thread * thread, char *smtp_msg, char *debug_msg);
 extern char *extract_html(char *buffer, int size_buffer);
-extern url *fetch_next_url(http_get_checker *http_get_check);
-extern int http_handle_response(thread *thread
-                                , unsigned char digest[16]
-                                , int empty_buffer);
+extern url *fetch_next_url(http_get_checker * http_get_check);
+extern int http_handle_response(thread * thread, unsigned char digest[16]
+                               , int empty_buffer);
 #endif
similarity index 94%
rename from check_misc.h
rename to keepalived/include/check_misc.h
index 65c354b..f8ad2ef 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_misc.c include file.
  *
- * Version:     $Id: check_misc.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: check_misc.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
@@ -32,7 +32,7 @@
 
 /* Checker argument structure  */
 typedef struct _misc_checker {
-  char *path;
+       char *path;
 } misc_checker;
 
 /* Prototypes defs */
similarity index 81%
rename from check_ssl.h
rename to keepalived/include/check_ssl.h
index bdc25e3..f27382e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_http.c include file.
  *
- * Version:     $Id: check_http.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: check_http.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Jan Holmberg, <jan@artech.net>
 /* Prototypes */
 extern void install_ssl_check_keyword(void);
 extern int init_ssl_ctx(void);
-extern void clear_ssl(SSL_DATA *ssl);
-extern int ssl_connect(thread *thread);
+extern void clear_ssl(SSL_DATA * ssl);
+extern int ssl_connect(thread * thread);
 extern int ssl_printerr(int err);
-extern int ssl_send_request(SSL *ssl, char *str_request, int request_len);
-extern int ssl_read_thread(thread *thread);
+extern int ssl_send_request(SSL * ssl, char *str_request, int request_len);
+extern int ssl_read_thread(thread * thread);
 
 #endif
similarity index 91%
rename from check_tcp.h
rename to keepalived/include/check_tcp.h
index 633cac6..7100f0c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_tcp.c include file.
  *
- * Version:     $Id: check_tcp.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: check_tcp.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -33,8 +33,8 @@
 
 /* Checker argument structure  */
 typedef struct _tcp_checker {
-  uint16_t connection_port;
-  int connection_to;
+       uint16_t connection_port;
+       int connection_to;
 } tcp_checker;
 
 /* Prototypes defs */
similarity index 95%
rename from daemon.h
rename to keepalived/include/daemon.h
index 0791e55..cfa61cf 100644 (file)
--- a/daemon.h
@@ -5,7 +5,7 @@
  *
  * Part:        Daemon process handling.
  *
- * Version:     $Id: daemon.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: daemon.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
similarity index 71%
rename from data.h
rename to keepalived/include/data.h
index 135030c..0951df2 100644 (file)
--- a/data.h
@@ -5,7 +5,7 @@
  *
  * Part:        Dynamic data structure definition.
  *
- * Version:     $Id: data.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: data.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 
 #ifdef _WITH_LVS_
 #ifdef _KRNL_2_2_
-  #include <linux/ip_masq.h>
-  #include <net/ip_masq.h>
-  #define SCHED_MAX_LENGTH IP_MASQ_TNAME_MAX
+#include <linux/ip_masq.h>
+#include <net/ip_masq.h>
+#define SCHED_MAX_LENGTH IP_MASQ_TNAME_MAX
 #else
-  #define SCHED_MAX_LENGTH IP_VS_SCHEDNAME_MAXLEN
+#define SCHED_MAX_LENGTH IP_VS_SCHEDNAME_MAXLEN
 #endif
 #include <net/ip_vs.h>
 #else
-  #define SCHED_MAX_LENGTH   1
+#define SCHED_MAX_LENGTH   1
 #endif
 
 /* local includes */
 /* SSL specific data */
 typedef struct _ssl_data SSL_DATA;
 typedef struct _ssl_data {
-  int          enable;
-  int          strong_check;
-  SSL_CTX      *ctx;
-  SSL_METHOD   *meth;
-  char         *password;
-  char         *cafile;
-  char         *certfile;
-  char         *keyfile;
+       int enable;
+       int strong_check;
+       SSL_CTX *ctx;
+       SSL_METHOD *meth;
+       char *password;
+       char *cafile;
+       char *certfile;
+       char *keyfile;
 } ssl_data;
 
 /* Real Server definition */
 typedef struct _real_server {
-  uint32_t     addr_ip;
-  uint16_t     addr_port;
-  int          weight;
-  int          alive;
+       uint32_t addr_ip;
+       uint16_t addr_port;
+       int weight;
+       int alive;
 } real_server;
 
 /* Real server group list */
 typedef struct _real_server_group {
-  char *gname;
-  list rs;
+       char *gname;
+       list rs;
 //  list vs;
 } real_server_group;
 
 /* Virtual Server definition */
 typedef struct _virtual_server {
-  uint32_t             addr_ip;
-  uint32_t             vfwmark;
-  uint16_t             addr_port;
-  uint16_t             service_type;
-  int                  delay_loop;
-  char                 sched[SCHED_MAX_LENGTH];
-  char                 timeout_persistence[MAX_TIMEOUT_LENGTH];
-  unsigned             loadbalancing_kind;
-  uint32_t             nat_mask;
-  uint32_t             granularity_persistence;
-  char                 *virtualhost;
-  real_server          *s_svr;
-  list                 rs;
-  list                 rs_group;
-  int                  last_rs_type;
+       uint32_t addr_ip;
+       uint32_t vfwmark;
+       uint16_t addr_port;
+       uint16_t service_type;
+       int delay_loop;
+       char sched[SCHED_MAX_LENGTH];
+       char timeout_persistence[MAX_TIMEOUT_LENGTH];
+       unsigned loadbalancing_kind;
+       uint32_t nat_mask;
+       uint32_t granularity_persistence;
+       char *virtualhost;
+       real_server *s_svr;
+       list rs;
+       list rs_group;
+       int last_rs_type;
 #define RS             (1 << 0)
 #define RS_GROUP       (1 << 1)
 } virtual_server;
 
 /* email link list */
 typedef struct _email {
-  char *addr;
+       char *addr;
 } email;
 
 /* Configuration data root */
 typedef struct _data {
-  char         *lvs_id;
-  char         *email_from;
-  uint32_t     smtp_server;
-  int          smtp_connection_to;
-  SSL_DATA     *ssl;
-  list         email;
-  list         vrrp;
-  list         vrrp_sync_group;
-  list         vs;
-  list         group;
+       char *lvs_id;
+       char *email_from;
+       uint32_t smtp_server;
+       int smtp_connection_to;
+       SSL_DATA *ssl;
+       list email;
+       list vrrp;
+       list vrrp_sync_group;
+       list vs;
+       list group;
 } data;
 
 /* macro utility */
similarity index 88%
rename from ipfwwrapper.h
rename to keepalived/include/ipfwwrapper.h
index b7d98bc..36ee116 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipfwwrapper.c include file.
  *
- * Version:     $Id: ipfwwrapper.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: ipfwwrapper.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -28,7 +28,7 @@
 #include <arpa/inet.h>
 
 /* locale includes */
-#include "libipfwc/libipfwc.h"
+#include "../libipfwc/libipfwc.h"
 #include "data.h"
 
 /* local defs */
@@ -42,6 +42,6 @@
 #define IPFW_SRC_NETMASK 0xffffffff
 
 /* prototypes */
-extern int ipfw_cmd(int cmd, virtual_server *vserver, real_server *rserver);
+extern int ipfw_cmd(int cmd, virtual_server * vserver, real_server * rserver);
 
 #endif
similarity index 77%
rename from ipvswrapper.h
rename to keepalived/include/ipvswrapper.h
index d1e553f..ad99452 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipvswrapper.c include file.
  *
- * Version:     $Id: ipvswrapper.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: ipvswrapper.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include <netinet/ip_icmp.h>
 #include <netinet/udp.h>
 #include <netinet/tcp.h>
+#include <sys/wait.h>
 
 #ifdef _WITH_LVS_
 #ifdef _KRNL_2_2_
-  #include <linux/ip_fw.h>
-  #include <net/ip_masq.h>
+#include <linux/ip_fw.h>
+#include <net/ip_masq.h>
 #else
-  #include "libipvs/libipvs.h"
+#include "../libipvs/libipvs.h"
 #endif
 #include <net/ip_vs.h>
 #endif
 #define IPVS_CMD_DELAY 3
 
 #ifdef _HAVE_IPVS_SYNCD_
-  #define IPVS_STARTDAEMON     IP_VS_SO_SET_STARTDAEMON
-  #define IPVS_STOPDAEMON      IP_VS_SO_SET_STOPDAEMON
-  #define IPVS_MASTER          IP_VS_STATE_MASTER
-  #define IPVS_BACKUP          IP_VS_STATE_BACKUP
+#define IPVS_STARTDAEMON       IP_VS_SO_SET_STARTDAEMON
+#define IPVS_STOPDAEMON        IP_VS_SO_SET_STOPDAEMON
+#define IPVS_MASTER            IP_VS_STATE_MASTER
+#define IPVS_BACKUP            IP_VS_STATE_BACKUP
 #else
-  #define IPVS_STARTDAEMON     1
-  #define IPVS_STOPDAEMON      2
-  #define IPVS_MASTER          3
-  #define IPVS_BACKUP          4
+#define IPVS_STARTDAEMON       1
+#define IPVS_STOPDAEMON        2
+#define IPVS_MASTER            3
+#define IPVS_BACKUP            4
 #endif
 
 extern thread_master *master;
@@ -71,7 +72,7 @@ extern thread_master *master;
 /* prototypes */
 extern int parse_timeout(char *buf, unsigned *timeout);
 extern int string_to_number(const char *s, int min, int max);
-extern int ipvs_cmd(int cmd, virtual_server *vserver, real_server *rserver);
+extern int ipvs_cmd(int cmd, virtual_server * vserver, real_server * rserver);
 extern int ipvs_syncd_cmd(int cmd, char *ifname, int state);
 extern void ipvs_syncd_master(char *ifname);
 extern void ipvs_syncd_backup(char *ifname);
similarity index 68%
rename from ipwrapper.h
rename to keepalived/include/ipwrapper.h
index d6f6776..6155536 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipwrapper.c include file.
  *
- * Version:     $Id: ipwrapper.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: ipwrapper.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 
 /* LVS command set by kernel */
 #ifdef _KRNL_2_2_
-  #define LVS_CMD_ADD      IP_MASQ_CMD_ADD
-  #define LVS_CMD_DEL      IP_MASQ_CMD_DEL
-  #define LVS_CMD_ADD_DEST IP_MASQ_CMD_ADD_DEST
-  #define LVS_CMD_DEL_DEST IP_MASQ_CMD_DEL_DEST
+#define LVS_CMD_ADD      IP_MASQ_CMD_ADD
+#define LVS_CMD_DEL      IP_MASQ_CMD_DEL
+#define LVS_CMD_ADD_DEST IP_MASQ_CMD_ADD_DEST
+#define LVS_CMD_DEL_DEST IP_MASQ_CMD_DEL_DEST
 #else
-  #define LVS_CMD_ADD      IP_VS_SO_SET_ADD
-  #define LVS_CMD_DEL      IP_VS_SO_SET_DEL
-  #define LVS_CMD_ADD_DEST IP_VS_SO_SET_ADDDEST
-  #define LVS_CMD_DEL_DEST IP_VS_SO_SET_DELDEST
+#define LVS_CMD_ADD      IP_VS_SO_SET_ADD
+#define LVS_CMD_DEL      IP_VS_SO_SET_DEL
+#define LVS_CMD_ADD_DEST IP_VS_SO_SET_ADDDEST
+#define LVS_CMD_DEL_DEST IP_VS_SO_SET_DELDEST
 #endif
 
 /* prototypes */
-extern void perform_svr_state(int alive, virtual_server *vs, real_server *rs);
+extern void perform_svr_state(int alive, virtual_server * vs, real_server * rs);
 extern int init_services(void);
 extern int clear_services(void);
 
-extern int ipvs_cmd(int cmd, virtual_server *vserver, real_server *rserver);
-extern int ipfw_cmd(int cmd, virtual_server *vserver, real_server *rserver);
+extern int ipvs_cmd(int cmd, virtual_server * vserver, real_server * rserver);
+extern int ipfw_cmd(int cmd, virtual_server * vserver, real_server * rserver);
 
 #endif
similarity index 77%
rename from layer4.h
rename to keepalived/include/layer4.h
index 045732a..e480961 100644 (file)
--- a/layer4.h
@@ -5,7 +5,7 @@
  *
  * Part:        layer4.c include file.
  *
- * Version:     $Id: layer4.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: layer4.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include "scheduler.h"
 
 enum connect_result {
-  connect_error,
-  connect_success,
-  connect_in_progress,
-  connect_timeout
+       connect_error,
+       connect_success,
+       connect_in_progress,
+       connect_timeout
 };
 
 /* Prototypes defs */
@@ -47,14 +47,11 @@ extern enum connect_result
 tcp_connect(int fd, uint32_t, uint16_t);
 
 extern enum connect_result
-tcp_socket_state(int, thread *
-                    , uint32_t
-                    , uint16_t
-                    , int (*func) (struct _thread *));
+tcp_socket_state(int, thread *, uint32_t, uint16_t,
+                int (*func) (struct _thread *));
 
 extern void
 tcp_connection_state(int, enum connect_result
-                        , thread *
-                        , int (*func) (struct _thread *)
-                        , int);
+                    , thread *, int (*func) (struct _thread *)
+                    , int);
 #endif
similarity index 83%
rename from list.h
rename to keepalived/include/list.h
index c141a54..3d826cf 100644 (file)
--- a/list.h
@@ -5,7 +5,7 @@
  * 
  * Part:        list.c include file.
  *  
- * Version:     $Id: list.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: list.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
  *              2 of the License, or (at your option) any later version.
  */
 
-
 #ifndef _LIST_H
 #define _LIST_H
 
 /* list definition */
-typedef struct _element        *element;
-typedef struct _list   *list;
+typedef struct _element *element;
+typedef struct _list *list;
 
 struct _element {
-  struct _element *next;
-  struct _element *prev;
-  void *data;
+       struct _element *next;
+       struct _element *prev;
+       void *data;
 };
 
 struct _list {
-  struct _element *head;
-  struct _element *tail;
-  unsigned int count;
-  void (*free) (void *);
-  void (*dump) (void *);
+       struct _element *head;
+       struct _element *tail;
+       unsigned int count;
+       void (*free) (void *);
+       void (*dump) (void *);
 };
 
 /* utility macro */
similarity index 90%
rename from main.h
rename to keepalived/include/main.h
index 3b75db4..797586b 100644 (file)
--- a/main.h
@@ -5,7 +5,7 @@
  *
  * Part:        Main program include file.
  *
- * Version:     $Id: main.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: main.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -50,16 +50,16 @@ data *conf_data;
 
 /* extern prototypes */
 #ifdef _WITH_LVS_
-  extern void clear_ssl(SSL_DATA *ssl);
-  extern int init_ssl_ctx(void);
+extern void clear_ssl(SSL_DATA * ssl);
+extern int init_ssl_ctx(void);
 #endif
 extern void register_vrrp_thread(void);
 
 /* Build version */
 #define PROG    "Keepalived"
 
-#define VERSION_CODE 0x000604
-#define DATE_CODE    0x190602
+#define VERSION_CODE 0x000606
+#define DATE_CODE    0x030702
 
 #define KEEPALIVED_VERSION(version)    \
        (version >> 16) & 0xFF,         \
similarity index 94%
rename from memory.h
rename to keepalived/include/memory.h
index 87e477c..36b1828 100644 (file)
--- a/memory.h
@@ -5,7 +5,7 @@
  *
  * Part:        memory.c include file.
  *
- * Version:     $Id: memory.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: memory.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Jan Holmberg, <jan@artech.net>
@@ -52,7 +52,7 @@ extern void xfree(void *p);
 
 /* Memory debug prototypes defs */
 extern char *keepalived_malloc(unsigned long, char *, char *, int);
-extern int keepalived_free(void *, char *, char*, int);
+extern int keepalived_free(void *, char *, char *, int);
 extern void *keepalived_realloc(void *, unsigned long, char *, char *, int);
 extern void keepalived_free_final(void);
 
similarity index 88%
rename from parser.h
rename to keepalived/include/parser.h
index bd995eb..e8771c2 100644 (file)
--- a/parser.h
@@ -5,7 +5,7 @@
  * 
  * Part:        cfreader.c include file.
  *  
- * Version:     $Id: parser.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: parser.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 
 /* ketword definition */
 struct keyword {
-  char *string;
-  void (*handler) (vector);
-  vector sub;
+       char *string;
+       void (*handler) (vector);
+       vector sub;
 };
 
-
 /* Prototypes */
 extern void init_data(char *conf_file);
-extern void install_keyword(char *string, void (*handler)(vector));
+extern void install_keyword(char *string, void (*handler) (vector));
 extern void install_sublevel(void);
 extern void install_sublevel_end(void);
 extern void *set_value(vector strvec);
similarity index 95%
rename from pidfile.h
rename to keepalived/include/pidfile.h
index 1fc4ea7..d4dc200 100644 (file)
--- a/pidfile.h
@@ -5,7 +5,7 @@
  *
  * Part:        pidfile.c include file.
  *
- * Version:     $Id: pidfile.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: pidfile.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
similarity index 54%
rename from scheduler.h
rename to keepalived/include/scheduler.h
index 0608b2b..a653173 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        scheduler.c include file.
  *
- * Version:     $Id: scheduler.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: scheduler.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 
 /* Thread itself. */
 typedef struct _thread {
-  unsigned long id;
-  unsigned char type;                  /* thread type */
-  struct _thread *next;                        /* next pointer of the thread */
-  struct _thread *prev;                        /* previous pointer of the thread */
-  struct _thread_master *master;       /* pointer to the struct thread_master. */
-  int (*func) (struct _thread *);      /* event function */
-  void *arg;                           /* event argument */
-  TIMEVAL sands;                       /* rest of time sands value. */
-  union {
-    int val;                           /* second argument of the event. */
-    int fd;                            /* file descriptor in case of read/write. */
-  } u;
+       unsigned long id;
+       unsigned char type;             /* thread type */
+       struct _thread *next;           /* next pointer of the thread */
+       struct _thread *prev;           /* previous pointer of the thread */
+       struct _thread_master *master;  /* pointer to the struct thread_master. */
+       int (*func) (struct _thread *); /* event function */
+       void *arg;                      /* event argument */
+       TIMEVAL sands;                  /* rest of time sands value. */
+       union {
+               int val;                /* second argument of the event. */
+               int fd;                 /* file descriptor in case of read/write. */
+       } u;
 } thread;
 
 /* Linked list of thread. */
 typedef struct _thread_list {
-  thread *head;
-  thread *tail;
-  int count;
+       thread *head;
+       thread *tail;
+       int count;
 } thread_list;
 
 /* Master of the theads. */
 typedef struct _thread_master {
-  thread_list read;
-  thread_list write;
-  thread_list timer;
-  thread_list event;
-  thread_list ready;
-  thread_list unuse;
-  fd_set readfd;
-  fd_set writefd;
-  fd_set exceptfd;
-  unsigned long alloc;
+       thread_list read;
+       thread_list write;
+       thread_list timer;
+       thread_list event;
+       thread_list ready;
+       thread_list unuse;
+       fd_set readfd;
+       fd_set writefd;
+       fd_set exceptfd;
+       unsigned long alloc;
 } thread_master;
 
 /* Thread types. */
@@ -89,29 +89,19 @@ typedef struct _thread_master {
 
 /* Prototypes. */
 thread_master *thread_make_master(void);
-thread *thread_add_terminate_event(thread_master *m);
-void thread_destroy_master(thread_master *m);
-thread *thread_add_read(thread_master *m
-                       , int (*func)(thread *)
-                       , void *arg
-                       , int fd
-                       , long timeout);
-thread *thread_add_write(thread_master *m
-                        , int (*func)(thread *)
-                        , void *arg
-                        , int fd
-                        , long timeout);
-thread *thread_add_timer(thread_master *m
-                        , int (*func)(thread *)
-                        , void *arg
-                        , long timer);
-thread *thread_add_event(thread_master *m
-                        , int (*func)(thread *)
-                        , void *arg
-                        , int val);
-void thread_cancel(thread *thread);
-void thread_cancel_event(thread_master *m, void *arg);
-thread *thread_fetch(thread_master *m, thread *fetch);
-void thread_call(thread *thread);
+thread *thread_add_terminate_event(thread_master * m);
+void thread_destroy_master(thread_master * m);
+thread *thread_add_read(thread_master * m, int (*func) (thread *)
+                       , void *arg, int fd, long timeout);
+thread *thread_add_write(thread_master * m, int (*func) (thread *)
+                        , void *arg, int fd, long timeout);
+thread *thread_add_timer(thread_master * m, int (*func) (thread *)
+                        , void *arg, long timer);
+thread *thread_add_event(thread_master * m, int (*func) (thread *)
+                        , void *arg, int val);
+void thread_cancel(thread * thread);
+void thread_cancel_event(thread_master * m, void *arg);
+thread *thread_fetch(thread_master * m, thread * fetch);
+void thread_call(thread * thread);
 
 #endif
similarity index 81%
rename from smtp.h
rename to keepalived/include/smtp.h
index 71201ab..e156214 100644 (file)
--- a/smtp.h
@@ -5,7 +5,7 @@
  *
  * Part:        smtp.c include file.
  *
- * Version:     $Id: smtp.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: smtp.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 
 /* command stage */
 enum smtp_cmd {
-  CONNECTION,
-  HELO,
-  MAIL,
-  RCPT,
-  DATA,
-  BODY,
-  QUIT,
-  ERROR
+       CONNECTION,
+       HELO,
+       MAIL,
+       RCPT,
+       DATA,
+       BODY,
+       QUIT,
+       ERROR
 };
 
 /* SMTP thread argument structure */
@@ -56,12 +56,12 @@ enum smtp_cmd {
 #define MAX_BODY_LENGTH    512
 
 typedef struct _smtp_thread_arg {
-  enum smtp_cmd stage;
-  int email_it;
-  char *subject;
-  char *body;
-  char *buffer;
-  long buflen;
+       enum smtp_cmd stage;
+       int email_it;
+       char *subject;
+       char *body;
+       char *buffer;
+       long buflen;
 } smtp_thread_arg;
 
 /* Smtp command string processing */
@@ -75,9 +75,6 @@ typedef struct _smtp_thread_arg {
 #define SMTP_QUIT_CMD    "QUIT\r\n"
 
 /* Prototypes defs */
-extern void smtp_alert(thread_master *
-                       , real_server *
-                       , vrrp_rt *
-                       , const char *
-                       , const char *);
+extern void smtp_alert(thread_master *, real_server *, vrrp_rt *, const char *,
+                      const char *);
 #endif
similarity index 96%
rename from timer.h
rename to keepalived/include/timer.h
index 539b3d5..66a848e 100644 (file)
--- a/timer.h
@@ -5,7 +5,7 @@
  * 
  * Part:        timer.c include file.
  *  
- * Version:     $Id: timer.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: timer.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
similarity index 82%
rename from utils.h
rename to keepalived/include/utils.h
index bd8d51c..5defa89 100644 (file)
--- a/utils.h
@@ -5,7 +5,7 @@
  *
  * Part:        utils.h include file.
  *
- * Version:     $Id: utils.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: utils.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
 
+/* Global debugging logging facilities */
+#ifdef _DEBUG_
+#define DBG(fmt, msg...) syslog(LOG_DEBUG, fmt, ## msg)
+#else
+#define DBG(fmt, msg...)
+#endif
+
 /* Prototypes defs */
 extern void print_buffer(int count, char *buff);
 extern char *inet_ntop2(uint32_t ip);
 extern char *inet_ntoa2(uint32_t ip, char *buf);
 extern uint8_t inet_stom(char *addr);
-extern int inet_ston(const char* addr, uint32_t *dst);
+extern int inet_ston(const char *addr, uint32_t * dst);
 
 #endif
similarity index 93%
rename from vector.h
rename to keepalived/include/vector.h
index 2b84d96..f9f3c4b 100644 (file)
--- a/vector.h
@@ -5,7 +5,7 @@
  * 
  * Part:        vector.c include file.
  *  
- * Version:     $Id: vector.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: vector.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
  *              2 of the License, or (at your option) any later version.
  */
 
-
 #ifndef _VECTOR_H
 #define _VECTOR_H
 
 /* vector definition */
 struct _vector {
-  unsigned int allocated;
-  void **slot;
+       unsigned int allocated;
+       void **slot;
 };
 typedef struct _vector *vector;
 
similarity index 53%
rename from vrrp.h
rename to keepalived/include/vrrp.h
index fef1d92..47c29ea 100644 (file)
--- a/vrrp.h
@@ -6,7 +6,7 @@
  *
  * Part:        vrrp.c program include file.
  *
- * Version:     $Id: vrrp.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: vrrp.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include "utils.h"
 #include "vector.h"
 
-typedef struct {       /* rfc2338.5.1 */
-       uint8_t         vers_type;      /* 0-3=type, 4-7=version */
-       uint8_t         vrid;           /* virtual router id */
-       uint8_t         priority;       /* router priority */
-       uint8_t         naddr;          /* address counter */
-       uint8_t         auth_type;      /* authentification type */
-       uint8_t         adver_int;      /* advertissement interval(in sec) */
-       uint16_t        chksum;         /* checksum (ip-like one) */
+typedef struct {               /* rfc2338.5.1 */
+       uint8_t vers_type;      /* 0-3=type, 4-7=version */
+       uint8_t vrid;           /* virtual router id */
+       uint8_t priority;       /* router priority */
+       uint8_t naddr;          /* address counter */
+       uint8_t auth_type;      /* authentification type */
+       uint8_t adver_int;      /* advertissement interval(in sec) */
+       uint16_t chksum;        /* checksum (ip-like one) */
 /* here <naddr> ip addresses */
 /* here authentification infos */
 } vrrp_pkt;
 
 /* protocol constants */
 #define INADDR_VRRP_GROUP 0xe0000012   /* multicast addr - rfc2338.5.2.2 */
-#define VRRP_IP_TTL    255     /* in and out pkt ttl -- rfc2338.5.2.3 */
-#define IPPROTO_VRRP   112     /* IP protocol number -- rfc2338.5.2.4*/
-#define VRRP_VERSION   2       /* current version -- rfc2338.5.3.1 */
-#define VRRP_PKT_ADVERT        1       /* packet type -- rfc2338.5.3.2 */
-#define VRRP_PRIO_OWNER        255     /* priority of the ip owner -- rfc2338.5.3.4 */
-#define VRRP_PRIO_DFL  100     /* default priority -- rfc2338.5.3.4 */
-#define VRRP_PRIO_STOP 0       /* priority to stop -- rfc2338.5.3.4 */
-#define VRRP_AUTH_NONE 0       /* no authentification -- rfc2338.5.3.6 */
-#define VRRP_AUTH_PASS 1       /* password authentification -- rfc2338.5.3.6 */
-#define VRRP_AUTH_AH   2       /* AH(IPSec) authentification - rfc2338.5.3.6 */
-#define VRRP_ADVER_DFL 1       /* advert. interval (in sec) -- rfc2338.5.3.7 */
-#define VRRP_PREEMPT_DFL 1     /* rfc2338.6.1.2.Preempt_Mode */
-
+#define VRRP_IP_TTL    255             /* in and out pkt ttl -- rfc2338.5.2.3 */
+#define IPPROTO_VRRP   112             /* IP protocol number -- rfc2338.5.2.4 */
+#define VRRP_VERSION   2               /* current version -- rfc2338.5.3.1 */
+#define VRRP_PKT_ADVERT        1               /* packet type -- rfc2338.5.3.2 */
+#define VRRP_PRIO_OWNER        255             /* priority of the ip owner -- rfc2338.5.3.4 */
+#define VRRP_PRIO_DFL  100             /* default priority -- rfc2338.5.3.4 */
+#define VRRP_PRIO_STOP 0               /* priority to stop -- rfc2338.5.3.4 */
+#define VRRP_AUTH_NONE 0               /* no authentification -- rfc2338.5.3.6 */
+#define VRRP_AUTH_PASS 1               /* password authentification -- rfc2338.5.3.6 */
+#define VRRP_AUTH_AH   2               /* AH(IPSec) authentification - rfc2338.5.3.6 */
+#define VRRP_ADVER_DFL 1               /* advert. interval (in sec) -- rfc2338.5.3.7 */
+#define VRRP_PREEMPT_DFL 1             /* rfc2338.6.1.2.Preempt_Mode */
 
 /*
  * parameters per vrrp sync group. A vrrp_sync_group is a set
  * of VRRP instances that need to be state sync together.
  */
 typedef struct _vrrp_sgroup {
-       char    *gname;         /* Group name */
-       vector  iname;          /* Set of VRRP instances in this group */
-       int     state;          /* current stable state */
+       char *gname;            /* Group name */
+       vector iname;           /* Set of VRRP instances in this group */
+       int state;              /* current stable state */
 
        /* State transition notification */
-       int     notify_exec;
-       char    *script_backup;
-       char    *script_master;
-       char    *script_fault;
+       int notify_exec;
+       char *script_backup;
+       char *script_master;
+       char *script_fault;
 } vrrp_sgroup;
 
-
 /* parameters per virtual router -- rfc2338.6.1.2 */
 typedef struct {
-       uint32_t        addr;   /* the ip address */
-       uint8_t         mask;   /* the ip address CIDR netmask */
-       int             set;    /* TRUE if addr is set */
+       uint32_t addr;          /* the ip address */
+       uint8_t mask;           /* the ip address CIDR netmask */
+       int set;                /* TRUE if addr is set */
 } vip_addr;
 
 typedef struct _vrrp_rt {
-       char    *iname;         /* Instance Name */
+       char *iname;            /* Instance Name */
        vrrp_sgroup *sync;
        interface *ifp;         /* Interface we belong to */
-       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
-                                 * => eth0 for example.
-                                 */
-       int     vrid;           /* virtual id. from 1(!) to 255 */
-       int     priority;       /* priority value */
-       int     naddr;          /* number of ip addresses */
-       int     vipset;         /* All the vips are set ? */
+       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
+                                * => eth0 for example.
+                                */
+       int vrid;               /* virtual id. from 1(!) to 255 */
+       int priority;           /* priority value */
+       int naddr;              /* number of ip addresses */
+       int vipset;             /* All the vips are set ? */
        vip_addr *vaddr;        /* point on the ip address array */
-       int     neaddr;         /* number of excluded ip addresses */
+       int neaddr;             /* number of excluded ip addresses */
        vip_addr *evaddr;       /* list of protocol excluded VIPs.
-                                * Those VIPs will not be presents into the
-                                 * VRRP adverts
-                                 */
-       int     adver_int;      /* delay between advertisements(in sec) */      
-       char    hwaddr[6];      /* VMAC -- rfc2338.7.3 */
-       int     preempt;        /* true if a higher prio preempt a lower one */
-       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     debug;          /* Debug level 0-4 */
+                                * Those VIPs will not be presents into the
+                                * VRRP adverts
+                                */
+       int adver_int;          /* delay between advertisements(in sec) */
+       char hwaddr[6];         /* VMAC -- rfc2338.7.3 */
+       int preempt;            /* true if a higher prio preempt a lower one */
+       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 debug;              /* Debug level 0-4 */
 
        /* State transition notification */
-       int     smtp_alert;
-       int     notify_exec;
-       char    *script_backup;
-       char    *script_master;
-       char    *script_fault;
+       int smtp_alert;
+       int notify_exec;
+       char *script_backup;
+       char *script_master;
+       char *script_fault;
 
        /* rfc2336.6.2 */
-       uint32_t        ms_down_timer;
-       struct timeval  sands;
+       uint32_t ms_down_timer;
+       struct timeval sands;
 
        /* Authentication data */
-       int             auth_type;      /* authentification type. VRRP_AUTH_* */
-       uint8_t         auth_data[8];   /* authentification data */
+       int auth_type;          /* authentification type. VRRP_AUTH_* */
+       uint8_t auth_data[8];   /* authentification data */
 
        /*
         * To have my own ip_id creates collision with kernel ip->id
@@ -144,7 +142,7 @@ typedef struct _vrrp_rt {
         * This packet isnt routed, i can check the outgoing MTU
         * to warn the user only if the outoing mtu is too small
         */
-       int             ip_id;
+       int ip_id;
 
        /* IPSEC AH counter def --rfc2402.3.3.2 */
        seq_counter *ipsecah_counter;
@@ -169,7 +167,7 @@ typedef struct _vrrp_rt {
 #define VRRP_PACKET_KO       1
 #define VRRP_PACKET_DROP     2
 #define VRRP_PACKET_NULL     3
-#define VRRP_PACKET_OTHER    4      /* Muliple VRRP on LAN, Identify "other" VRRP */
+#define VRRP_PACKET_OTHER    4 /* Muliple VRRP on LAN, Identify "other" VRRP */
 
 /* VRRP Packet fixed lenght */
 #define VRRP_MAX_VIP           20
@@ -183,7 +181,7 @@ typedef struct _vrrp_rt {
 #define VRRP_IS_BAD_ADVERT_INT(d)      ((d)<1)
 #define VRRP_IS_BAD_DEBUG_INT(d)       ((d)<0 || (d)>4)
 
-#define VRRP_TIMER_SKEW(srv)   ((256-(srv)->priority)*TIMER_HZ/256) 
+#define VRRP_TIMER_SKEW(srv)   ((256-(srv)->priority)*TIMER_HZ/256)
 #define VRRP_VIP_ISSET(V)      ((V)->vipset)
 
 #define VRRP_MIN(a, b) ((a) < (b)?(a):(b))
@@ -193,16 +191,16 @@ typedef struct _vrrp_rt {
 
 /* prototypes */
 extern int open_vrrp_socket(const int proto, const int index);
-extern void new_vrrp_socket(vrrp_rt *vrrp);
-extern void close_vrrp_socket(vrrp_rt *vrrp);
-extern void vrrp_send_gratuitous_arp(vrrp_rt *vrrp);
-extern int vrrp_send_adv(vrrp_rt *vrrp, int prio);
-extern int vrrp_state_fault_rx(vrrp_rt *vrrp, char *buf, int buflen);
-extern int vrrp_state_master_rx(vrrp_rt *vrrp, char *buf, int buflen);
-extern void vrrp_state_master_tx(vrrp_rt *vrrp, const int prio);
-extern void vrrp_state_backup(vrrp_rt *vrrp, char *buf, int buflen);
-extern void vrrp_state_goto_master(vrrp_rt *vrrp);
-extern void vrrp_state_leave_master(vrrp_rt *vrrp);
+extern void new_vrrp_socket(vrrp_rt * vrrp);
+extern void close_vrrp_socket(vrrp_rt * vrrp);
+extern void vrrp_send_gratuitous_arp(vrrp_rt * vrrp);
+extern int vrrp_send_adv(vrrp_rt * vrrp, int prio);
+extern int vrrp_state_fault_rx(vrrp_rt * vrrp, char *buf, int buflen);
+extern int vrrp_state_master_rx(vrrp_rt * vrrp, char *buf, int buflen);
+extern void vrrp_state_master_tx(vrrp_rt * vrrp, const int prio);
+extern void vrrp_state_backup(vrrp_rt * vrrp, char *buf, int buflen);
+extern void vrrp_state_goto_master(vrrp_rt * vrrp);
+extern void vrrp_state_leave_master(vrrp_rt * vrrp);
 extern int vrrp_ipsecah_len(void);
 extern int vrrp_complete_init(void);
 extern void shutdown_vrrp_instances(void);
similarity index 65%
rename from vrrp_if.h
rename to keepalived/include/vrrp_if.h
index 5d2e64d..9860e9d 100644 (file)
--- a/vrrp_if.h
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_if.c include file.
  *
- * Version:     $Id: vrrp_if.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: vrrp_if.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 
 /* types definition */
 #ifndef SIOCETHTOOL
-  #define SIOCETHTOOL     0x8946
+#define SIOCETHTOOL     0x8946
 #endif
 #ifndef SIOCGMIIPHY
-  #define SIOCGMIIPHY (SIOCDEVPRIVATE)            /* Get the PHY in use. */
-  #define SIOCGMIIREG (SIOCDEVPRIVATE+1)          /* Read a PHY register. */
-  #define SIOCSMIIREG (SIOCDEVPRIVATE+2)          /* Write a PHY register. */
-  #define SIOCGPARAMS (SIOCDEVPRIVATE+3)          /* Read operational parameters. */
-  #define SIOCSPARAMS (SIOCDEVPRIVATE+4)          /* Set operational parameters. */
+#define SIOCGMIIPHY (SIOCDEVPRIVATE)   /* Get the PHY in use. */
+#define SIOCGMIIREG (SIOCDEVPRIVATE+1) /* Read a PHY register. */
+#define SIOCSMIIREG (SIOCDEVPRIVATE+2) /* Write a PHY register. */
+#define SIOCGPARAMS (SIOCDEVPRIVATE+3) /* Read operational parameters. */
+#define SIOCSPARAMS (SIOCDEVPRIVATE+4) /* Set operational parameters. */
 #endif
 #define LINK_UP   1
 #define LINK_DOWN 0
-#define IF_NAMESIZ    20 /* Max interface lenght size */
-#define IF_HWADDR_MAX 20 /* Max MAC address length size */
+#define IF_NAMESIZ    20       /* Max interface lenght size */
+#define IF_HWADDR_MAX 20       /* Max MAC address length size */
 #define ARPHRD_ETHER 1
 #define ARPHRD_LOOPBACK 772
 #define POLLING_DELAY 1
 
 /* Interface structure definition */
 typedef struct _interface {
-  char ifname[IF_NAMESIZ + 1];         /* Interface name */
-  unsigned int ifindex;                        /* Interface index */
-  uint32_t address;                    /* Interface main primary IP address */
-  unsigned long flags;                 /* flags */
-  unsigned int mtu;                    /* MTU for this interface */
-  unsigned short hw_type;              /* Type of hardware address */
-  u_char hw_addr[IF_HWADDR_MAX];       /* MAC address */
-  int hw_addr_len;                     /* MAC addresss length */
-  int lb_type;                         /* Interface regs selection */
-  int linkbeat;                                /* LinkBeat from MII BMSR req */
+       char ifname[IF_NAMESIZ + 1];    /* Interface name */
+       unsigned int ifindex;           /* Interface index */
+       uint32_t address;               /* Interface main primary IP address */
+       unsigned long flags;            /* flags */
+       unsigned int mtu;               /* MTU for this interface */
+       unsigned short hw_type;         /* Type of hardware address */
+       u_char hw_addr[IF_HWADDR_MAX];  /* MAC address */
+       int hw_addr_len;                /* MAC addresss length */
+       int lb_type;                    /* Interface regs selection */
+       int linkbeat;                   /* LinkBeat from MII BMSR req */
 } interface;
 
 /* Global interface queue */
@@ -86,12 +86,12 @@ list if_queue;
 /* prototypes */
 extern interface *if_get_by_ifindex(const int ifindex);
 extern interface *if_get_by_ifname(const char *ifname);
-extern int if_linkbeat(const interface *ifp);
+extern int if_linkbeat(const interface * ifp);
 extern int if_mii_probe(const char *ifname);
 extern int if_ethtool_probe(const char *ifname);
 extern void if_mii_poller_init(void);
-extern void if_add_queue(interface *ifp);
-extern int if_monitor_thread(thread *thread);
+extern void if_add_queue(interface * ifp);
+extern int if_monitor_thread(thread * thread);
 extern void init_interface_queue(void);
 extern void free_interface_queue(void);
 extern void dump_if(void *data);
similarity index 82%
rename from vrrp_ipaddress.h
rename to keepalived/include/vrrp_ipaddress.h
index 856dc20..c055b13 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_ipaddress.c include file.
  *
- * Version:     $Id: vrrp_ipaddress.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: vrrp_ipaddress.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -35,9 +35,7 @@
 #define VRRP_IPADDRESS_ADD 1
 
 /* prototypes */
-extern int netlink_address_ipv4(int ifindex, uint32_t addr
-                                           , uint8_t mask
-                                           , int cmd);
+extern int netlink_address_ipv4(int ifindex, uint32_t addr, uint8_t mask,
+                               int cmd);
 
 #endif
-
similarity index 50%
rename from vrrp_ipsecah.h
rename to keepalived/include/vrrp_ipsecah.h
index 5087c74..420d04a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_ipsecah.c include file.
  * 
- * Version:     $Id: vrrp_ipsecah.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: vrrp_ipsecah.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
 #include <stdint.h>
 
 /* Predefined values */
-#define HMAC_MD5_TRUNC 0x0C  /* MD5 digest truncate value : 96-bit
-                                -- rfc2403.2 & rfc2104.5 */
-#define IPSEC_AH_PLEN  0x04  /* Const for a 96-bit auth value :
-                                Computed in 32-bit words minus 2
-                                => (HMAC_MD5_TRUNC*8+3*32)/32 - 2
-                                -- rfc2402.2.2 */
-#define IPPROTO_IPSEC_AH 51 /* IP protocol number -- rfc2402.2 */
+#define HMAC_MD5_TRUNC 0x0C    /* MD5 digest truncate value : 96-bit
+                                  -- rfc2403.2 & rfc2104.5 */
+#define IPSEC_AH_PLEN  0x04    /* Const for a 96-bit auth value :
+                                  Computed in 32-bit words minus 2
+                                  => (HMAC_MD5_TRUNC*8+3*32)/32 - 2
+                                  -- rfc2402.2.2 */
+#define IPPROTO_IPSEC_AH 51    /* IP protocol number -- rfc2402.2 */
 
-typedef struct {            /* rfc2402.2 */
-  uint8_t  next_header;     /* Next header field */
-  uint8_t  payload_len;     /* Payload Lenght */
-  uint16_t reserved;        /* Reserved field */
-  uint32_t spi;             /* Security Parameter Index */
-  uint32_t seq_number;      /* Sequence number */
-  uint32_t auth_data[3];    /* Authentication data 128-bit MD5 digest trucated
-                               => HMAC_MD5_TRUNC*8/32 */
+typedef struct {               /* rfc2402.2 */
+       uint8_t next_header;    /* Next header field */
+       uint8_t payload_len;    /* Payload Lenght */
+       uint16_t reserved;      /* Reserved field */
+       uint32_t spi;           /* Security Parameter Index */
+       uint32_t seq_number;    /* Sequence number */
+       uint32_t auth_data[3];  /* Authentication data 128-bit MD5 digest trucated
+                                  => HMAC_MD5_TRUNC*8/32 */
 } ipsec_ah;
 
-typedef struct {          /* rfc2402.3.3.3.1.1.1 */
-  u_int8_t  tos;
-  u_int16_t id;
-  u_int16_t frag_off;
-  u_int16_t check;
-} ICV_mutable_fields;    /* We need to zero this fields to compute the ICV */
+typedef struct {               /* rfc2402.3.3.3.1.1.1 */
+       u_int8_t tos;
+       u_int16_t id;
+       u_int16_t frag_off;
+       u_int16_t check;
+} ICV_mutable_fields;          /* We need to zero this fields to compute the ICV */
 
 typedef struct {
-  int cycle;
-  uint32_t seq_number;
+       int cycle;
+       uint32_t seq_number;
 } seq_counter;
 
-
 extern void hmac_md5(unsigned char *buffer, int buffer_len,
-                     unsigned char *key, int key_len, unsigned char *digest);
+                    unsigned char *key, int key_len, unsigned char *digest);
 
 #endif
similarity index 87%
rename from vrrp_netlink.h
rename to keepalived/include/vrrp_netlink.h
index 78aee09..f22208a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_netlink.c include file.
  *
- * Version:     $Id: vrrp_netlink.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: vrrp_netlink.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -26,7 +26,7 @@
 /* Hack for GNU libc version 2. */
 #ifndef MSG_TRUNC
 #define MSG_TRUNC      0x20
-#endif /* MSG_TRUNC */
+#endif                         /* MSG_TRUNC */
 
 /* global includes */
 #include <asm/types.h>
@@ -35,9 +35,9 @@
 
 /* types definitions */
 struct nl_handle {
-  int fd;
-  struct sockaddr_nl snl;
-  __u32 seq;
+       int fd;
+       struct sockaddr_nl snl;
+       __u32 seq;
 };
 
 /* Define types */
@@ -47,10 +47,11 @@ struct nl_handle {
 struct nl_handle nl_kernel;
 
 /* prototypes */
-extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen);
+extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data,
+                    int alen);
 extern int netlink_socket(struct nl_handle *nl, unsigned long groups);
 extern int netlink_close(struct nl_handle *nl);
-extern int netlink_talk (struct nl_handle *nl, struct nlmsghdr *n);
+extern int netlink_talk(struct nl_handle *nl, struct nlmsghdr *n);
 extern int netlink_interface_lookup(void);
 extern int netlink_interface_refresh(void);
 extern void kernel_netlink_init(void);
similarity index 85%
rename from vrrp_notify.h
rename to keepalived/include/vrrp_notify.h
index e7a27e0..81248bd 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Part:        vrrp_notify.c include file.
  *
- * Version:     $Id: vrrp_notify.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: vrrp_notify.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -27,7 +27,7 @@
 /* local include */
 #include "vrrp.h"
 
-extern int notify_instance_exec(vrrp_rt *vrrp, int state);
-extern int notify_group_exec(vrrp_sgroup *vgroup, int state);
+extern int notify_instance_exec(vrrp_rt * vrrp, int state);
+extern int notify_group_exec(vrrp_sgroup * vgroup, int state);
 
 #endif
similarity index 76%
rename from vrrp_scheduler.h
rename to keepalived/include/vrrp_scheduler.h
index ff7fbe3..f8984d6 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_scheduler.c include file.
  * 
- * Version:     $Id: vrrp_scheduler.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: vrrp_scheduler.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
  * physical interface.
  */
 typedef struct {
-  int ifindex;
-  int proto;
-  int fd;
+       int ifindex;
+       int proto;
+       int fd;
 } sock;
 
 /* VRRP FSM Macro */
-#define VRRP_FSM_READ_TO(V) \
-do { \
-  if ((*(FSM[(V)->state].read_to))) \
-    (*(FSM[(V)->state].read_to)) (V); \
+#define VRRP_FSM_READ_TO(V)                    \
+do {                                           \
+  if ((*(VRRP_FSM[(V)->state].read_to)))       \
+    (*(VRRP_FSM[(V)->state].read_to)) (V);     \
 } while (0)
 
-#define VRRP_FSM_READ(V, B, L) \
-do { \
-  if ((*(FSM[(V)->state].read))) \
-    (*(FSM[(V)->state].read)) (V, B, L); \
+#define VRRP_FSM_READ(V, B, L)                 \
+do {                                           \
+  if ((*(VRRP_FSM[(V)->state].read)))          \
+    (*(VRRP_FSM[(V)->state].read)) (V, B, L);  \
 } while (0)
 
 /* extern prototypes */
-extern int vrrp_read_dispatcher_thread(thread *thread);
+extern int vrrp_read_dispatcher_thread(thread * thread);
 
 #endif
similarity index 82%
rename from vrrp_sync.h
rename to keepalived/include/vrrp_sync.h
index 0bfeed7..8c5e5ff 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_sync.c include file.
  * 
- * Version:     $Id: vrrp_sync.h,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: vrrp_sync.h,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
 /* local include */
 #include "vrrp.h"
 
-
 /* MACRO definition */
 #define GROUP_STATE(G) ((G)->state)
 #define GROUP_NAME(G)  ((G)->gname)
 
 /* extern prototypes */
 extern vrrp_sgroup *vrrp_get_sync_group(char *iname);
-extern int vrrp_sync_group_up(vrrp_sgroup *vgroup);
-extern int vrrp_sync_leave_fault(vrrp_rt *vrrp);
-extern void vrrp_sync_read_to(vrrp_rt *vrrp, int prev_state);
-extern void vrrp_sync_read(vrrp_rt *vrrp, int prev_state);
+extern int vrrp_sync_group_up(vrrp_sgroup * vgroup);
+extern int vrrp_sync_leave_fault(vrrp_rt * vrrp);
+extern void vrrp_sync_read_to(vrrp_rt * vrrp, int prev_state);
+extern void vrrp_sync_read(vrrp_rt * vrrp, int prev_state);
 
 #endif
similarity index 53%
rename from libipfwc/Makefile
rename to keepalived/libipfwc/Makefile.in
index bfa78f5..3d67ab3 100644 (file)
@@ -1,8 +1,11 @@
 # Makefile to make libipfwc.
 
-CC     = gcc
-COPTS   = -g -O
-CFLAGS = -Wall -Wunused $(COPTS)
+CC     = @CC@
+CFLAGS = @CFLAGS@ -Wall -Wunused
+
+export OBJS += libipfwc.a
+
+all: libipfwc.a
 
 libipfwc.a: libipfwc.a(libipfwc.o)
 
@@ -10,3 +13,6 @@ libipfwc.o: libipfwc.h ipfwc_kernel_headers.h
 
 clean:
        rm -f *.a *.o *~
+
+distclean: clean
+       rm -f Makefile
diff --git a/keepalived/libipfwc/ipfwc_kernel_headers.h b/keepalived/libipfwc/ipfwc_kernel_headers.h
new file mode 100644 (file)
index 0000000..b14a6db
--- /dev/null
@@ -0,0 +1,175 @@
+/* This is the userspace/kernel interface for Generic IP Chains,
+   required for libc6. */
+#ifndef _FWCHAINS_KERNEL_HEADERS_H
+#define _FWCHAINS_KERNEL_HEADERS_H
+
+#if defined(__GLIBC__) && __GLIBC__ == 2
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <net/if.h>
+#include <sys/types.h>
+
+typedef u_int64_t __u64;
+typedef u_int32_t __u32;
+typedef int32_t __s32;
+typedef u_int16_t __u16;
+typedef u_int8_t __u8;
+
+#else                          /* libc5 */
+#include <sys/socket.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/if.h>
+#include <linux/icmp.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#endif
+
+#define IP_FW_MAX_LABEL_LENGTH 8
+typedef char ip_chainlabel[IP_FW_MAX_LABEL_LENGTH + 1];
+
+struct ip_fw {
+       struct in_addr fw_src, fw_dst;  /* Source and destination IP addr */
+       struct in_addr fw_smsk, fw_dmsk;        /* Mask for src and dest IP addr */
+       __u32 fw_mark;          /* ID to stamp on packet */
+       __u16 fw_proto;         /* Protocol, 0 = ANY */
+       __u16 fw_flg;           /* Flags word */
+       __u16 fw_invflg;        /* Inverse flags */
+       __u16 fw_spts[2];       /* Source port range. */
+       __u16 fw_dpts[2];       /* Destination port range. */
+       __u16 fw_redirpt;       /* Port to redirect to. */
+       __u16 fw_outputsize;    /* Max amount to output to
+                                  NETLINK */
+       char fw_vianame[IFNAMSIZ];      /* name of interface "via" */
+       __u8 fw_tosand, fw_tosxor;      /* Revised packet priority */
+};
+
+struct ip_fwuser {
+       struct ip_fw ipfw;
+       ip_chainlabel label;
+};
+
+/* Values for "fw_flg" field .  */
+#define IP_FW_F_PRN    0x0001  /* Print packet if it matches */
+#define IP_FW_F_TCPSYN 0x0002  /* For tcp packets-check SYN only */
+#define IP_FW_F_FRAG   0x0004  /* Set if rule is a fragment rule */
+#define IP_FW_F_MARKABS        0x0008  /* Set the mark to fw_mark, not add. */
+#define IP_FW_F_WILDIF 0x0010  /* Need only match start of interface name. */
+#define IP_FW_F_NETLINK 0x0020 /* Redirect to netlink: 2.1.x only */
+#define IP_FW_F_MASK   0x003F  /* All possible flag bits mask   */
+
+/* Values for "fw_invflg" field. */
+#define IP_FW_INV_SRCIP 0x0001 /* Invert the sense of fw_src. */
+#define IP_FW_INV_DSTIP 0x0002 /* Invert the sense of fw_dst. */
+#define IP_FW_INV_PROTO 0x0004 /* Invert the sense of fw_proto. */
+#define IP_FW_INV_SRCPT 0x0008 /* Invert the sense of source ports. */
+#define IP_FW_INV_DSTPT 0x0010 /* Invert the sense of destination ports. */
+#define IP_FW_INV_VIA   0x0020 /* Invert the sense of fw_vianame. */
+#define IP_FW_INV_SYN   0x0040 /* Invert the sense of IP_FW_F_TCPSYN. */
+#define IP_FW_INV_FRAG  0x0080 /* Invert the sense of IP_FW_F_FRAG. */
+
+/*    
+ *     New IP firewall options for [gs]etsockopt at the RAW IP level.
+ *     Unlike BSD Linux inherits IP options so you don't have to use
+ * a raw socket for this. Instead we check rights in the calls.  */
+
+#define IP_FW_BASE_CTL         64      /* base for firewall socket options */
+
+#define IP_FW_APPEND           (IP_FW_BASE_CTL)        /* Takes ip_fwchange */
+#define IP_FW_REPLACE          (IP_FW_BASE_CTL+1)      /* Takes ip_fwnew */
+#define IP_FW_DELETE_NUM       (IP_FW_BASE_CTL+2)      /* Takes ip_fwdelnum */
+#define IP_FW_DELETE           (IP_FW_BASE_CTL+3)      /* Takes ip_fwchange */
+#define IP_FW_INSERT           (IP_FW_BASE_CTL+4)      /* Takes ip_fwnew */
+#define IP_FW_FLUSH            (IP_FW_BASE_CTL+5)      /* Takes ip_chainlabel */
+#define IP_FW_ZERO             (IP_FW_BASE_CTL+6)      /* Takes ip_chainlabel */
+#define IP_FW_CHECK            (IP_FW_BASE_CTL+7)      /* Takes ip_fwtest */
+#define IP_FW_MASQ_TIMEOUTS    (IP_FW_BASE_CTL+8)      /* Takes 3 ints */
+#define IP_FW_CREATECHAIN      (IP_FW_BASE_CTL+9)      /* Takes ip_chainlabel */
+#define IP_FW_DELETECHAIN      (IP_FW_BASE_CTL+10)     /* Takes ip_chainlabel */
+#define IP_FW_POLICY           (IP_FW_BASE_CTL+11)     /* Takes ip_fwpolicy */
+/* Masquerade controls */
+#define IP_FW_MASQ_INSERT      (IP_FW_BASE_CTL+12)
+#define IP_FW_MASQ_ADD         (IP_FW_BASE_CTL+13)
+#define IP_FW_MASQ_DEL         (IP_FW_BASE_CTL+14)
+#define IP_FW_MASQ_FLUSH       (IP_FW_BASE_CTL+15)
+
+/* Builtin chain labels */
+#define IP_FW_LABEL_FORWARD    "forward"
+#define IP_FW_LABEL_INPUT      "input"
+#define IP_FW_LABEL_OUTPUT     "output"
+
+/* Special targets */
+#define IP_FW_LABEL_MASQUERADE  "MASQ"
+#define IP_FW_LABEL_REDIRECT    "REDIRECT"
+#define IP_FW_LABEL_ACCEPT     "ACCEPT"
+#define IP_FW_LABEL_BLOCK      "DENY"
+#define IP_FW_LABEL_REJECT     "REJECT"
+#define IP_FW_LABEL_RETURN     "RETURN"
+
+/* Files in /proc/net */
+#define IP_FW_PROC_CHAINS      "ip_fwchains"
+#define IP_FW_PROC_CHAIN_NAMES "ip_fwnames"
+
+struct ip_fwpkt {
+       struct iphdr fwp_iph;   /* IP header */
+       union {
+               struct tcphdr fwp_tcph; /* TCP header or */
+               struct udphdr fwp_udph; /* UDP header */
+               struct icmphdr fwp_icmph;       /* ICMP header */
+       } fwp_protoh;
+       struct in_addr fwp_via; /* interface address */
+       char fwp_vianame[IFNAMSIZ];     /* interface name */
+};
+
+/* The argument to IP_FW_DELETE and IP_FW_APPEND */
+struct ip_fwchange {
+       struct ip_fwuser fwc_rule;
+       ip_chainlabel fwc_label;
+};
+
+/* The argument to IP_FW_CHECK. */
+struct ip_fwtest {
+       struct ip_fwpkt fwt_packet;     /* Packet to be tested */
+       ip_chainlabel fwt_label;        /* Block to start test in */
+};
+
+/* The argument to IP_FW_DELETE_NUM */
+struct ip_fwdelnum {
+       __u32 fwd_rulenum;
+       ip_chainlabel fwd_label;
+};
+
+/* The argument to IP_FW_REPLACE and IP_FW_INSERT */
+struct ip_fwnew {
+       __u32 fwn_rulenum;
+       struct ip_fwuser fwn_rule;
+       ip_chainlabel fwn_label;
+};
+
+/* The argument to IP_FW_POLICY */
+struct ip_fwpolicy {
+       ip_chainlabel fwp_policy;
+       ip_chainlabel fwp_label;
+};
+/*      
+ * timeouts for ip masquerading
+ */
+
+struct ip_fw_masq;
+
+/* Masquerading stuff */
+#define IP_FW_MASQCTL_MAX 256
+#define IP_MASQ_MOD_NMAX  32
+
+struct ip_fw_masqctl {
+       int mctl_action;
+       union {
+               struct {
+                       char name[IP_MASQ_MOD_NMAX];
+                       char data[1];
+               } mod;
+       } u;
+};
+#endif
similarity index 55%
rename from libipfwc/libipfwc.c
rename to keepalived/libipfwc/libipfwc.c
index e76726a..430ea3a 100644 (file)
@@ -30,16 +30,19 @@ static enum {
        IPFWC_REDIRECT
 } ipfwc_type;
 
-static void ipfwc_settype(const struct ip_fwuser *fw)
+static void
+ipfwc_settype(const struct ip_fwuser *fw)
 {
        if (strcmp(fw->label, "MASQ") == 0)
                ipfwc_type = IPFWC_MASQ;
        else if (strcmp(fw->label, "REDIRECT") == 0)
                ipfwc_type = IPFWC_REDIRECT;
-       else ipfwc_type = IPFWC_NORMAL;
+       else
+               ipfwc_type = IPFWC_NORMAL;
 }
 
-static int ipfwc_init()
+static int
+ipfwc_init()
 {
        ipfwc_fn = ipfwc_init;
        init = 1;
@@ -49,75 +52,83 @@ static int ipfwc_init()
 static int
 do_setsockopt(int cmd, const void *data, int length)
 {
-       return setsockopt(sockfd, IPPROTO_IP, cmd, (char *)data, length) != -1;
+       return setsockopt(sockfd, IPPROTO_IP, cmd, (char *) data, length) != -1;
 }
 
 /* Insert the entry `fw' in chain `chain' into position `rulenum'. */
-int ipfwc_insert_entry(const ip_chainlabel chain, 
-                       const struct ip_fwuser *fw, 
-                       unsigned int rulenum)
+int
+ipfwc_insert_entry(const ip_chainlabel chain,
+                  const struct ip_fwuser *fw, unsigned int rulenum)
 {
        struct ip_fwnew new = { rulenum, *fw, "" };
-       memcpy(new.fwn_label, chain, sizeof(new.fwn_label));
+       memcpy(new.fwn_label, chain, sizeof (new.fwn_label));
 
-       if (!init && !ipfwc_init()) return 0;
+       if (!init && !ipfwc_init())
+               return 0;
 
        ipfwc_fn = ipfwc_insert_entry;
        ipfwc_settype(fw);
-       return do_setsockopt(IP_FW_INSERT, &new, sizeof(new));
+       return do_setsockopt(IP_FW_INSERT, &new, sizeof (new));
 }
 
 /* Atomically replace rule `rulenum' in `chain' with `fw'. */
-int ipfwc_replace_entry(const ip_chainlabel chain, 
-                        const struct ip_fwuser *fw, 
-                        unsigned int rulenum)
+int
+ipfwc_replace_entry(const ip_chainlabel chain,
+                   const struct ip_fwuser *fw, unsigned int rulenum)
 {
        struct ip_fwnew new = { rulenum, *fw, "" };
-       memcpy(new.fwn_label, chain, sizeof(new.fwn_label));
+       memcpy(new.fwn_label, chain, sizeof (new.fwn_label));
 
-       if (!init && !ipfwc_init()) return 0;
+       if (!init && !ipfwc_init())
+               return 0;
 
        ipfwc_fn = ipfwc_replace_entry;
        ipfwc_settype(fw);
-       return do_setsockopt(IP_FW_REPLACE, &new, sizeof(new));
+       return do_setsockopt(IP_FW_REPLACE, &new, sizeof (new));
 }
 
 /* Append entry `fw' to chain `chain'.  Equivalent to insert with
    rulenum = length of chain. */
-int ipfwc_append_entry(const ip_chainlabel chain, const struct ip_fwuser *fw)
+int
+ipfwc_append_entry(const ip_chainlabel chain, const struct ip_fwuser *fw)
 {
        struct ip_fwchange new = { *fw, "" };
-       memcpy(new.fwc_label, chain, sizeof(new.fwc_label));
+       memcpy(new.fwc_label, chain, sizeof (new.fwc_label));
 
-       if (!init && !ipfwc_init()) return 0;
+       if (!init && !ipfwc_init())
+               return 0;
 
        ipfwc_fn = ipfwc_append_entry;
        ipfwc_settype(fw);
-       return do_setsockopt(IP_FW_APPEND, &new, sizeof(new));  
+       return do_setsockopt(IP_FW_APPEND, &new, sizeof (new));
 }
 
 /* Delete the first rule in `chain' which matches `fw'. */
-int ipfwc_delete_entry(const ip_chainlabel chain, const struct ip_fwuser *fw)
+int
+ipfwc_delete_entry(const ip_chainlabel chain, const struct ip_fwuser *fw)
 {
        struct ip_fwchange del = { *fw, "" };
-       memcpy(del.fwc_label, chain, sizeof(del.fwc_label));
+       memcpy(del.fwc_label, chain, sizeof (del.fwc_label));
 
-       if (!init && !ipfwc_init()) return 0;
+       if (!init && !ipfwc_init())
+               return 0;
 
        ipfwc_fn = ipfwc_delete_entry;
-       return do_setsockopt(IP_FW_DELETE, &del, sizeof(del));  
+       return do_setsockopt(IP_FW_DELETE, &del, sizeof (del));
 }
 
 /* Delete the rule in position `rulenum' in `chain'. */
-int ipfwc_delete_num_entry(const ip_chainlabel chain, unsigned int rulenum)
+int
+ipfwc_delete_num_entry(const ip_chainlabel chain, unsigned int rulenum)
 {
        struct ip_fwdelnum del = { rulenum, "" };
-       memcpy(del.fwd_label, chain, sizeof(del.fwd_label));
+       memcpy(del.fwd_label, chain, sizeof (del.fwd_label));
 
-       if (!init && !ipfwc_init()) return 0;
+       if (!init && !ipfwc_init())
+               return 0;
 
        ipfwc_fn = ipfwc_delete_num_entry;
-       return do_setsockopt(IP_FW_DELETE_NUM, &del, sizeof(del));
+       return do_setsockopt(IP_FW_DELETE_NUM, &del, sizeof (del));
 }
 
 static struct ip_fwtest *
@@ -134,8 +145,8 @@ fw_to_fwtest(const struct ip_fw *fw, const ip_chainlabel chain)
        iph = &ipfwt.fwt_packet.fwp_iph;
 
        iph->version = IP_VERSION;
-       iph->ihl = sizeof(struct iphdr) / 4;
-       iph->tot_len = sizeof(struct ip_fwpkt);
+       iph->ihl = sizeof (struct iphdr) / 4;
+       iph->tot_len = sizeof (struct ip_fwpkt);
        iph->frag_off &= htons(~IP_OFFSET);
        iph->protocol = fw->fw_proto;
 
@@ -145,7 +156,7 @@ fw_to_fwtest(const struct ip_fw *fw, const ip_chainlabel chain)
        strncpy(ipfwt.fwt_packet.fwp_vianame, fw->fw_vianame, IFNAMSIZ);
 
        if (fw->fw_flg & IP_FW_F_FRAG)
-               iph->frag_off |= htons(2); /* = 64 bytes - why not? */
+               iph->frag_off |= htons(2);      /* = 64 bytes - why not? */
 
        /* The tcp and udp headers are ignored for fragments, anyway */
        switch (iph->protocol) {
@@ -172,95 +183,108 @@ fw_to_fwtest(const struct ip_fw *fw, const ip_chainlabel chain)
 
 /* Check the packet `fw' on chain `chain'.  Returns the verdict, or
    NULL and sets errno. */
-const char *ipfwc_check_packet(const ip_chainlabel chain, 
-                               struct ip_fw *fw)
+const char *
+ipfwc_check_packet(const ip_chainlabel chain, struct ip_fw *fw)
 {
        int old_errno = errno;
 
-       if (!init && !ipfwc_init()) return NULL;
+       if (!init && !ipfwc_init())
+               return NULL;
 
        ipfwc_fn = ipfwc_check_packet;
-       if (do_setsockopt(IP_FW_CHECK, fw_to_fwtest(fw, chain), 
-                         sizeof(struct ip_fwtest)))
+       if (do_setsockopt(IP_FW_CHECK, fw_to_fwtest(fw, chain),
+                         sizeof (struct ip_fwtest)))
                return "accepted";
-       else switch (errno) {
-       case ECONNRESET:
-               errno = old_errno;
-               return "masqueraded";
-       case ETIMEDOUT:
-               errno = old_errno;
-               return "denied";
-       case ECONNREFUSED:
-               errno = old_errno;
-               return "rejected";
-       case ECONNABORTED:
-               errno = old_errno;
-               return "redirected";
-       case ELOOP:
-               errno = old_errno;
-               return "caught in loop";
-       case ENFILE:
-               errno = old_errno;
-               return "passed through chain";
-
-       default:
-               return NULL;
-       }
+       else
+               switch (errno) {
+               case ECONNRESET:
+                       errno = old_errno;
+                       return "masqueraded";
+               case ETIMEDOUT:
+                       errno = old_errno;
+                       return "denied";
+               case ECONNREFUSED:
+                       errno = old_errno;
+                       return "rejected";
+               case ECONNABORTED:
+                       errno = old_errno;
+                       return "redirected";
+               case ELOOP:
+                       errno = old_errno;
+                       return "caught in loop";
+               case ENFILE:
+                       errno = old_errno;
+                       return "passed through chain";
+
+               default:
+                       return NULL;
+               }
 }
 
 /* Flushes the entries in the given chain (ie. empties chain). */
-int ipfwc_flush_entries(const ip_chainlabel chain)
+int
+ipfwc_flush_entries(const ip_chainlabel chain)
 {
-       if (!init && !ipfwc_init()) return 0;
+       if (!init && !ipfwc_init())
+               return 0;
 
        ipfwc_fn = ipfwc_flush_entries;
-       return do_setsockopt(IP_FW_FLUSH, chain, sizeof(ip_chainlabel));
+       return do_setsockopt(IP_FW_FLUSH, chain, sizeof (ip_chainlabel));
 }
 
 /* Zeroes the counters in a chain. */
-int ipfwc_zero_entries(const ip_chainlabel chain)
+int
+ipfwc_zero_entries(const ip_chainlabel chain)
 {
-       if (!init && !ipfwc_init()) return 0;
+       if (!init && !ipfwc_init())
+               return 0;
 
        ipfwc_fn = ipfwc_zero_entries;
-       return do_setsockopt(IP_FW_ZERO, chain, sizeof(ip_chainlabel));
+       return do_setsockopt(IP_FW_ZERO, chain, sizeof (ip_chainlabel));
 }
 
 /* Creates a new chain. */
-int ipfwc_create_chain(const ip_chainlabel chain)
+int
+ipfwc_create_chain(const ip_chainlabel chain)
 {
-       if (!init && !ipfwc_init()) return 0;
+       if (!init && !ipfwc_init())
+               return 0;
 
        ipfwc_fn = ipfwc_create_chain;
-       return do_setsockopt(IP_FW_CREATECHAIN, chain, sizeof(ip_chainlabel));
+       return do_setsockopt(IP_FW_CREATECHAIN, chain, sizeof (ip_chainlabel));
 }
 
 /* Deletes a chain. */
-int ipfwc_delete_chain(const ip_chainlabel chain)
+int
+ipfwc_delete_chain(const ip_chainlabel chain)
 {
-       if (!init && !ipfwc_init()) return 0;
+       if (!init && !ipfwc_init())
+               return 0;
 
        ipfwc_fn = ipfwc_delete_chain;
-       return do_setsockopt(IP_FW_DELETECHAIN, chain, sizeof(ip_chainlabel));
+       return do_setsockopt(IP_FW_DELETECHAIN, chain, sizeof (ip_chainlabel));
 }
 
 /* Sets the policy on a built-in chain. */
-int ipfwc_set_policy(const ip_chainlabel chain, const ip_chainlabel policy)
+int
+ipfwc_set_policy(const ip_chainlabel chain, const ip_chainlabel policy)
 {
        struct ip_fwpolicy fwp;
 
-       if (!init && !ipfwc_init()) return 0;
+       if (!init && !ipfwc_init())
+               return 0;
 
        ipfwc_fn = ipfwc_set_policy;
-       memcpy(fwp.fwp_policy, policy, sizeof(fwp.fwp_policy));
-       memcpy(fwp.fwp_label, chain, sizeof(fwp.fwp_label));
-       return do_setsockopt(IP_FW_POLICY, &fwp, sizeof(fwp));
+       memcpy(fwp.fwp_policy, policy, sizeof (fwp.fwp_policy));
+       memcpy(fwp.fwp_label, chain, sizeof (fwp.fwp_label));
+       return do_setsockopt(IP_FW_POLICY, &fwp, sizeof (fwp));
 }
 
 /* Gets the names of all the chains.  Returns single malloc()d region;
    and array of ip_chainlabels.  Fills in num_chains.  Returns NULL on
    error.  */
-struct ipfwc_fwchain *ipfwc_get_chainnames(unsigned int *num_chains)
+struct ipfwc_fwchain *
+ipfwc_get_chainnames(unsigned int *num_chains)
 {
        int nread;
        static unsigned int maxnum = 4;
@@ -270,7 +294,7 @@ struct ipfwc_fwchain *ipfwc_get_chainnames(unsigned int *num_chains)
 
        ipfwc_fn = ipfwc_get_chainnames;
        if (!chains) {
-               chains = malloc(sizeof(struct ipfwc_fwchain) * maxnum);
+               chains = malloc(sizeof (struct ipfwc_fwchain) * maxnum);
 
                if (!chains) {
                        errno = ENOMEM;
@@ -279,26 +303,28 @@ struct ipfwc_fwchain *ipfwc_get_chainnames(unsigned int *num_chains)
        }
 
        /* Read names from IP_FW_PROC_CHAIN_NAMES */
-       fp = fopen("/proc/net/"IP_FW_PROC_CHAIN_NAMES, "r");
+       fp = fopen("/proc/net/" IP_FW_PROC_CHAIN_NAMES, "r");
        if (!fp) {
                /* Bad kernel version? */
-               if (errno == ENOENT) errno = 0;
+               if (errno == ENOENT)
+                       errno = 0;
                return NULL;
        }
 
        *num_chains = 0;
-       while ((nread = fscanf(fp,"%s %s %u %u %u %u %u", 
-                              chains[*num_chains].label, 
-                              chains[*num_chains].policy, 
-                              &chains[*num_chains].refcnt, 
+       while ((nread = fscanf(fp, "%s %s %u %u %u %u %u",
+                              chains[*num_chains].label,
+                              chains[*num_chains].policy,
+                              &chains[*num_chains].refcnt,
                               &pkthi, &pktlo, &bytehi, &bytelo)) == 7) {
-               chains[*num_chains].packets = ((__u64)pkthi)<<32 | pktlo;
-               chains[*num_chains].bytes = ((__u64)bytehi)<<32 | bytelo;
+               chains[*num_chains].packets = ((__u64) pkthi) << 32 | pktlo;
+               chains[*num_chains].bytes = ((__u64) bytehi) << 32 | bytelo;
                (*num_chains)++;
                if (*num_chains >= maxnum) {
                        maxnum *= 2;
-                       chains = realloc(chains, 
-                                        sizeof(struct ipfwc_fwchain)*maxnum);
+                       chains = realloc(chains,
+                                        sizeof (struct ipfwc_fwchain) *
+                                        maxnum);
                        if (!chains) {
                                fclose(fp);
                                errno = ENOMEM;
@@ -315,18 +341,17 @@ struct ipfwc_fwchain *ipfwc_get_chainnames(unsigned int *num_chains)
        }
 
        return chains;
-}      
+}
 
 static const struct ipfwc_fwchain *
 find_chain(const ip_chainlabel label,
-          const struct ipfwc_fwchain *chains,
-          unsigned int num_chains)
+          const struct ipfwc_fwchain *chains, unsigned int num_chains)
 {
        unsigned int i;
 
        for (i = 0; i < num_chains; i++) {
                if (strcmp(label, chains[i].label) == 0)
-                       return chains+i;
+                       return chains + i;
        }
        return NULL;
 }
@@ -337,7 +362,8 @@ find_chain(const ip_chainlabel label,
 
 /* Take a snapshot of the rules.  Returns internal pointer to array of
    ipfwc_fwrules.  Fills in num_rules.  Returns NULL on error. */
-struct ipfwc_fwrule *ipfwc_get_rules(unsigned int *num_rules, int zero)
+struct ipfwc_fwrule *
+ipfwc_get_rules(unsigned int *num_rules, int zero)
 {
        FILE *fp;
        __u32 pkthi, pktlo, bytehi, bytelo;
@@ -351,46 +377,46 @@ struct ipfwc_fwrule *ipfwc_get_rules(unsigned int *num_rules, int zero)
 
        ipfwc_fn = ipfwc_get_rules;
        if (!rules) {
-               rules = malloc(sizeof(struct ipfwc_fwrule) * maxnum);
+               rules = malloc(sizeof (struct ipfwc_fwrule) * maxnum);
                if (!rules) {
                        errno = ENOMEM;
                        return NULL;
                }
        }
 
-       fp = fopen("/proc/net/"IP_FW_PROC_CHAINS, zero ? "r+" : "r");
+       fp = fopen("/proc/net/" IP_FW_PROC_CHAINS, zero ? "r+" : "r");
        if (!fp) {
-               if (errno == ENOENT) errno = 0;
+               if (errno == ENOENT)
+                       errno = 0;
                return NULL;
        }
 
        *num_rules = 0;
-       while ((nread = fscanf(fp,
-                              IPFWC_CHAIN_FMT          /* Chain name */
-                              "%X/%X->%X/%X "          /* IPs */
-                              "%s "                    /* Interface */
-                              "%hX %hX "               /* flg & invflg */
-                              "%hu "                   /* Protocol */
-                              "%u %u %u %u "           /* Counters */
+       while ((nread = fscanf(fp, IPFWC_CHAIN_FMT      /* Chain name */
+                              "%X/%X->%X/%X "  /* IPs */
+                              "%s "    /* Interface */
+                              "%hX %hX "       /* flg & invflg */
+                              "%hu "   /* Protocol */
+                              "%u %u %u %u "   /* Counters */
                               "%hu-%hu %hu-%hu "       /* Ports */
-                              "A%hX X%hX "             /* TOS masks */
-                              "%hX "                   /* fw_redir */
-                              "%u "                    /* fw_mark */
-                              "%hu "                   /* output size */
-                              "%s",                    /* Target */
+                              "A%hX X%hX "     /* TOS masks */
+                              "%hX "   /* fw_redir */
+                              "%u "    /* fw_mark */
+                              "%hu "   /* output size */
+                              "%s",    /* Target */
                               label,
                               &rules[*num_rules].ipfw.ipfw.fw_src.s_addr,
                               &rules[*num_rules].ipfw.ipfw.fw_smsk.s_addr,
                               &rules[*num_rules].ipfw.ipfw.fw_dst.s_addr,
                               &rules[*num_rules].ipfw.ipfw.fw_dmsk.s_addr,
                               rules[*num_rules].ipfw.ipfw.fw_vianame,
-                              &rules[*num_rules].ipfw.ipfw.fw_flg, 
+                              &rules[*num_rules].ipfw.ipfw.fw_flg,
                               &rules[*num_rules].ipfw.ipfw.fw_invflg,
                               &rules[*num_rules].ipfw.ipfw.fw_proto,
                               &pkthi, &pktlo, &bytehi, &bytelo,
-                              &rules[*num_rules].ipfw.ipfw.fw_spts[0], 
+                              &rules[*num_rules].ipfw.ipfw.fw_spts[0],
                               &rules[*num_rules].ipfw.ipfw.fw_spts[1],
-                              &rules[*num_rules].ipfw.ipfw.fw_dpts[0], 
+                              &rules[*num_rules].ipfw.ipfw.fw_dpts[0],
                               &rules[*num_rules].ipfw.ipfw.fw_dpts[1],
                               &tosand, &tosxor,
                               &rules[*num_rules].ipfw.ipfw.fw_redirpt,
@@ -401,30 +427,29 @@ struct ipfwc_fwrule *ipfwc_get_rules(unsigned int *num_rules, int zero)
                        (rules[*num_rules].ipfw.label)[0] = '\0';
                if (strcmp("-", rules[*num_rules].ipfw.ipfw.fw_vianame) == 0)
                        (rules[*num_rules].ipfw.ipfw.fw_vianame)[0] = '\0';
-               rules[*num_rules].ipfw.ipfw.fw_tosand = (unsigned char)tosand;
-               rules[*num_rules].ipfw.ipfw.fw_tosxor = (unsigned char)tosxor;
+               rules[*num_rules].ipfw.ipfw.fw_tosand = (unsigned char) tosand;
+               rules[*num_rules].ipfw.ipfw.fw_tosxor = (unsigned char) tosxor;
 
                /* we always keep these addresses in network byte order */
                rules[*num_rules].ipfw.ipfw.fw_src.s_addr
-                       = htonl(rules[*num_rules].ipfw.ipfw.fw_src.s_addr);
+                   = htonl(rules[*num_rules].ipfw.ipfw.fw_src.s_addr);
                rules[*num_rules].ipfw.ipfw.fw_smsk.s_addr
-                       = htonl(rules[*num_rules].ipfw.ipfw.fw_smsk.s_addr);
+                   = htonl(rules[*num_rules].ipfw.ipfw.fw_smsk.s_addr);
                rules[*num_rules].ipfw.ipfw.fw_dst.s_addr
-                       = htonl(rules[*num_rules].ipfw.ipfw.fw_dst.s_addr);
+                   = htonl(rules[*num_rules].ipfw.ipfw.fw_dst.s_addr);
                rules[*num_rules].ipfw.ipfw.fw_dmsk.s_addr
-                       = htonl(rules[*num_rules].ipfw.ipfw.fw_dmsk.s_addr);
+                   = htonl(rules[*num_rules].ipfw.ipfw.fw_dmsk.s_addr);
 
-               rules[*num_rules].packets = ((__u64)pkthi)<<32 | pktlo;
-               rules[*num_rules].bytes = ((__u64)bytehi)<<32 | bytelo;
+               rules[*num_rules].packets = ((__u64) pkthi) << 32 | pktlo;
+               rules[*num_rules].bytes = ((__u64) bytehi) << 32 | bytelo;
 
-               rules[*num_rules].chain
-                       = find_chain(label, chains, num_chains);
+               rules[*num_rules].chain = find_chain(label, chains, num_chains);
 
                (*num_rules)++;
                if (*num_rules >= maxnum) {
                        maxnum *= 2;
-                       rules = realloc(rules, 
-                                       sizeof(struct ipfwc_fwrule)*maxnum);
+                       rules = realloc(rules,
+                                       sizeof (struct ipfwc_fwrule) * maxnum);
                        if (!rules) {
                                fclose(fp);
                                errno = ENOMEM;
@@ -444,14 +469,16 @@ struct ipfwc_fwrule *ipfwc_get_rules(unsigned int *num_rules, int zero)
 }
 
 /* Get raw socket. */
-int ipfwc_get_raw_socket()
+int
+ipfwc_get_raw_socket()
 {
        return sockfd;
 }
 
 /* Translates errno numbers into more human-readable form than strerror.
  * `ipfwc_fn' is a pointer to the function which returned the error. */
-const char *ipfwc_strerror(int err)
+const char *
+ipfwc_strerror(int err)
 {
        unsigned int i;
        static char message[200];
@@ -460,30 +487,35 @@ const char *ipfwc_strerror(int err)
                int err;
                const char *message;
                int support_warning;
-       } table [] = 
-         { { ipfwc_insert_entry, ENOENT, "No target by that name", 1 },
-           { ipfwc_replace_entry, ENOENT, "No target by that name", 1 },
-           { ipfwc_append_entry, ENOENT, "No target by that name", 1 },
-           { NULL, ENOENT, "No chain by that name", 0 },
-           { NULL, 0, "Incompatible with this kernel", 0 },
-           { ipfwc_init, EPERM, "Permission denied (you must be root)", 0 },
-           { ipfwc_delete_chain, ENOTEMPTY, "Chain is not empty", 0 },
-           { ipfwc_create_chain, EEXIST, "Chain already exists", 0 },
+       } table[] = { {
+       ipfwc_insert_entry, ENOENT, "No target by that name", 1}, {
+       ipfwc_replace_entry, ENOENT, "No target by that name", 1}, {
+       ipfwc_append_entry, ENOENT, "No target by that name", 1}, {
+       NULL, ENOENT, "No chain by that name", 0}, {
+       NULL, 0, "Incompatible with this kernel", 0}, {
+       ipfwc_init, EPERM, "Permission denied (you must be root)", 0}, {
+       ipfwc_delete_chain, ENOTEMPTY, "Chain is not empty", 0}, {
+       ipfwc_create_chain, EEXIST, "Chain already exists", 0},
            /* EINVAL for CHECK probably means bad interface. */
-           { ipfwc_check_packet, EINVAL, 
-             "bad arguments (does that interface exist?)", 0 },
+       {
+       ipfwc_check_packet, EINVAL,
+                   "bad arguments (does that interface exist?)", 0},
            /* EINVAL for DELETE probably means no matching rule */
-           { ipfwc_delete_entry, EINVAL,
-             "bad rule (does a matching rule exist in that chain?)", 0 },
-           { ipfwc_insert_entry, EINVAL,
-             "bad rule (does a matching rule exist in that chain?)", 0 },
-           { ipfwc_delete_num_entry, EINVAL,
-             "bad rule (does a matching rule exist in that chain?)", 0 },
-           { ipfwc_replace_entry, EINVAL,
-             "bad rule (does a matching rule exist in that chain?)", 0 }
-         };
-
-       for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) {
+       {
+       ipfwc_delete_entry, EINVAL,
+                   "bad rule (does a matching rule exist in that chain?)", 0},
+       {
+       ipfwc_insert_entry, EINVAL,
+                   "bad rule (does a matching rule exist in that chain?)", 0},
+       {
+       ipfwc_delete_num_entry, EINVAL,
+                   "bad rule (does a matching rule exist in that chain?)", 0},
+       {
+       ipfwc_replace_entry, EINVAL,
+                   "bad rule (does a matching rule exist in that chain?)", 0}
+       };
+
+       for (i = 0; i < sizeof (table) / sizeof (struct table_struct); i++) {
                if ((!table[i].fn || table[i].fn == ipfwc_fn)
                    && table[i].err == err) {
                        strcpy(message, table[i].message);
@@ -507,4 +539,3 @@ const char *ipfwc_strerror(int err)
        }
        return strerror(err);
 }
-
similarity index 85%
rename from libipfwc/libipfwc.h
rename to keepalived/libipfwc/libipfwc.h
index 4c8200b..b4cf206 100644 (file)
 
 #include "ipfwc_kernel_headers.h"
 
-struct ipfwc_fwchain
-{
+struct ipfwc_fwchain {
        ip_chainlabel label;
-        unsigned int refcnt;
+       unsigned int refcnt;
        ip_chainlabel policy;
-        __u64 packets, bytes;
+       __u64 packets, bytes;
 };
 
 /* Gets the names of all the chains.  Returns internal pointer to
@@ -23,11 +22,10 @@ struct ipfwc_fwchain
    root.  Returns NULL on error.*/
 struct ipfwc_fwchain *ipfwc_get_chainnames(unsigned int *num_chains);
 
-struct ipfwc_fwrule
-{
+struct ipfwc_fwrule {
        const struct ipfwc_fwchain *chain;
        struct ip_fwuser ipfw;
-        __u64 packets, bytes;
+       __u64 packets, bytes;
 };
 
 /* Take a snapshot of the rules; if zero is set, clears counters.
@@ -41,14 +39,12 @@ struct ipfwc_fwrule *ipfwc_get_rules(unsigned int *num_rules, int zero);
 /* Rule numbers start at 1 for the first rule. */
 
 /* Insert the entry `fw' in chain `chain' into position `rulenum'. */
-int ipfwc_insert_entry(const ip_chainlabel chain, 
-                       const struct ip_fwuser *fw, 
-                       unsigned int rulenum);
+int ipfwc_insert_entry(const ip_chainlabel chain,
+                      const struct ip_fwuser *fw, unsigned int rulenum);
 
 /* Atomically replace rule `rulenum' in `chain' with `fw'. */
-int ipfwc_replace_entry(const ip_chainlabel chain, 
-                        const struct ip_fwuser *fw, 
-                        unsigned int rulenum);
+int ipfwc_replace_entry(const ip_chainlabel chain,
+                       const struct ip_fwuser *fw, unsigned int rulenum);
 
 /* Append entry `fw' to chain `chain'.  Equivalent to insert with
    rulenum = length of chain. */
@@ -84,4 +80,4 @@ int ipfwc_get_raw_socket(void);
 
 /* Translates errno numbers into more human-readable form than strerror. */
 const char *ipfwc_strerror(int err);
-#endif /* _LIBIPFWC_H */
+#endif                         /* _LIBIPFWC_H */
diff --git a/keepalived/libipvs/Makefile.in b/keepalived/libipvs/Makefile.in
new file mode 100644 (file)
index 0000000..863cb67
--- /dev/null
@@ -0,0 +1,18 @@
+# Makefile to make libipvsc.
+
+CC     = @CC@
+CFLAGS = @CFLAGS@ -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
similarity index 100%
rename from samples/root.pem
rename to keepalived/samples/root.pem
diff --git a/keepalived/vrrp/Makefile.in b/keepalived/vrrp/Makefile.in
new file mode 100644 (file)
index 0000000..d94a643
--- /dev/null
@@ -0,0 +1,27 @@
+# Makefile
+#
+# Keepalived OpenSource project.
+#
+# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
+
+CC      = @CC@
+INCLUDES = -I../include
+CFLAGS  = @CFLAGS@ $(INCLUDES) \
+          -Wall -Wunused -Wstrict-prototypes
+DEFS    = -D@KERN@ -D@IPVS_SUPPORT@ -D@IPVS_SYNCD@ @DFLAGS@
+COMPILE         = $(CC) $(CFLAGS) $(DEFS)
+
+OBJS =         vrrp.o vrrp_notify.o vrrp_scheduler.o vrrp_sync.o \
+       vrrp_netlink.o vrrp_if.o vrrp_ipaddress.o vrrp_ipsecah.o
+HEADERS = $(OBJS:.o=.h)
+
+.c.o:
+       $(COMPILE) -c $<
+
+all:   $(OBJS)
+
+clean:
+       rm -f *.a *.o *~
+
+distclean: clean
+       rm -f Makefile
diff --git a/keepalived/vrrp/vrrp.c b/keepalived/vrrp/vrrp.c
new file mode 100644 (file)
index 0000000..2fab32e
--- /dev/null
@@ -0,0 +1,1158 @@
+/*
+ * 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 implementation of VRRPv2 as specified in rfc2338.
+ *              VRRP is a protocol which elect a master server on a LAN. If the
+ *              master fails, a backup server takes over.
+ *              The original implementation has been made by jerome etienne.
+ *
+ * Version:     $Id: vrrp.c,v 0.6.5 2002/07/01 23:41:28 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 <ctype.h>
+#include "vrrp_scheduler.h"
+#include "vrrp_notify.h"
+#include "ipvswrapper.h"
+#include "vrrp.h"
+#include "memory.h"
+#include "list.h"
+#include "data.h"
+
+extern data *conf_data;
+
+/* compute checksum */
+static u_short
+in_csum(u_short * addr, int len, u_short csum)
+{
+       register int nleft = len;
+       const u_short *w = addr;
+       register u_short answer;
+       register int sum = csum;
+
+       /*
+        *  Our algorithm is simple, using a 32 bit accumulator (sum),
+        *  we add sequential 16 bit words to it, and at the end, fold
+        *  back all the carry bits from the top 16 bits into the lower
+        *  16 bits.
+        */
+       while (nleft > 1) {
+               sum += *w++;
+               nleft -= 2;
+       }
+
+       /* mop up an odd byte, if necessary */
+       if (nleft == 1)
+               sum += htons(*(u_char *) w << 8);
+
+       /*
+        * add back carry outs from top 16 bits to low 16 bits
+        */
+       sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
+       sum += (sum >> 16);                     /* add carry */
+       answer = ~sum;                          /* truncate to 16 bits */
+       return (answer);
+}
+
+/*
+ * add/remove VIP
+ * retry must clear for each vip address Hoj:-
+ */
+static int
+vrrp_handle_ipaddress(vrrp_rt * vrrp, int cmd, int type)
+{
+       int i, err = 0;
+       int retry = 0;
+       int num;
+       int ifindex = IF_INDEX(vrrp->ifp);
+
+       syslog(LOG_INFO, "VRRP_Instance(%s) %s protocol %s", vrrp->iname,
+              (cmd == VRRP_IPADDRESS_ADD) ? "setting" : "removing",
+              (type == VRRP_VIP_TYPE) ? "VIPs." : "E-VIPs");
+
+       num = (type == VRRP_VIP_TYPE) ? vrrp->naddr : vrrp->neaddr;
+       for (i = 0; i < num; i++) {
+               vip_addr *vadd =
+                   (type ==
+                    VRRP_VIP_TYPE) ? &vrrp->vaddr[i] : &vrrp->evaddr[i];
+               if (!cmd && !vadd->set)
+                       continue;
+             retry:
+               if (netlink_address_ipv4(ifindex, vadd->addr, vadd->mask, cmd) <
+                   0) {
+                       err = 1;
+                       vadd->set = 0;
+                       syslog(LOG_INFO, "cant %s the address %s to %s\n",
+                              cmd ? "set" : "remove", inet_ntop2(vadd->addr)
+                              , IF_NAME(vrrp->ifp));
+                       if (cmd == VRRP_IPADDRESS_ADD) {
+                               syslog(LOG_INFO,
+                                      "try to delete eventual stalled ip");
+                               netlink_address_ipv4(ifindex, vadd->addr,
+                                                    vadd->mask,
+                                                    VRRP_IPADDRESS_DEL);
+                               if (retry < 4) {
+                                       retry++;
+                                       goto retry;
+                               }
+                       }
+               } else {
+                       vadd->set = 1;
+               }
+       }
+       return err;
+}
+
+/* ARP header length */
+static int
+vrrp_dlt_len(vrrp_rt * rt)
+{
+       return ETHER_HDR_LEN;   /* hardcoded for ethernet */
+}
+
+/* IP header length */
+static int
+vrrp_iphdr_len(vrrp_rt * vrrp)
+{
+       return sizeof (struct iphdr);
+}
+
+/* IPSEC AH header length */
+int
+vrrp_ipsecah_len(void)
+{
+       return sizeof (ipsec_ah);
+}
+
+/* VRRP header length */
+static int
+vrrp_hd_len(vrrp_rt * vrrp)
+{
+       return sizeof (vrrp_pkt)
+           + vrrp->naddr * sizeof (uint32_t)
+           + VRRP_AUTH_LEN;
+}
+
+/*
+ * IPSEC AH incoming packet check.
+ * return 0 for a valid pkt, != 0 otherwise.
+ */
+static int
+vrrp_in_chk_ipsecah(vrrp_rt * vrrp, char *buffer)
+{
+       struct iphdr *ip = (struct iphdr *) (buffer);
+       ipsec_ah *ah = (ipsec_ah *) ((char *) ip + (ip->ihl << 2));
+       unsigned char *digest;
+       uint32_t backup_auth_data[3];
+
+       /* first verify that the SPI value is equal to src IP */
+       if (ah->spi != ip->saddr) {
+               syslog(LOG_INFO,
+                      "IPSEC AH : invalid IPSEC SPI value. %d and expect %d",
+                      ip->saddr, ah->spi);
+               return 1;
+       }
+
+       /*
+        * then proceed with the sequence number to prevent against replay attack.
+        * in inbound processing, we increment seq_number counter to audit 
+        * sender counter.
+        */
+       vrrp->ipsecah_counter->seq_number++;
+       if (ah->seq_number >= vrrp->ipsecah_counter->seq_number) {
+               vrrp->ipsecah_counter->seq_number = ah->seq_number;
+       } else {
+               syslog(LOG_INFO,
+                      "IPSEC AH : sequence number %d already proceeded."
+                      " Packet droped", ah->seq_number);
+               return 1;
+       }
+
+       /*
+        * then compute a ICV to compare with the one present in AH pkt.
+        * alloc a temp memory space to stock the ip mutable fields
+        */
+       digest = (unsigned char *) MALLOC(16 * sizeof (unsigned char *));
+
+       /* zero the ip mutable fields */
+       ip->tos = 0;
+       ip->id = 0;
+       ip->frag_off = 0;
+       ip->check = 0;
+       memcpy(backup_auth_data, ah->auth_data, sizeof (ah->auth_data));
+       memset(ah->auth_data, 0, sizeof (ah->auth_data));
+
+       /* Compute the ICV */
+       hmac_md5(buffer,
+                vrrp_iphdr_len(vrrp) + vrrp_ipsecah_len() + vrrp_hd_len(vrrp)
+                , vrrp->auth_data, sizeof (vrrp->auth_data)
+                , digest);
+
+       if (memcmp(backup_auth_data, digest, HMAC_MD5_TRUNC) != 0) {
+               syslog(LOG_INFO, "IPSEC AH : invalid IPSEC HMAC-MD5 value."
+                      " Due to fields mutation or bad password !");
+               return 1;
+       }
+
+       FREE(digest);
+       return 0;
+}
+
+/* check if ipaddr is present in VIP buffer */
+static int
+vrrp_in_chk_vips(vrrp_rt * vrrp, uint32_t ipaddr, unsigned char *buffer)
+{
+       int i;
+       uint32_t ipbuf;
+
+       for (i = 0; i < vrrp->naddr; i++) {
+               bcopy(buffer + i * sizeof (uint32_t), &ipbuf,
+                     sizeof (uint32_t));
+               if (ipaddr == ntohl(ipbuf))
+                       return 1;
+       }
+
+       return 0;
+}
+
+/*
+ * VRRP incoming packet check.
+ * return 0 if the pkt is valid, != 0 otherwise.
+ */
+static int
+vrrp_in_chk(vrrp_rt * vrrp, char *buffer)
+{
+       struct iphdr *ip = (struct iphdr *) (buffer);
+       int ihl = ip->ihl << 2;
+       ipsec_ah *ah;
+       vrrp_pkt *hd;
+       unsigned char *vips;
+       int i;
+
+       if (vrrp->auth_type == VRRP_AUTH_AH) {
+               ah = (ipsec_ah *) (buffer + sizeof (struct iphdr));
+               hd = (vrrp_pkt *) (buffer + ihl + vrrp_ipsecah_len());
+       } else {
+               hd = (vrrp_pkt *) (buffer + ihl);
+       }
+
+       /* pointer to vrrp vips pkt zone */
+       vips = (unsigned char *) ((char *) hd + sizeof (vrrp_pkt));
+
+       /* MUST verify that the IP TTL is 255 */
+       if (ip->ttl != VRRP_IP_TTL) {
+               syslog(LOG_INFO, "invalid ttl. %d and expect %d", ip->ttl,
+                      VRRP_IP_TTL);
+               return VRRP_PACKET_KO;
+       }
+
+       /* MUST verify the VRRP version */
+       if ((hd->vers_type >> 4) != VRRP_VERSION) {
+               syslog(LOG_INFO, "invalid version. %d and expect %d",
+                      (hd->vers_type >> 4), VRRP_VERSION);
+               return VRRP_PACKET_KO;
+       }
+
+       /*
+        * MUST verify that the received packet length is greater than or
+        * equal to the VRRP header
+        */
+       if ((ntohs(ip->tot_len) - ihl) <= sizeof (vrrp_pkt)) {
+               syslog(LOG_INFO,
+                      "ip payload too short. %d and expect at least %d",
+                      ntohs(ip->tot_len) - ihl, sizeof (vrrp_pkt));
+               return VRRP_PACKET_KO;
+       }
+
+       /* MUST verify the VRRP checksum */
+       if (in_csum((u_short *) hd, vrrp_hd_len(vrrp), 0)) {
+               syslog(LOG_INFO, "Invalid vrrp checksum");
+               return VRRP_PACKET_KO;
+       }
+
+       /*
+        * MUST perform authentication specified by Auth Type 
+        * check the authentication type
+        */
+       if (vrrp->auth_type != hd->auth_type) {
+               syslog(LOG_INFO, "receive a %d auth, expecting %d!",
+                      vrrp->auth_type, hd->auth_type);
+               return VRRP_PACKET_KO;
+       }
+
+       /* check the authentication if it is a passwd */
+       if (hd->auth_type == VRRP_AUTH_PASS) {
+               char *pw = (char *) ip + ntohs(ip->tot_len)
+                   - sizeof (vrrp->auth_data);
+               if (strncmp(pw, vrrp->auth_data, strlen(vrrp->auth_data)) != 0) {
+                       syslog(LOG_INFO, "receive an invalid passwd!");
+                       return VRRP_PACKET_KO;
+               }
+       }
+
+       /* MUST verify that the VRID is valid on the receiving interface */
+       if (vrrp->vrid != hd->vrid) {
+               syslog(LOG_INFO,
+                      "received VRID mismatch. Received %d, Expected %d",
+                      hd->vrid, vrrp->vrid);
+               return VRRP_PACKET_DROP;
+       }
+
+       /*
+        * MAY verify that the IP address(es) associated with the
+        * VRID are valid
+        */
+       if (vrrp->naddr != hd->naddr) {
+               syslog(LOG_INFO,
+                      "receive an invalid ip number count associated with VRID!");
+               return VRRP_PACKET_KO;
+       }
+
+       for (i = 0; i < vrrp->naddr; i++)
+               if (!vrrp_in_chk_vips(vrrp, vrrp->vaddr[i].addr, vips)) {
+                       syslog(LOG_INFO, "ip address associated with VRID"
+                              " not present in received packet : %d",
+                              vrrp->vaddr[i].addr);
+                       syslog(LOG_INFO,
+                              "one or more VIP associated with"
+                              " VRID mismatch actual MASTER advert");
+                       return VRRP_PACKET_KO;
+               }
+
+       /*
+        * MUST verify that the Adver Interval in the packet is the same as
+        * the locally configured for this virtual router
+        */
+       if (vrrp->adver_int / TIMER_HZ != hd->adver_int) {
+               syslog(LOG_INFO,
+                      "advertissement interval mismatch mine=%d rcved=%d",
+                      vrrp->adver_int, hd->adver_int);
+               /* to prevent concurent VRID running => multiple master in 1 VRID */
+               return VRRP_PACKET_DROP;
+       }
+
+       /* check the authenicaion if it is ipsec ah */
+       if (hd->auth_type == VRRP_AUTH_AH)
+               return (vrrp_in_chk_ipsecah(vrrp, buffer));
+
+       return VRRP_PACKET_OK;
+}
+
+/* build ARP header */
+static void
+vrrp_build_arp(vrrp_rt * vrrp, char *buffer, int buflen)
+{
+       /* hardcoded for ethernet */
+       struct ether_header *eth = (struct ether_header *) buffer;
+
+       /* destination address --rfc1122.6.4 */
+       eth->ether_dhost[0] = 0x01;
+       eth->ether_dhost[1] = 0x00;
+       eth->ether_dhost[2] = 0x5E;
+       eth->ether_dhost[3] = (INADDR_VRRP_GROUP >> 16) & 0x7F;
+       eth->ether_dhost[4] = (INADDR_VRRP_GROUP >> 8) & 0xFF;
+       eth->ether_dhost[5] = INADDR_VRRP_GROUP & 0xFF;
+
+       /* source address -- rfc2338.7.3 */
+       memcpy(eth->ether_shost, vrrp->hwaddr, sizeof (vrrp->hwaddr));
+
+       /* type */
+       eth->ether_type = htons(ETHERTYPE_IP);
+}
+
+/* build IP header */
+static void
+vrrp_build_ip(vrrp_rt * vrrp, char *buffer, int buflen)
+{
+       struct iphdr *ip = (struct iphdr *) (buffer);
+
+       ip->ihl = 5;
+       ip->version = 4;
+       ip->tos = 0;
+       ip->tot_len = ip->ihl * 4 + vrrp_hd_len(vrrp);
+       ip->tot_len = htons(ip->tot_len);
+       ip->id = ++vrrp->ip_id;
+       ip->frag_off = 0;
+       ip->ttl = VRRP_IP_TTL;
+
+       /* fill protocol type --rfc2402.2 */
+       ip->protocol =
+           (vrrp->auth_type == VRRP_AUTH_AH) ? IPPROTO_IPSEC_AH : IPPROTO_VRRP;
+       ip->saddr = VRRP_PKT_SADDR(vrrp);
+       ip->daddr = htonl(INADDR_VRRP_GROUP);
+
+       /* checksum must be done last */
+       ip->check = in_csum((u_short *) ip, ip->ihl * 4, 0);
+}
+
+/* build IPSEC AH header */
+static void
+vrrp_build_ipsecah(vrrp_rt * vrrp, char *buffer, int buflen)
+{
+       ICV_mutable_fields *ip_mutable_fields;
+       unsigned char *digest;
+       struct iphdr *ip = (struct iphdr *) (buffer);
+       ipsec_ah *ah = (ipsec_ah *) (buffer + sizeof (struct iphdr));
+
+       /* alloc a temp memory space to stock the ip mutable fields */
+       ip_mutable_fields =
+           (ICV_mutable_fields *) MALLOC(sizeof (ICV_mutable_fields));
+
+       /* fill in next header filed --rfc2402.2.1 */
+       ah->next_header = IPPROTO_VRRP;
+
+       /* update IP header total length value */
+       ip->tot_len = ip->ihl * 4 + vrrp_ipsecah_len() + vrrp_hd_len(vrrp);
+       ip->tot_len = htons(ip->tot_len);
+
+       /* update ip checksum */
+       ip->check = 0;
+       ip->check = in_csum((u_short *) ip, ip->ihl * 4, 0);
+
+       /* backup the ip mutable fields */
+       ip_mutable_fields->tos = ip->tos;
+       ip_mutable_fields->id = ip->id;
+       ip_mutable_fields->frag_off = ip->frag_off;
+       ip_mutable_fields->check = ip->check;
+
+       /* zero the ip mutable fields */
+       ip->tos = 0;
+       ip->id = 0;
+       ip->frag_off = 0;
+       ip->check = 0;
+
+       /* fill in the Payload len field */
+       ah->payload_len = IPSEC_AH_PLEN;
+
+       /* The SPI value is filled with the ip header source address.
+          SPI uniquely identify the Security Association (SA). This value
+          is chosen by the recipient itself when setting up the SA. In a 
+          multicast environment, this becomes unfeasible.
+
+          If left to the sender, the choice of the SPI value should be done
+          so by the sender that it cannot possibly conflict with SPI values
+          chosen by other entities sending IPSEC traffic to any of the receivers.
+          To overpass this problem, the rule I have chosen to implement here is
+          that the SPI value chosen by the sender is based on unique information
+          such as its IP address.
+          -- INTERNET draft : <draft-paridaens-xcast-sec-framework-01.txt>
+        */
+       ah->spi = ip->saddr;
+
+       /* Processing sequence number.
+          Cycled assumed if 0xFFFFFFFD reached. So the MASTER state is free for another srv.
+          Here can result a flapping MASTER state owner when max seq_number value reached.
+          => Much work needed here.
+          In the current implementation if counter has cycled, we stop sending adverts and 
+          become BACKUP. If all the master are down we reset the counter for becoming MASTER.
+        */
+//  if (vrrp->ipsecah_counter->seq_number > 5) {
+       if (vrrp->ipsecah_counter->seq_number > 0xFFFFFFFD) {
+               vrrp->ipsecah_counter->cycle = 1;
+       } else {
+               vrrp->ipsecah_counter->seq_number++;
+       }
+
+       ah->seq_number = vrrp->ipsecah_counter->seq_number;
+
+       /* Compute the ICV & trunc the digest to 96bits
+          => No padding needed.
+          -- rfc2402.3.3.3.1.1.1 & rfc2401.5
+        */
+       digest = (unsigned char *) MALLOC(16 * sizeof (unsigned char *));
+       hmac_md5(buffer, buflen, vrrp->auth_data, sizeof (vrrp->auth_data)
+                , digest);
+       memcpy(ah->auth_data, digest, HMAC_MD5_TRUNC);
+
+       /* Restore the ip mutable fields */
+       ip->tos = ip_mutable_fields->tos;
+       ip->id = ip_mutable_fields->id;
+       ip->frag_off = ip_mutable_fields->frag_off;
+       ip->check = ip_mutable_fields->check;
+
+       FREE(ip_mutable_fields);
+       FREE(digest);
+}
+
+/* build VRRP header */
+static int
+vrrp_build_vrrp(vrrp_rt * vrrp, int prio, char *buffer, int buflen)
+{
+       int i;
+       vrrp_pkt *hd = (vrrp_pkt *) buffer;
+       uint32_t *iparr = (uint32_t *) ((char *) hd + sizeof (*hd));
+
+       hd->vers_type = (VRRP_VERSION << 4) | VRRP_PKT_ADVERT;
+       hd->vrid = vrrp->vrid;
+       hd->priority = prio;
+       hd->naddr = vrrp->naddr;
+       hd->auth_type = vrrp->auth_type;
+       hd->adver_int = vrrp->adver_int / TIMER_HZ;
+
+       /* copy the ip addresses */
+       for (i = 0; i < vrrp->naddr; i++) {
+               iparr[i] = htonl(vrrp->vaddr[i].addr);
+       }
+
+       /* copy the passwd if the authentication is VRRP_AH_PASS */
+       if (vrrp->auth_type == VRRP_AUTH_PASS) {
+               char *pw = (char *) hd + sizeof (*hd) + vrrp->naddr * 4;
+               memcpy(pw, vrrp->auth_data, sizeof (vrrp->auth_data));
+       }
+
+       /* finaly compute vrrp checksum */
+       hd->chksum = in_csum((u_short *) hd, vrrp_hd_len(vrrp), 0);
+
+       return (0);
+}
+
+/* build VRRP packet */
+static void
+vrrp_build_pkt(vrrp_rt * vrrp, int prio, char *buffer, int buflen)
+{
+       char *bufptr;
+
+       bufptr = buffer;
+
+       /* build the ethernet header */
+       vrrp_build_arp(vrrp, buffer, buflen);
+
+       /* build the ip header */
+       buffer += vrrp_dlt_len(vrrp);
+       buflen -= vrrp_dlt_len(vrrp);
+       vrrp_build_ip(vrrp, buffer, buflen);
+
+       /* build the vrrp header */
+       buffer += vrrp_iphdr_len(vrrp);
+
+       if (vrrp->auth_type == VRRP_AUTH_AH)
+               buffer += vrrp_ipsecah_len();
+       buflen -= vrrp_iphdr_len(vrrp);
+
+       if (vrrp->auth_type == VRRP_AUTH_AH)
+               buflen -= vrrp_ipsecah_len();
+       vrrp_build_vrrp(vrrp, prio, buffer, buflen);
+
+       /* build the IPSEC AH header */
+       if (vrrp->auth_type == VRRP_AUTH_AH) {
+               bufptr += vrrp_dlt_len(vrrp);
+               buflen += vrrp_ipsecah_len() + vrrp_iphdr_len(vrrp);;
+               vrrp_build_ipsecah(vrrp, bufptr, buflen);
+       }
+}
+
+/* send VRRP packet */
+static int
+vrrp_send_pkt(vrrp_rt * vrrp, char *buffer, int buflen)
+{
+       struct sockaddr from;
+       int len;
+       int fd = socket(PF_PACKET, SOCK_PACKET, 0x300); /* 0x300 is magic */
+
+       if (fd < 0) {
+               syslog(LOG_INFO, "VRRP Error : socket creation");
+               return -1;
+       }
+
+       /* build the address */
+       memset(&from, 0, sizeof (from));
+       strncpy(from.sa_data, IF_NAME(vrrp->ifp), IF_NAMESIZ);
+
+//print_buffer(buflen, buffer);
+
+       /* send the data */
+       len = sendto(fd, buffer, buflen, 0, &from, sizeof (from));
+
+       close(fd);
+       return len;
+}
+
+/* send VRRP advertissement */
+int
+vrrp_send_adv(vrrp_rt * vrrp, int prio)
+{
+       int buflen, ret;
+       char *buffer;
+
+       /* alloc the memory */
+       buflen = vrrp_dlt_len(vrrp) + vrrp_iphdr_len(vrrp) + vrrp_hd_len(vrrp);
+       if (vrrp->auth_type == VRRP_AUTH_AH)
+               buflen += vrrp_ipsecah_len();
+
+       buffer = MALLOC(buflen);
+
+       /* build the packet  */
+       vrrp_build_pkt(vrrp, prio, buffer, buflen);
+
+       /* send it */
+       ret = vrrp_send_pkt(vrrp, buffer, buflen);
+
+       /* free the memory */
+       FREE(buffer);
+       return ret;
+}
+
+/* Received packet processing */
+int
+vrrp_check_packet(vrrp_rt * vrrp, char *buf, int buflen)
+{
+       int ret;
+
+       if (buflen > 0) {
+               ret = vrrp_in_chk(vrrp, buf);
+
+               if (ret == VRRP_PACKET_DROP) {
+                       syslog(LOG_INFO, "Sync instance needed on %s !!!",
+                              IF_NAME(vrrp->ifp));
+               }
+
+               if (ret == VRRP_PACKET_KO)
+                       syslog(LOG_INFO, "bogus VRRP packet received on %s !!!",
+                              IF_NAME(vrrp->ifp));
+               return ret;
+       }
+
+       return VRRP_PACKET_NULL;
+}
+
+/* send a gratuitous ARP packet */
+static int
+send_gratuitous_arp(vrrp_rt * vrrp, int addr)
+{
+       struct m_arphdr {
+               unsigned short int ar_hrd;      /* Format of hardware address.  */
+               unsigned short int ar_pro;      /* Format of protocol address.  */
+               unsigned char ar_hln;   /* Length of hardware address.  */
+               unsigned char ar_pln;   /* Length of protocol address.  */
+               unsigned short int ar_op;       /* ARP opcode (command).  */
+               /* Ethernet looks like this : This bit is variable sized however...  */
+               unsigned char __ar_sha[ETH_ALEN];       /* Sender hardware address.  */
+               unsigned char __ar_sip[4];      /* Sender IP address.  */
+               unsigned char __ar_tha[ETH_ALEN];       /* Target hardware address.  */
+               unsigned char __ar_tip[4];      /* Target IP address.  */
+       };
+
+       char buf[sizeof (struct m_arphdr) + ETHER_HDR_LEN];
+       char buflen = sizeof (struct m_arphdr) + ETHER_HDR_LEN;
+       struct ether_header *eth = (struct ether_header *) buf;
+       struct m_arphdr *arph = (struct m_arphdr *) (buf + vrrp_dlt_len(vrrp));
+       char *hwaddr = IF_HWADDR(vrrp->ifp);
+       int hwlen = ETH_ALEN;
+
+       /* hardcoded for ethernet */
+       memset(eth->ether_dhost, 0xFF, ETH_ALEN);
+       memcpy(eth->ether_shost, hwaddr, hwlen);
+       eth->ether_type = htons(ETHERTYPE_ARP);
+
+       /* build the arp payload */
+       memset(arph, 0, sizeof (*arph));
+       arph->ar_hrd = htons(ARPHRD_ETHER);
+       arph->ar_pro = htons(ETHERTYPE_IP);
+       arph->ar_hln = 6;
+       arph->ar_pln = 4;
+       arph->ar_op = htons(ARPOP_REQUEST);
+       memcpy(arph->__ar_sha, hwaddr, hwlen);
+       memcpy(arph->__ar_sip, &addr, sizeof (addr));
+       memcpy(arph->__ar_tip, &addr, sizeof (addr));
+
+       return vrrp_send_pkt(vrrp, buf, buflen);
+}
+
+/* Gratuitous ARP on each VIP */
+void
+vrrp_send_gratuitous_arp(vrrp_rt * vrrp)
+{
+       int i, j;
+
+       /* send gratuitous arp for each virtual ip */
+       syslog(LOG_INFO, "VRRP_Instance(%s) Sending gratuitous ARP on %s",
+              vrrp->iname, IF_NAME(vrrp->ifp));
+
+       for (j = 0; j < 5; j++) {
+               for (i = 0; i < vrrp->naddr; i++)
+                       send_gratuitous_arp(vrrp, vrrp->vaddr[i].addr);
+               for (i = 0; i < vrrp->neaddr; i++)
+                       send_gratuitous_arp(vrrp, vrrp->evaddr[i].addr);
+       }
+}
+
+/* becoming master */
+void
+vrrp_state_become_master(vrrp_rt * vrrp)
+{
+       /* add the ip addresses */
+       if (vrrp->naddr)
+               vrrp_handle_ipaddress(vrrp, VRRP_IPADDRESS_ADD, VRRP_VIP_TYPE);
+       if (vrrp->neaddr)
+               vrrp_handle_ipaddress(vrrp, VRRP_IPADDRESS_ADD, VRRP_EVIP_TYPE);
+       vrrp->vipset = 1;
+
+       /* remotes arp tables update */
+       vrrp_send_gratuitous_arp(vrrp);
+
+       /* Check if notify is needed */
+       notify_instance_exec(vrrp, VRRP_STATE_MAST);
+
+#ifdef _HAVE_IPVS_SYNCD_
+       /* Check if sync daemon handling is needed */
+       if (vrrp->lvs_syncd_if)
+               ipvs_syncd_master(vrrp->lvs_syncd_if);
+#endif
+}
+
+void
+vrrp_state_goto_master(vrrp_rt * vrrp)
+{
+       /*
+        * Send an advertisement. To force a new master
+        * election.
+        */
+       vrrp_send_adv(vrrp, vrrp->priority);
+
+       if (vrrp->wantstate == VRRP_STATE_MAST) {
+               vrrp->state = VRRP_STATE_MAST;
+               syslog(LOG_INFO, "VRRP_Instance(%s) Transition to MASTER STATE",
+                      vrrp->iname);
+       } else {
+               vrrp->state = VRRP_STATE_DUMMY_MAST;
+               syslog(LOG_INFO,
+                      "VRRP_Instance(%s) Transition to DUMMY_MASTER STATE",
+                      vrrp->iname);
+       }
+}
+
+/* leaving master state */
+static void
+vrrp_restore_interface(vrrp_rt * vrrp, int advF)
+{
+       /* remove the ip addresses */
+       if (VRRP_VIP_ISSET(vrrp)) {
+               if (vrrp->naddr)
+                       vrrp_handle_ipaddress(vrrp, VRRP_IPADDRESS_DEL,
+                                             VRRP_VIP_TYPE);
+               if (vrrp->neaddr)
+                       vrrp_handle_ipaddress(vrrp, VRRP_IPADDRESS_DEL,
+                                             VRRP_EVIP_TYPE);
+               vrrp->vipset = 0;
+       }
+
+       /* if we stop vrrp, warn the other routers to speed up the recovery */
+       if (advF)
+               vrrp_send_adv(vrrp, VRRP_PRIO_STOP);
+}
+
+void
+vrrp_state_leave_master(vrrp_rt * vrrp)
+{
+       if (VRRP_VIP_ISSET(vrrp)) {
+#ifdef _HAVE_IPVS_SYNCD_
+               /* Check if sync daemon handling is needed */
+               if (vrrp->lvs_syncd_if)
+                       ipvs_syncd_backup(vrrp->lvs_syncd_if);
+#endif
+       }
+
+       /* set the new vrrp state */
+       switch (vrrp->wantstate) {
+       case VRRP_STATE_BACK:
+               syslog(LOG_INFO, "VRRP_Instance(%s) Entering BACKUP STATE",
+                      vrrp->iname);
+               vrrp_restore_interface(vrrp, 0);
+               vrrp->state = vrrp->wantstate;
+               notify_instance_exec(vrrp, VRRP_STATE_BACK);
+               break;
+       case VRRP_STATE_GOTO_FAULT:
+               syslog(LOG_INFO, "VRRP_Instance(%s) Entering FAULT STATE",
+                      vrrp->iname);
+               vrrp_restore_interface(vrrp, 0);
+               vrrp->state = VRRP_STATE_FAULT;
+               notify_instance_exec(vrrp, VRRP_STATE_FAULT);
+               break;
+       }
+}
+
+/* BACKUP state processing */
+void
+vrrp_state_backup(vrrp_rt * vrrp, char *buf, int buflen)
+{
+       struct iphdr *iph = (struct iphdr *) buf;
+       vrrp_pkt *hd = NULL;
+       int ret = 0;
+
+       /* Fill the VRRP header */
+       switch (iph->protocol) {
+       case IPPROTO_IPSEC_AH:
+               hd = (vrrp_pkt *) ((char *) iph + (iph->ihl << 2) +
+                                  vrrp_ipsecah_len());
+               break;
+       case IPPROTO_VRRP:
+               hd = (vrrp_pkt *) ((char *) iph + (iph->ihl << 2));
+               break;
+       }
+
+       /* Process the incoming packet */
+       ret = vrrp_check_packet(vrrp, buf, buflen);
+
+       if (ret == VRRP_PACKET_KO || ret == VRRP_PACKET_NULL) {
+               syslog(LOG_INFO,
+                      "VRRP_Instance(%s) ignoring received advertisment...",
+                      vrrp->iname);
+               vrrp->ms_down_timer =
+                   3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
+       } else if (hd->priority == 0) {
+               vrrp->ms_down_timer = VRRP_TIMER_SKEW(vrrp);
+       } else if (!vrrp->preempt || hd->priority >= vrrp->priority) {
+               vrrp->ms_down_timer =
+                   3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
+       } else if (hd->priority < vrrp->priority) {
+               vrrp->wantstate = VRRP_STATE_GOTO_MASTER;
+       }
+}
+
+/* MASTER state processing */
+void
+vrrp_state_master_tx(vrrp_rt * vrrp, const int prio)
+{
+       if (!VRRP_VIP_ISSET(vrrp)) {
+               syslog(LOG_INFO, "VRRP_Instance(%s) Entering MASTER STATE",
+                      vrrp->iname);
+               vrrp_state_become_master(vrrp);
+       }
+
+       vrrp_send_adv(vrrp,
+                     (prio ==
+                      VRRP_PRIO_OWNER) ? VRRP_PRIO_OWNER : vrrp->priority);
+}
+
+int
+vrrp_state_master_rx(vrrp_rt * vrrp, char *buf, int buflen)
+{
+       int ret = 0;
+       struct iphdr *iph = (struct iphdr *) buf;
+       vrrp_pkt *hd = NULL;
+
+       /* return on link failure */
+       if (vrrp->wantstate == VRRP_STATE_GOTO_FAULT) {
+               vrrp->ms_down_timer =
+                   3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
+               vrrp->state = VRRP_STATE_FAULT;
+               return 1;
+       }
+
+       /* Fill the VRRP header */
+       switch (iph->protocol) {
+       case IPPROTO_IPSEC_AH:
+               hd = (vrrp_pkt *) ((char *) iph + (iph->ihl << 2) +
+                                  vrrp_ipsecah_len());
+               break;
+       case IPPROTO_VRRP:
+               hd = (vrrp_pkt *) ((char *) iph + (iph->ihl << 2));
+               break;
+       }
+
+       /* Process the incoming packet */
+       ret = vrrp_check_packet(vrrp, buf, buflen);
+
+       if (ret == VRRP_PACKET_KO ||
+           ret == VRRP_PACKET_NULL || ret == VRRP_PACKET_DROP) {
+               syslog(LOG_INFO,
+                      "VRRP_Instance(%s) Dropping received VRRP packet...",
+                      vrrp->iname);
+               vrrp_send_adv(vrrp, vrrp->priority);
+               return 0;
+       } else if (hd->priority < vrrp->priority) {
+               /* We receive a lower prio adv we just refresh remote ARP cache */
+               syslog(LOG_INFO, "VRRP_Instance(%s) Received lower prio advert"
+                      ", forcing new election", vrrp->iname);
+               vrrp_send_adv(vrrp, vrrp->priority);
+               vrrp_send_gratuitous_arp(vrrp);
+               return 0;
+       } else if (hd->priority == 0) {
+               vrrp_send_adv(vrrp, vrrp->priority);
+               return 0;
+       } else if (hd->priority > vrrp->priority ||
+                  (hd->priority == vrrp->priority &&
+                   ntohl(iph->saddr) > VRRP_PKT_SADDR(vrrp))) {
+               syslog(LOG_INFO,
+                      "VRRP_Instance(%s) Received higher prio advert",
+                      vrrp->iname);
+               vrrp->ms_down_timer =
+                   3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
+               vrrp->state = VRRP_STATE_BACK;
+               return 1;
+       }
+
+       return 0;
+}
+
+int
+vrrp_state_fault_rx(vrrp_rt * vrrp, char *buf, int buflen)
+{
+       int ret = 0;
+       struct iphdr *iph = (struct iphdr *) buf;
+       vrrp_pkt *hd = NULL;
+
+       /* Fill the VRRP header */
+       switch (iph->protocol) {
+       case IPPROTO_IPSEC_AH:
+               hd = (vrrp_pkt *) ((char *) iph + (iph->ihl << 2) +
+                                  vrrp_ipsecah_len());
+               break;
+       case IPPROTO_VRRP:
+               hd = (vrrp_pkt *) ((char *) iph + (iph->ihl << 2));
+               break;
+       }
+
+       /* Process the incoming packet */
+       ret = vrrp_check_packet(vrrp, buf, buflen);
+
+       if (ret == VRRP_PACKET_KO ||
+           ret == VRRP_PACKET_NULL || ret == VRRP_PACKET_DROP) {
+               syslog(LOG_INFO,
+                      "VRRP_Instance(%s) Dropping received VRRP packet...",
+                      vrrp->iname);
+               vrrp_send_adv(vrrp, vrrp->priority);
+               return 0;
+       } else if (vrrp->priority > hd->priority ||
+                  hd->priority == VRRP_PRIO_OWNER)
+               return 1;
+
+       return 0;
+}
+
+/* check for minimum configuration requirements */
+static int
+chk_min_cfg(vrrp_rt * vrrp)
+{
+       if (vrrp->naddr == 0) {
+               syslog(LOG_INFO,
+                      "provide at least one ip for the virtual server");
+               return 0;
+       }
+       if (vrrp->vrid == 0) {
+               syslog(LOG_INFO, "the virtual id must be set!");
+               return 0;
+       }
+       if (!vrrp->ifp) {
+               syslog(LOG_INFO, "Unknown interface for instance %s !",
+                      vrrp->iname);
+               return 0;
+       }
+
+       return 1;
+}
+
+/* open the socket and join the multicast group. */
+int
+open_vrrp_socket(const int proto, const int index)
+{
+       struct ip_mreqn req_add;
+       interface *ifp;
+       int fd;
+       int ret;
+       int retry_num = 0;
+
+       /* Retreive interface */
+       ifp = if_get_by_ifindex(index);
+
+       /* Simply return if interface is shut */
+       if (!IF_ISUP(ifp))
+               return -1;
+
+       /* open the socket */
+       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)",
+                      err);
+               return -1;
+       }
+
+       /* -> inbound processing option
+        * Specify the bound_dev_if.
+        * why IP_ADD_MEMBERSHIP & IP_MULTICAST_IF doesnt set
+        * sk->bound_dev_if themself ??? !!!
+        * Needed for filter multicasted advert per interface.
+        * 
+        * -- If you read this !!! and know the answer to the question
+        *    please feel free to answer me ! :)
+        */
+       ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, IF_NAME(ifp)
+                        , strlen(IF_NAME(ifp)) + 1);
+       if (ret < 0) {
+               int err = errno;
+               syslog(LOG_INFO,
+                      "cant bind to device %s. errno=%d. (try to run it as root)",
+                      IF_NAME(ifp)
+                      , err);
+               close(fd);
+               return -1;
+       }
+
+       /* -> outbound processing option
+        * join the multicast group.
+        * binding the socket to the interface for outbound multicast
+        * traffic.
+        */
+       memset(&req_add, 0, sizeof (req_add));
+       req_add.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);
+       req_add.imr_address.s_addr = IF_ADDR(ifp);
+       req_add.imr_ifindex = IF_INDEX(ifp);
+
+       /* -> Need to handle multicast convergance after takeover.
+        * We retry until multicast is available on the interface.
+        * After VRRP_MCAST_RETRY we assume interface doesn't support
+        * multicast then exist with error.
+        * -> This can sound a little nasty since it degrade a little
+        * the global scheduling timers.
+        */
+moretry:
+       ret =
+           setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &req_add,
+                      sizeof (struct ip_mreqn));
+       if (ret < 0) {
+               syslog(LOG_INFO, "cant do IP_ADD_MEMBERSHIP errno=%s (%d)",
+                      strerror(errno), errno);
+               if (errno == 19) {
+                       retry_num++;
+                       if (retry_num > VRRP_MCAST_RETRY) {
+                               syslog(LOG_INFO,
+                                      "cant do IP_ADD_MEMBERSHIP after %d retry errno=%s",
+                                      VRRP_MCAST_RETRY, strerror(errno));
+                               return -1;
+                       }
+                       sleep(1);       /* FIXME: Beurk... Very nasty... !!! */
+                       goto moretry;
+               }
+               return -1;
+       }
+
+       return fd;
+}
+
+void
+close_vrrp_socket(vrrp_rt * vrrp)
+{
+       struct ip_mreqn req_add;
+       int ret = 0;
+
+       /* Leaving the VRRP multicast group */
+       memset(&req_add, 0, sizeof (req_add));
+       req_add.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);
+       req_add.imr_address.s_addr = IF_ADDR(vrrp->ifp);
+       req_add.imr_ifindex = IF_INDEX(vrrp->ifp);
+       ret =
+           setsockopt(vrrp->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+                      (char *) &req_add, sizeof (struct ip_mreqn));
+       if (ret < 0) {
+               syslog(LOG_INFO, "cant do IP_DROP_MEMBERSHIP errno=%s (%d)",
+                      strerror(errno)
+                      , errno);
+               return;
+       }
+
+       /* Finally close the desc */
+       close(vrrp->fd);
+}
+
+void
+new_vrrp_socket(vrrp_rt * vrrp)
+{
+       int old_fd = vrrp->fd;
+       list p = conf_data->vrrp;
+       vrrp_rt *vrrp_ptr;
+       element e;
+
+       /* close the desc & open a new one */
+       close_vrrp_socket(vrrp);
+       if (vrrp->auth_type == VRRP_AUTH_AH)
+               vrrp->fd =
+                   open_vrrp_socket(IPPROTO_IPSEC_AH, IF_INDEX(vrrp->ifp));
+       else
+               vrrp->fd = open_vrrp_socket(IPPROTO_VRRP, IF_INDEX(vrrp->ifp));
+
+       /* Sync the other desc */
+       for (e = LIST_HEAD(p); e; ELEMENT_NEXT(e)) {
+               vrrp_ptr = ELEMENT_DATA(e);
+               if (vrrp_ptr->fd == old_fd)
+                       vrrp_ptr->fd = vrrp->fd;
+       }
+}
+
+/* handle terminate state */
+void
+shutdown_vrrp_instances(void)
+{
+       list l = conf_data->vrrp;
+       element e;
+       vrrp_rt *vrrp;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               vrrp = ELEMENT_DATA(e);
+
+               /* remove VIPs */
+               if (vrrp->state == VRRP_STATE_MAST ||
+                   vrrp->state == VRRP_STATE_DUMMY_MAST)
+                       vrrp_restore_interface(vrrp, 1);
+
+#ifdef _HAVE_IPVS_SYNCD_
+               /* Stop stalled syncd */
+               if (vrrp->lvs_syncd_if)
+                       ipvs_syncd_cmd(IPVS_STOPDAEMON, NULL, 0);
+#endif
+       }
+}
+
+/* complete vrrp structure */
+static int
+vrrp_complete_instance(vrrp_rt * vrrp)
+{
+       /* complete the VMAC address */
+       vrrp->hwaddr[0] = 0x00;
+       vrrp->hwaddr[1] = 0x00;
+       vrrp->hwaddr[2] = 0x5E;
+       vrrp->hwaddr[3] = 0x00;
+       vrrp->hwaddr[4] = 0x01;
+       vrrp->hwaddr[5] = vrrp->vrid;
+
+       vrrp->state = VRRP_STATE_INIT;
+       if (!vrrp->adver_int)
+               vrrp->adver_int = VRRP_ADVER_DFL * TIMER_HZ;
+       if (!vrrp->priority)
+               vrrp->priority = VRRP_PRIO_DFL;
+       if (!vrrp->preempt)
+               vrrp->preempt = VRRP_PREEMPT_DFL;
+
+       return (chk_min_cfg(vrrp));
+}
+
+int
+vrrp_complete_init(void)
+{
+       list l = conf_data->vrrp;
+       element e;
+       vrrp_rt *vrrp;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               vrrp = ELEMENT_DATA(e);
+               if (!vrrp_complete_instance(vrrp))
+                       return 0;
+       }
+       return 1;
+}
diff --git a/keepalived/vrrp/vrrp_if.c b/keepalived/vrrp/vrrp_if.c
new file mode 100644 (file)
index 0000000..ed10b3f
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        Interfaces manipulation.
+ *
+ * Version:     $Id: vrrp_if.c,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
+ *
+ * Author:      Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+/* global include */
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+typedef __uint64_t u64;
+typedef __uint32_t u32;
+typedef __uint16_t u16;
+typedef __uint8_t u8;
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/ip.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <ctype.h>
+#ifdef use_linux_libc5
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#ifdef _KRNL_2_4_
+#include <linux/ethtool.h>
+#endif
+
+/* local include */
+#include "scheduler.h"
+#include "data.h"
+#include "vrrp_if.h"
+#include "vrrp_netlink.h"
+#include "memory.h"
+#include "utils.h"
+
+/* Global vars */
+extern thread_master *master;
+extern data *conf_data;
+static struct ifreq ifr;
+
+/* Helper functions */
+/* Return interface from interface index */
+interface *
+if_get_by_ifindex(const int ifindex)
+{
+       interface *ifp;
+       element e;
+
+       for (e = LIST_HEAD(if_queue); e; ELEMENT_NEXT(e)) {
+               ifp = ELEMENT_DATA(e);
+               if (ifp->ifindex == ifindex)
+                       return ifp;
+       }
+       return NULL;
+}
+
+interface *
+if_get_by_ifname(const char *ifname)
+{
+       interface *ifp;
+       element e;
+
+       for (e = LIST_HEAD(if_queue); e; ELEMENT_NEXT(e)) {
+               ifp = ELEMENT_DATA(e);
+               if (!strcmp(ifp->ifname, ifname))
+                       return ifp;
+       }
+       return NULL;
+}
+
+/* MII Transceiver Registers poller functions */
+static int
+if_mii_read(const int fd, const int phy_id, int location)
+{
+       uint16_t *data = (uint16_t *) (&ifr.ifr_data);
+
+       data[0] = phy_id;
+       data[1] = location;
+
+       if (ioctl(fd, SIOCGMIIREG, &ifr) < 0) {
+               syslog(LOG_ERR, "SIOCGMIIREG on %s failed: %s", ifr.ifr_name,
+                      strerror(errno));
+               return -1;
+       }
+       return data[3];
+}
+
+/*
+static void if_mii_dump(const uint16_t mii_regs[32], unsigned phy_id)
+{
+  int mii_reg;
+
+  printf(" MII PHY #%d transceiver registers:\n", phy_id);
+  for (mii_reg = 0; mii_reg < 32; mii_reg++)
+    printf("%s %4.4x", (mii_reg % 8) == 0 ? "\n ":"", mii_regs[mii_reg]);
+}
+*/
+
+static int
+if_mii_status(const int fd)
+{
+       uint16_t *data = (uint16_t *) (&ifr.ifr_data);
+       unsigned phy_id = data[0];
+       uint16_t mii_regs[32];
+       int mii_reg;
+       uint16_t bmsr, new_bmsr;
+
+       /* Reset MII registers */
+       memset(mii_regs, 0, sizeof (mii_regs));
+
+       for (mii_reg = 0; mii_reg < 32; mii_reg++)
+               mii_regs[mii_reg] = if_mii_read(fd, phy_id, mii_reg);
+
+// if_mii_dump(mii_regs, phy_id);
+
+       if (mii_regs[0] == 0xffff) {
+               syslog(LOG_ERR, "No MII transceiver present for %s !!!",
+                      ifr.ifr_name);
+               return -1;
+       }
+
+       bmsr = mii_regs[1];
+
+       /*
+        * For Basic Mode Status Register (BMSR).
+        * Sticky field (Link established & Jabber detected), we need to read
+        * a second time the BMSR to get current status.
+        */
+       new_bmsr = if_mii_read(fd, phy_id, 1);
+
+// printf(" \nBasic Mode Status Register 0x%4.4x ... 0x%4.4x\n", bmsr, new_bmsr);
+
+       if (bmsr & 0x0004)
+               return LINK_UP;
+       else if (new_bmsr & 0x0004)
+               return LINK_UP;
+       else
+               return LINK_DOWN;
+}
+
+int
+if_mii_probe(const char *ifname)
+{
+       int fd = socket(AF_INET, SOCK_DGRAM, 0);
+       int status = 0;
+
+       if (fd < 0)
+               return -1;
+       memset(&ifr, 0, sizeof (struct ifreq));
+       strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+       if (ioctl(fd, SIOCGMIIPHY, &ifr) < 0) {
+               close(fd);
+               return -1;
+       }
+
+       /* Dump the MII transceiver */
+       status = if_mii_status(fd);
+       close(fd);
+       return status;
+}
+
+static int
+if_ethtool_status(const int fd)
+{
+#ifdef _KRNL_2_4_
+       struct ethtool_value edata;
+       int err = 0;
+
+       edata.cmd = ETHTOOL_GLINK;
+       ifr.ifr_data = (caddr_t) & edata;
+       err = ioctl(fd, SIOCETHTOOL, &ifr);
+       if (err == 0)
+               return (edata.data) ? 1 : 0;
+       else
+#endif
+               return -1;
+}
+
+int
+if_ethtool_probe(const char *ifname)
+{
+       int fd = socket(AF_INET, SOCK_DGRAM, 0);
+       int status = 0;
+
+       if (fd < 0)
+               return -1;
+       memset(&ifr, 0, sizeof (struct ifreq));
+       strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+
+       status = if_ethtool_status(fd);
+       close(fd);
+       return status;
+}
+
+void
+if_ioctl_flags(interface * ifp)
+{
+       int fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+       if (fd < 0)
+               return;
+       memset(&ifr, 0, sizeof (struct ifreq));
+       strncpy(ifr.ifr_name, ifp->ifname, sizeof (ifr.ifr_name));
+       if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+               close(fd);
+               return;
+       }
+       ifp->flags = ifr.ifr_flags;
+       close(fd);
+}
+
+/* Interfaces lookup */
+static void
+free_if(void *data)
+{
+       FREE(data);
+}
+
+void
+dump_if(void *data)
+{
+       interface *ifp = data;
+
+       syslog(LOG_INFO, "------< NIC >------");
+       syslog(LOG_INFO, " Name = %s", ifp->ifname);
+       syslog(LOG_INFO, " index = %d", ifp->ifindex);
+       syslog(LOG_INFO, " address = %s", inet_ntop2(ifp->address));
+
+       /* FIXME: Harcoded for ethernet */
+       if (ifp->hw_type == ARPHRD_ETHER)
+               syslog(LOG_INFO, " MAC = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+                      ifp->hw_addr[0], ifp->hw_addr[1], ifp->hw_addr[2]
+                      , ifp->hw_addr[3], ifp->hw_addr[4], ifp->hw_addr[5]);
+
+       if (ifp->flags & IFF_UP)
+               syslog(LOG_INFO, " is UP");
+
+       if (ifp->flags & IFF_RUNNING)
+               syslog(LOG_INFO, " is RUNNING");
+
+       if (!(ifp->flags & IFF_UP) && !(ifp->flags & IFF_RUNNING))
+               syslog(LOG_INFO, " is DOWN");
+
+       syslog(LOG_INFO, " MTU = %d", ifp->mtu);
+
+       switch (ifp->hw_type) {
+       case ARPHRD_LOOPBACK:
+               syslog(LOG_INFO, " HW Type = LOOPBACK");
+               break;
+       case ARPHRD_ETHER:
+               syslog(LOG_INFO, " HW Type = ETHERNET");
+               break;
+       default:
+               syslog(LOG_INFO, " HW Type = UNKNOWN");
+               break;
+       }
+
+       /* MII channel supported ? */
+       if (IF_MII_SUPPORTED(ifp))
+               syslog(LOG_INFO, " NIC support MII regs");
+       else if (IF_ETHTOOL_SUPPORTED(ifp))
+               syslog(LOG_INFO, " NIC support EHTTOOL GLINK interface");
+       else
+               syslog(LOG_INFO, " Enabling NIC ioctl refresh polling");
+}
+
+static void
+init_if_queue(void)
+{
+       if_queue = alloc_list(free_if, dump_if);
+}
+
+void
+if_add_queue(interface * ifp)
+{
+       list_add(if_queue, ifp);
+}
+
+static void
+init_if_mii(void)
+{
+       interface *ifp;
+       element e;
+       int status;
+
+       for (e = LIST_HEAD(if_queue); e; ELEMENT_NEXT(e)) {
+               ifp = ELEMENT_DATA(e);
+               ifp->lb_type = LB_IOCTL;
+               status = if_mii_probe(ifp->ifname);
+               if (status >= 0) {
+                       ifp->lb_type = LB_MII;
+                       ifp->linkbeat = (status) ? 1 : 0;
+               } else {
+                       status = if_ethtool_probe(ifp->ifname);
+                       if (status >= 0) {
+                               ifp->lb_type = LB_ETHTOOL;
+                               ifp->linkbeat = (status) ? 1 : 0;
+                       }
+               }
+       }
+}
+
+static void
+if_linkbeat_refresh(void)
+{
+       interface *ifp;
+       element e;
+
+       for (e = LIST_HEAD(if_queue); e; ELEMENT_NEXT(e)) {
+               ifp = ELEMENT_DATA(e);
+               if (IF_MII_SUPPORTED(ifp))
+                       ifp->linkbeat = (if_mii_probe(ifp->ifname)) ? 1 : 0;
+               else if (IF_ETHTOOL_SUPPORTED(ifp))
+                       ifp->linkbeat = (if_ethtool_probe(ifp->ifname)) ? 1 : 0;
+               else
+                       if_ioctl_flags(ifp);
+       }
+}
+
+int
+if_linkbeat(const interface * ifp)
+{
+       if (IF_MII_SUPPORTED(ifp) || IF_ETHTOOL_SUPPORTED(ifp))
+               return IF_LINKBEAT(ifp);
+       return 1;
+}
+
+/* Our interface Heartbeat thread */
+int
+if_monitor_thread(thread * thread)
+{
+       /* If present, refresh link beat status from MII BMSR */
+       if_linkbeat_refresh();
+
+       /* Register new monitor thread */
+       thread_add_timer(master, if_monitor_thread, NULL, POLLING_DELAY);
+       return 0;
+}
+
+/* Interface queue helpers*/
+void
+free_interface_queue(void)
+{
+       if (!LIST_ISEMPTY(if_queue))
+               free_list(if_queue);
+       netlink_close(&nl_kernel);
+}
+
+void
+init_interface_queue(void)
+{
+       init_if_queue();
+       netlink_interface_lookup();
+       init_if_mii();
+}
+
+void
+if_mii_poller_init(void)
+{
+//     dump_list(if_queue);
+
+       /* Register NIC Heartbeat monitoring thread */
+       thread_add_timer(master, if_monitor_thread, NULL, POLLING_DELAY);
+}
similarity index 57%
rename from vrrp_ipaddress.c
rename to keepalived/vrrp/vrrp_ipaddress.c
index 7c361f3..ad1b9f4 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        NETLINK IPv4 address manipulation.
  *
- * Version:     $Id: vrrp_ipaddress.c,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
+ * Version:     $Id: vrrp_ipaddress.c,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include "utils.h"
 
 /* Add/Delete IP address to a specific interface */
-int netlink_address_ipv4(int ifindex, uint32_t addr, uint8_t mask, int cmd)
+int
+netlink_address_ipv4(int ifindex, uint32_t addr, uint8_t mask, int cmd)
 {
-  struct nl_handle nlh;
-  int status = 1;
-  struct {
-    struct nlmsghdr n;
-    struct ifaddrmsg ifa;
-    char buf[256];
-  } req;
+       struct nl_handle nlh;
+       int status = 1;
+       struct {
+               struct nlmsghdr n;
+               struct ifaddrmsg ifa;
+               char buf[256];
+       } req;
 
-  memset(&req, 0, sizeof(req));
+       memset(&req, 0, sizeof (req));
 
-  req.n.nlmsg_len    = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
-  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  = ifindex;
-  req.ifa.ifa_prefixlen = mask;
-  addattr_l(&req.n, sizeof(req), IFA_LOCAL, &addr, sizeof(addr));
+       req.n.nlmsg_len = NLMSG_LENGTH(sizeof (struct ifaddrmsg));
+       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 = ifindex;
+       req.ifa.ifa_prefixlen = mask;
+       addattr_l(&req.n, sizeof (req), IFA_LOCAL, &addr, sizeof (addr));
 
-  if (netlink_socket(&nlh, 0) < 0)
-    return -1;
+       if (netlink_socket(&nlh, 0) < 0)
+               return -1;
 
-  if (netlink_talk(&nlh, &req.n) < 0)
-    status = -1;
+       if (netlink_talk(&nlh, &req.n) < 0)
+               status = -1;
 
-  /* to close the clocket */
-  netlink_close(&nlh);
-  return status;
+       /* to close the clocket */
+       netlink_close(&nlh);
+       return status;
 }
diff --git a/keepalived/vrrp/vrrp_ipsecah.c b/keepalived/vrrp/vrrp_ipsecah.c
new file mode 100644 (file)
index 0000000..689597e
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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:        IPSEC AH implementation according to RFC 2402. Processing
+ *              authentication data encryption using HMAC MD5 according to
+ *              RFCs 2085 & 2104.
+ *
+ * Version:     $Id: vrrp_ipsecah.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "vrrp_ipsecah.h"
+#include <openssl/md5.h>
+
+/* hmac_md5 computation according to the RFCs 2085 & 2104 */
+void
+hmac_md5(unsigned char *buffer, int buffer_len, unsigned char *key, int key_len,
+        unsigned char *digest)
+{
+       MD5_CTX context;
+       unsigned char k_ipad[65];       /* inner padding - key XORd with ipad */
+       unsigned char k_opad[65];       /* outer padding - key XORd with opad */
+       unsigned char tk[16];
+       int i;
+
+       /* Initialize data */
+       memset(k_ipad, 0, sizeof (k_ipad));
+       memset(k_opad, 0, sizeof (k_opad));
+       memset(tk, 0, sizeof (tk));
+
+       /* If the key is longer than 64 bytes => set it to key=MD5(key) */
+       if (key_len > 64) {
+               MD5_CTX tctx;
+
+               /* Compute the MD5 digest */
+               MD5_Init(&tctx);
+               MD5_Update(&tctx, key, key_len);
+               MD5_Final(tk, &tctx);
+
+               key = tk;
+               key_len = 16;
+       }
+
+       /* The global HMAC_MD5 algo looks like (rfc2085.2.2) :
+          MD5(K XOR opad, MD5(K XOR ipad, buffer))
+          K : an n byte key
+          ipad : byte 0x36 repeated 64 times
+          opad : byte 0x5c repeated 64 times
+          buffer : buffer being protected
+        */
+       memset(k_ipad, 0, sizeof (k_ipad));
+       memset(k_opad, 0, sizeof (k_opad));
+       memcpy(k_ipad, key, key_len);
+       memcpy(k_opad, key, key_len);
+
+       /* XOR key with ipad and opad values */
+       for (i = 0; i < 64; i++) {
+               k_ipad[i] ^= 0x36;
+               k_opad[i] ^= 0x5c;
+       }
+
+       /* Compute inner MD5 */
+       MD5_Init(&context);                             /* Init context for 1st pass */
+       MD5_Update(&context, k_ipad, 64);               /* start with inner pad */
+       MD5_Update(&context, buffer, buffer_len);       /* next with buffer datagram */
+       MD5_Final(digest, &context);                    /* Finish 1st pass */
+
+       /* Compute outer MD5 */
+       MD5_Init(&context);                     /* Init context for 2nd pass */
+       MD5_Update(&context, k_opad, 64);       /* start with inner pad */
+       MD5_Update(&context, digest, 16);       /* next result of 1st pass */
+       MD5_Final(digest, &context);            /* Finish 2nd pass */
+}
diff --git a/keepalived/vrrp/vrrp_netlink.c b/keepalived/vrrp/vrrp_netlink.c
new file mode 100644 (file)
index 0000000..e927a2b
--- /dev/null
@@ -0,0 +1,558 @@
+/*
+ * 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:        NETLINK kernel command channel.
+ *
+ * Version:     $Id: vrrp_netlink.c,v 0.6.5 2002/07/01 23:41:28 acassen Exp $
+ *
+ * Author:      Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+/* global include */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <net/if_arp.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/uio.h>
+
+/* local include */
+#include "check_api.h"
+#include "vrrp_netlink.h"
+#include "vrrp_if.h"
+#include "memory.h"
+#include "scheduler.h"
+#include "utils.h"
+
+/* Global vars */
+extern thread_master *master;
+
+/* Create a socket to netlink interface */
+int
+netlink_socket(struct nl_handle *nl, unsigned long groups)
+{
+       int addr_len;
+       int ret;
+
+       memset(nl, 0, sizeof (nl));
+
+       nl->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+       if (nl->fd < 0) {
+               syslog(LOG_INFO, "Netlink: Cannot open netlink socket : (%s)",
+                      strerror(errno));
+               return -1;
+       }
+
+       ret = fcntl(nl->fd, F_SETFL, O_NONBLOCK);
+       if (ret < 0) {
+               syslog(LOG_INFO,
+                      "Netlink: Cannot set netlink socket flags : (%s)",
+                      strerror(errno));
+               close(nl->fd);
+               return -1;
+       }
+
+       memset(&nl->snl, 0, sizeof (nl->snl));
+       nl->snl.nl_family = AF_NETLINK;
+       nl->snl.nl_groups = groups;
+
+       ret = bind(nl->fd, (struct sockaddr *) &nl->snl, sizeof (nl->snl));
+       if (ret < 0) {
+               syslog(LOG_INFO, "Netlink: Cannot bind netlink socket : (%s)",
+                      strerror(errno));
+               close(nl->fd);
+               return -1;
+       }
+
+       addr_len = sizeof (nl->snl);
+       ret = getsockname(nl->fd, (struct sockaddr *) &nl->snl, &addr_len);
+       if (ret < 0 || addr_len != sizeof (nl->snl)) {
+               syslog(LOG_INFO, "Netlink: Cannot getsockname : (%s)",
+                      strerror(errno));
+               close(nl->fd);
+               return -1;
+       }
+
+       if (nl->snl.nl_family != AF_NETLINK) {
+               syslog(LOG_INFO, "Netlink: Wrong address family %d",
+                      nl->snl.nl_family);
+               close(nl->fd);
+               return -1;
+       }
+
+       nl->seq = time(NULL);
+
+       return ret;
+}
+
+/* Close a netlink socket */
+int
+netlink_close(struct nl_handle *nl)
+{
+       close(nl->fd);
+       return 0;
+}
+
+/* iproute2 utility function */
+int
+addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
+{
+       int len = RTA_LENGTH(alen);
+       struct rtattr *rta;
+
+       if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
+               return -1;
+
+       rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN(n->nlmsg_len));
+       rta->rta_type = type;
+       rta->rta_len = len;
+       memcpy(RTA_DATA(rta), data, alen);
+       n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
+
+       return 0;
+}
+
+static void
+parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len)
+{
+       while (RTA_OK(rta, len)) {
+               if (rta->rta_type <= max)
+                       tb[rta->rta_type] = rta;
+               rta = RTA_NEXT(rta, len);
+       }
+}
+
+/* Our netlink parser */
+static int
+netlink_parse_info(int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
+                  struct nl_handle *nl)
+{
+       int status;
+       int ret = 0;
+       int error;
+
+       while (1) {
+               char buf[4096];
+               struct iovec iov = { buf, sizeof buf };
+               struct sockaddr_nl snl;
+               struct msghdr msg =
+                   { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
+               struct nlmsghdr *h;
+
+               status = recvmsg(nl->fd, &msg, 0);
+
+               if (status < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       if (errno == EWOULDBLOCK)
+                               break;
+                       syslog(LOG_INFO, "Netlink: Received message overrun");
+                       continue;
+               }
+
+               if (status == 0) {
+                       syslog(LOG_INFO, "Netlink: EOF");
+                       return -1;
+               }
+
+               if (msg.msg_namelen != sizeof snl) {
+                       syslog(LOG_INFO,
+                              "Netlink: Sender address length error: length %d",
+                              msg.msg_namelen);
+                       return -1;
+               }
+
+               for (h = (struct nlmsghdr *) buf; NLMSG_OK(h, status);
+                    h = NLMSG_NEXT(h, status)) {
+                       /* Finish of reading. */
+                       if (h->nlmsg_type == NLMSG_DONE)
+                               return ret;
+
+                       /* Error handling. */
+                       if (h->nlmsg_type == NLMSG_ERROR) {
+                               struct nlmsgerr *err =
+                                   (struct nlmsgerr *) NLMSG_DATA(h);
+                               if (h->nlmsg_len <
+                                   NLMSG_LENGTH(sizeof (struct nlmsgerr))) {
+                                       syslog(LOG_INFO,
+                                              "Netlink: error: message truncated");
+                                       return -1;
+                               }
+                               syslog(LOG_INFO,
+                                      "Netlink: error: %s, type=(%u), seq=%u, pid=%d",
+                                      strerror(-err->error),
+                                      err->msg.nlmsg_type,
+                                      err->msg.nlmsg_seq, err->msg.nlmsg_pid);
+
+                               return -1;
+                       }
+
+                       error = (*filter) (&snl, h);
+                       if (error < 0) {
+                               syslog(LOG_INFO,
+                                      "Netlink: filter function error");
+                               ret = error;
+                       }
+               }
+
+               /* After error care. */
+               if (msg.msg_flags & MSG_TRUNC) {
+                       syslog(LOG_INFO, "Netlink: error: message truncated");
+                       continue;
+               }
+               if (status) {
+                       syslog(LOG_INFO, "Netlink: error: data remnant size %d",
+                              status);
+                       return -1;
+               }
+       }
+
+       return ret;
+}
+
+/* Out talk filter */
+static int
+netlink_talk_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
+{
+       syslog(LOG_INFO, "Netlink: ignoring message type 0x%04x",
+              h->nlmsg_type);
+       return 0;
+}
+
+/* send message to netlink kernel socket, then receive response */
+int
+netlink_talk(struct nl_handle *nl, struct nlmsghdr *n)
+{
+       int status;
+       struct sockaddr_nl snl;
+       struct iovec iov = { (void *) n, n->nlmsg_len };
+       struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
+
+       memset(&snl, 0, sizeof snl);
+       snl.nl_family = AF_NETLINK;
+
+       n->nlmsg_seq = ++nl->seq;
+
+       /* Send message to netlink interface. */
+       status = sendmsg(nl->fd, &msg, 0);
+       if (status < 0) {
+               syslog(LOG_INFO, "Netlink: sendmsg() error: %s",
+                      strerror(errno));
+               return -1;
+       }
+
+       status = netlink_parse_info(netlink_talk_filter, nl);
+       return status;
+}
+
+/* Fetch a specific type information from netlink kernel */
+static int
+netlink_request(struct nl_handle *nl, int family, int type)
+{
+       int status;
+       struct sockaddr_nl snl;
+       struct {
+               struct nlmsghdr nlh;
+               struct rtgenmsg g;
+       } req;
+
+       /* Cleanup the room */
+       memset(&snl, 0, sizeof (snl));
+       snl.nl_family = AF_NETLINK;
+
+       req.nlh.nlmsg_len = sizeof (req);
+       req.nlh.nlmsg_type = type;
+       req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
+       req.nlh.nlmsg_pid = 0;
+       req.nlh.nlmsg_seq = ++nl->seq;
+       req.g.rtgen_family = family;
+
+       status = sendto(nl->fd, (void *) &req, sizeof (req)
+                       , 0, (struct sockaddr *) &snl, sizeof (snl));
+       if (status < 0) {
+               syslog(LOG_INFO, "Netlink: sendto() failed: %s",
+                      strerror(errno));
+               return -1;
+       }
+       return 0;
+}
+
+/* Netlink interface link lookup filter */
+static int
+netlink_if_link_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
+{
+       struct ifinfomsg *ifi;
+       struct rtattr *tb[IFLA_MAX + 1];
+       interface *ifp;
+       int i, len;
+       char *name;
+
+       ifi = NLMSG_DATA(h);
+
+       if (h->nlmsg_type != RTM_NEWLINK)
+               return 0;
+
+       len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifinfomsg));
+       if (len < 0)
+               return -1;
+
+       /* Interface name lookup */
+       memset(tb, 0, sizeof (tb));
+       parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+       if (tb[IFLA_IFNAME] == NULL)
+               return -1;
+       name = (char *) RTA_DATA(tb[IFLA_IFNAME]);
+
+       /* Return if loopback */
+       if (ifi->ifi_type == ARPHRD_LOOPBACK)
+               return 0;
+
+       /* Fill the interface structure */
+       ifp = (interface *) MALLOC(sizeof (interface));
+       memcpy(ifp->ifname, name, strlen(name));
+       ifp->ifindex = ifi->ifi_index;
+       ifp->flags = ifi->ifi_flags;
+       ifp->mtu = *(int *) RTA_DATA(tb[IFLA_MTU]);
+       ifp->hw_type = ifi->ifi_type;
+
+       if (tb[IFLA_ADDRESS]) {
+               int hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
+
+               if (hw_addr_len > IF_HWADDR_MAX)
+                       syslog(LOG_ERR, "MAC address for %s is too large: %d",
+                              name, hw_addr_len);
+               else {
+                       ifp->hw_addr_len = hw_addr_len;
+                       memcpy(ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]),
+                              hw_addr_len);
+                       for (i = 0; i < hw_addr_len; i++)
+                               if (ifp->hw_addr[i] != 0)
+                                       break;
+                       if (i == hw_addr_len)
+                               ifp->hw_addr_len = 0;
+                       else
+                               ifp->hw_addr_len = hw_addr_len;
+               }
+       }
+
+       /* Queue this new interface */
+       if_add_queue(ifp);
+       return 0;
+}
+
+/*
+ * Netlink interface address lookup filter
+ * We need to handle multiple primary address and
+ * multiple secondary address to the same interface.
+ */
+static int
+netlink_if_address_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
+{
+       struct ifaddrmsg *ifa;
+       struct rtattr *tb[IFA_MAX + 1];
+       interface *ifp;
+       uint32_t address = 0;
+       int len;
+
+       ifa = NLMSG_DATA(h);
+
+       /* Only IPV4 are valid us */
+       if (ifa->ifa_family != AF_INET)
+               return 0;
+
+       if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
+               return 0;
+
+       len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifaddrmsg));
+       if (len < 0)
+               return -1;
+
+       memset(tb, 0, sizeof (tb));
+       parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len);
+
+       /* Fetch interface */
+       ifp = if_get_by_ifindex(ifa->ifa_index);
+       if (!ifp)
+               return 0;
+
+       if (tb[IFA_ADDRESS] == NULL)
+               tb[IFA_ADDRESS] = tb[IFA_LOCAL];
+
+       if (ifp->flags & IFF_POINTOPOINT) {
+               if (tb[IFA_LOCAL])
+                       address = *(uint32_t *) RTA_DATA(tb[IFA_LOCAL]);
+       } else {
+               if (tb[IFA_ADDRESS])
+                       address = *(uint32_t *) RTA_DATA(tb[IFA_ADDRESS]);
+       }
+
+       /* If no address is set on interface then set the first time */
+       if (!ifp->address)
+               ifp->address = address;
+
+#ifdef _WITH_LVS_
+       /* Refresh checkers state */
+       update_checker_activity(address,
+                               (h->nlmsg_type == RTM_NEWADDR) ? 1 : 0);
+#endif
+
+       return 0;
+}
+
+/* Interfaces lookup bootstrap function */
+int
+netlink_interface_lookup(void)
+{
+       struct nl_handle nlh;
+       int status = 0;
+
+       if (netlink_socket(&nlh, 0) < 0)
+               return -1;
+
+       /* Interface lookup */
+       if (netlink_request(&nlh, AF_PACKET, RTM_GETLINK) < 0) {
+               status = -1;
+               goto end_int;
+       }
+       status = netlink_parse_info(netlink_if_link_filter, &nlh);
+
+end_int:
+       netlink_close(&nlh);
+       return status;
+}
+
+/* Adresses lookup bootstrap function */
+static int
+netlink_address_lookup(void)
+{
+       struct nl_handle nlh;
+       int status = 0;
+
+       if (netlink_socket(&nlh, 0) < 0)
+               return -1;
+
+       /* Address lookup */
+       if (netlink_request(&nlh, AF_INET, RTM_GETADDR) < 0) {
+               status = -1;
+               goto end_addr;
+       }
+       status = netlink_parse_info(netlink_if_address_filter, &nlh);
+
+end_addr:
+       netlink_close(&nlh);
+       return status;
+}
+
+/* Netlink flag Link update */
+static int
+netlink_reflect_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
+{
+       struct ifinfomsg *ifi;
+       struct rtattr *tb[IFLA_MAX + 1];
+       interface *ifp;
+       int len;
+
+       ifi = NLMSG_DATA(h);
+       if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
+               return 0;
+
+       len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifinfomsg));
+       if (len < 0)
+               return -1;
+
+       /* Interface name lookup */
+       memset(tb, 0, sizeof (tb));
+       parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+       if (tb[IFLA_IFNAME] == NULL)
+               return -1;
+
+       /* ignore loopback device */
+       if (ifi->ifi_type == ARPHRD_LOOPBACK)
+               return 0;
+
+       /* find the interface */
+       ifp = if_get_by_ifindex(ifi->ifi_index);
+       if (!ifp)
+               return -1;
+
+       /* Update flags */
+       ifp->flags = ifi->ifi_flags;
+
+       return 0;
+}
+
+/* Netlink kernel message reflection */
+static int
+netlink_broadcast_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
+{
+       switch (h->nlmsg_type) {
+       case RTM_NEWLINK:
+       case RTM_DELLINK:
+               return netlink_reflect_filter(snl, h);
+               break;
+       case RTM_NEWADDR:
+       case RTM_DELADDR:
+               return netlink_if_address_filter(snl, h);
+               break;
+       default:
+               syslog(LOG_INFO,
+                      "Kernel is reflecting an unknown netlink nlmsg_type: %d",
+                      h->nlmsg_type);
+               break;
+       }
+       return 0;
+}
+
+int
+kernel_netlink(thread * thread)
+{
+       int status = 0;
+
+       if (thread->type != THREAD_READ_TIMEOUT)
+               status =
+                   netlink_parse_info(netlink_broadcast_filter, &nl_kernel);
+       thread_add_read(master, kernel_netlink, NULL, nl_kernel.fd,
+                       NETLINK_TIMER);
+       return 0;
+}
+
+void
+kernel_netlink_init(void)
+{
+       unsigned long groups;
+
+       /* Start with a netlink address lookup */
+       netlink_address_lookup();
+
+       /*
+        * Prepare netlink kernel broadcast channel
+        * subscribtion. We subscribe to LINK and ADDR
+        * netlink broadcast messages.
+        */
+       groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
+       netlink_socket(&nl_kernel, groups);
+
+       if (nl_kernel.fd > 0) {
+               syslog(LOG_INFO, "Registering Kernel netlink reflector");
+               thread_add_read(master, kernel_netlink, NULL, nl_kernel.fd,
+                               NETLINK_TIMER);
+       }
+}
diff --git a/keepalived/vrrp/vrrp_notify.c b/keepalived/vrrp/vrrp_notify.c
new file mode 100644 (file)
index 0000000..e352082
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * 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 state transition notification scripts handling.
+ *
+ * Version:     $Id: vrrp_notify.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+/* system include */
+#include <ctype.h>
+
+/* local include */
+#include "vrrp_notify.h"
+#include "memory.h"
+
+/* Close all FDs >= a specified value */
+void
+closeall(int fd)
+{
+       int fdlimit = sysconf(_SC_OPEN_MAX);
+       while (fd < fdlimit)
+               close(fd++);
+}
+
+static char *
+get_iscript(vrrp_rt * vrrp, int state)
+{
+       if (!vrrp->notify_exec)
+               return NULL;
+       if (state == VRRP_STATE_BACK)
+               return vrrp->script_backup;
+       if (state == VRRP_STATE_MAST)
+               return vrrp->script_master;
+       if (state == VRRP_STATE_FAULT)
+               return vrrp->script_fault;
+       return NULL;
+}
+
+static char *
+get_gscript(vrrp_sgroup * vgroup, int state)
+{
+       if (!vgroup->notify_exec)
+               return NULL;
+       if (state == VRRP_STATE_BACK)
+               return vgroup->script_backup;
+       if (state == VRRP_STATE_MAST)
+               return vgroup->script_master;
+       if (state == VRRP_STATE_FAULT)
+               return vgroup->script_fault;
+       return NULL;
+}
+
+static char *
+notify_script_name(char *cmdline)
+{
+       char *cp = cmdline;
+       char *script;
+       int strlen;
+
+       if (!cmdline)
+               return NULL;
+       while (!isspace((int) *cp) && *cp != '\0')
+               cp++;
+       strlen = cp - cmdline;
+       script = MALLOC(strlen + 1);
+       memcpy(script, cmdline, strlen);
+       *(script + strlen) = '\0';
+
+       return script;
+}
+
+/* Execute extern script/program */
+static int
+notify_exec(const char *cmd)
+{
+       int err;
+       pid_t pid;
+
+       pid = fork();
+
+       /* In case of fork is error. */
+       if (pid < 0) {
+               syslog(LOG_INFO, "Failed fork process");
+               return -1;
+       }
+
+       /* In case of this is parent process. */
+       if (pid)
+               return (0);
+
+       closeall(0);
+
+       open("/dev/null", O_RDWR);
+       dup(0);
+       dup(0);
+
+       err = system(cmd);
+       if (err != 0) {
+               if (err == 127)
+                       syslog(LOG_ALERT, "Failed to exec [%s]", cmd);
+               else
+                       syslog(LOG_ALERT, "Error running [%s], error: %d", cmd,
+                              err);
+       } else
+               syslog(LOG_INFO, "Success executing [%s]", cmd);
+
+       exit(0);
+}
+
+static int
+script_open(char *script)
+{
+       char *script_name = notify_script_name(script);
+       FILE *fOut;
+
+       fOut = fopen(script_name, "r");;
+       if (!fOut) {
+               syslog(LOG_INFO, "Can't open %s (errno %d %s)", script_name,
+                      errno, strerror(errno));
+               return 0;
+       }
+       FREE(script_name);
+       fclose(fOut);
+       return 1;
+}
+
+int
+notify_instance_exec(vrrp_rt * vrrp, int state)
+{
+       char *script = get_iscript(vrrp, state);
+
+       if (!script || !script_open(script))
+               return 0;
+
+       /* Launch the script */
+       notify_exec(script);
+       return 1;
+}
+
+int
+notify_group_exec(vrrp_sgroup * vgroup, int state)
+{
+       char *script = get_gscript(vgroup, state);
+
+       if (!script || !script_open(script))
+               return 0;
+
+       /* Launch the script */
+       notify_exec(script);
+       return 1;
+}
diff --git a/keepalived/vrrp/vrrp_scheduler.c b/keepalived/vrrp/vrrp_scheduler.c
new file mode 100644 (file)
index 0000000..7f62b58
--- /dev/null
@@ -0,0 +1,753 @@
+/*
+ * 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:        Sheduling framework for vrrp code.
+ *
+ * Version:     $Id: vrrp_scheduler.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#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"
+#include "memory.h"
+#include "list.h"
+#include "data.h"
+#include "smtp.h"
+
+extern thread_master *master;
+extern data *conf_data;
+
+/* VRRP FSM definition */
+static void vrrp_backup(vrrp_rt *, char *, int);
+static void vrrp_leave_master(vrrp_rt *, char *, int);
+static void vrrp_leave_fault(vrrp_rt *, char *, int);
+static void vrrp_become_master(vrrp_rt *, char *, int);
+static void vrrp_leave_dummy_master(vrrp_rt *, char *, int);
+
+static void vrrp_goto_master(vrrp_rt *);
+static void vrrp_master(vrrp_rt *);
+static void vrrp_fault(vrrp_rt *);
+static void vrrp_dummy_master(vrrp_rt *);
+
+struct {
+       void (*read) (vrrp_rt *, char *, int);
+       void (*read_to) (vrrp_rt *);
+} VRRP_FSM[VRRP_MAX_FSM_STATE + 1] = {
+/*    Stream Read Handlers      |    Stream Read_to handlers   */
+/*------------------------------+------------------------------*/
+       {NULL,                          NULL},
+       {vrrp_backup,                   vrrp_goto_master},      /*  BACKUP          */
+       {vrrp_leave_master,             vrrp_master},           /*  MASTER          */
+       {vrrp_leave_fault,              vrrp_fault},            /*  FAULT           */
+       {vrrp_become_master,            vrrp_goto_master},      /*  GOTO_MASTER     */
+       {vrrp_leave_dummy_master,       vrrp_dummy_master}      /*  DUMMY_MASTER    */
+};
+
+/* SMTP alert notifier */
+static void
+vrrp_smtp_notifier(vrrp_rt * vrrp)
+{
+       if (vrrp->smtp_alert)
+               smtp_alert(master, NULL, vrrp, "Transition to MASTER state",
+                          "=> VRRP Instance is now owning VRRP VIPs <=\n\n");
+}
+
+/*
+ * Initialize state handling
+ * --rfc2338.6.4.1
+ */
+static void
+vrrp_init_state(list l)
+{
+       vrrp_rt *vrrp;
+       element e;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               vrrp = ELEMENT_DATA(e);
+
+               if (vrrp->priority == VRRP_PRIO_OWNER ||
+                   vrrp->wantstate == VRRP_STATE_MAST) {
+#ifdef _HAVE_IPVS_SYNCD_
+                       /* Check if sync daemon handling is needed */
+                       if (vrrp->lvs_syncd_if)
+                               ipvs_syncd_cmd(IPVS_STARTDAEMON,
+                                              vrrp->lvs_syncd_if, IPVS_MASTER);
+#endif
+                       vrrp->state = VRRP_STATE_GOTO_MASTER;
+               } else {
+                       vrrp->ms_down_timer = 3 * vrrp->adver_int
+                           + VRRP_TIMER_SKEW(vrrp);
+#ifdef _HAVE_IPVS_SYNCD_
+                       /* Check if sync daemon handling is needed */
+                       if (vrrp->lvs_syncd_if)
+                               ipvs_syncd_cmd(IPVS_STARTDAEMON,
+                                              vrrp->lvs_syncd_if, IPVS_BACKUP);
+#endif
+                       vrrp->state = VRRP_STATE_BACK;
+               }
+       }
+}
+
+static 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;
+       }
+       if (vrrp->state == VRRP_STATE_GOTO_MASTER ||
+           vrrp->state == VRRP_STATE_GOTO_DUMMY_MAST ||
+           vrrp->state == VRRP_STATE_MAST ||
+           vrrp->state == VRRP_STATE_DUMMY_MAST ||
+           vrrp->state == VRRP_STATE_GOTO_FAULT) {
+               vrrp->sands.tv_sec = timer.tv_sec + vrrp->adver_int / TIMER_HZ;
+               vrrp->sands.tv_usec = timer.tv_usec;
+       }
+}
+
+static void
+vrrp_init_sands(list l)
+{
+       vrrp_rt *vrrp;
+       element e;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               vrrp = ELEMENT_DATA(e);
+               vrrp_init_instance_sands(vrrp);
+       }
+}
+
+/* Timer functions */
+static TIMEVAL
+vrrp_compute_timer(const int fd)
+{
+       vrrp_rt *vrrp;
+       TIMEVAL timer;
+       element e;
+       list l = conf_data->vrrp;
+
+       /* clean the memory */
+       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);
+               }
+       }
+
+       return timer;
+}
+
+static long
+vrrp_timer_fd(const int fd)
+{
+       TIMEVAL timer, vrrp_timer, now;
+
+       timer = vrrp_compute_timer(fd);
+       now = timer_now();
+       vrrp_timer = timer_sub(timer, now);
+
+       return (vrrp_timer.tv_sec * TIMER_HZ + vrrp_timer.tv_usec);
+}
+
+static int
+vrrp_timer_vrid_timeout(const int fd)
+{
+       vrrp_rt *vrrp;
+       list l = conf_data->vrrp;
+       element e;
+       TIMEVAL vrrp_timer;
+       int vrid = 0;
+
+       /* clean the memory */
+       memset(&vrrp_timer, 0, sizeof (struct timeval));
+       vrrp_timer = vrrp_compute_timer(fd);
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               vrrp = ELEMENT_DATA(e);
+               if (timer_cmp(vrrp->sands, vrrp_timer) == 0)
+                       vrid = vrrp->vrid;
+       }
+       return vrid;
+}
+
+/* Thread functions */
+static void
+vrrp_register_workers(list l)
+{
+       sock *sock;
+       TIMEVAL timer;
+       long vrrp_timer = 0;
+       element e;
+
+       /* Init compute timer */
+       memset(&timer, 0, sizeof (struct timeval));
+
+       /* Init the VRRP instances state */
+       vrrp_init_state(conf_data->vrrp);
+
+       /* Init VRRP instances sands */
+       vrrp_init_sands(conf_data->vrrp);
+
+       /* Register VRRP workers threads */
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               sock = ELEMENT_DATA(e);
+               /* jump to asynchronous handling */
+               vrrp_timer = vrrp_timer_fd(sock->fd);
+
+               /* Register a timer thread if interface is shut */
+               if (sock->fd == -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);
+       }
+}
+
+/* VRRP dispatcher functions */
+static int
+already_exist_sock(list l, int ifindex, int proto)
+{
+       sock *sock;
+       element e;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               sock = ELEMENT_DATA(e);
+               if ((sock->ifindex == ifindex) && (sock->proto == proto))
+                       return 1;
+       }
+       return 0;
+}
+
+/* sockpool list primitives */
+void
+free_sock(void *data)
+{
+       FREE(data);
+}
+
+void
+dump_sock(void *data)
+{
+#ifdef _DEBUG_
+       sock *sock = data;
+       DBG("sockpool -> ifindex(%d), proto(%d), fd(%d)",
+           sock->ifindex, sock->proto, sock->fd);
+#endif
+}
+
+void
+alloc_sock(list l, int ifindex, int proto)
+{
+       sock *new;
+
+       new = (sock *) MALLOC(sizeof (sock));
+       new->ifindex = ifindex;
+       new->proto = proto;
+
+       list_add(l, new);
+}
+
+static void
+vrrp_create_sockpool(list l)
+{
+       vrrp_rt *vrrp;
+       list p = conf_data->vrrp;
+       element e;
+       int ifindex;
+       int proto;
+
+       for (e = LIST_HEAD(p); e; ELEMENT_NEXT(e)) {
+               vrrp = ELEMENT_DATA(e);
+               ifindex = IF_INDEX(vrrp->ifp);
+               if (vrrp->auth_type == VRRP_AUTH_AH)
+                       proto = IPPROTO_IPSEC_AH;
+               else
+                       proto = IPPROTO_VRRP;
+
+               /* add the vrrp element if not exist */
+               if (!already_exist_sock(l, ifindex, proto))
+                       alloc_sock(l, ifindex, proto);
+       }
+}
+
+static void
+vrrp_open_sockpool(list l)
+{
+       sock *sock;
+       element e;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               sock = ELEMENT_DATA(e);
+               sock->fd = open_vrrp_socket(sock->proto, sock->ifindex);
+       }
+}
+
+static void
+vrrp_set_fds(list l)
+{
+       sock *sock;
+       vrrp_rt *vrrp;
+       list p = conf_data->vrrp;
+       element e_sock;
+       element e_vrrp;
+       int proto;
+
+       for (e_sock = LIST_HEAD(l); e_sock; ELEMENT_NEXT(e_sock)) {
+               sock = ELEMENT_DATA(e_sock);
+               for (e_vrrp = LIST_HEAD(p); e_vrrp; ELEMENT_NEXT(e_vrrp)) {
+                       vrrp = ELEMENT_DATA(e_vrrp);
+                       if (vrrp->auth_type == VRRP_AUTH_AH)
+                               proto = IPPROTO_IPSEC_AH;
+                       else
+                               proto = IPPROTO_VRRP;
+
+                       if ((sock->ifindex == IF_INDEX(vrrp->ifp)) &&
+                           (sock->proto == proto))
+                               vrrp->fd = sock->fd;
+               }
+       }
+}
+
+/*
+ * We create & allocate a socket pool here. The soft design
+ * can be sum up by the following sketch :
+ *
+ *    fd1  fd2    fd3  fd4          fdi  fdi+1
+ * -----\__/--------\__/---........---\__/---
+ *    | ETH0 |    | ETH1 |          | ETHn |
+ *    +------+    +------+          +------+
+ *
+ * Here we have n physical NIC. Each NIC own a maximum of 2 fds.
+ * (one for VRRP the other for IPSEC_AH). All our VRRP instances
+ * are multiplexed through this fds. So our design can handle 2*n
+ * multiplexing points.
+ */
+int
+vrrp_dispatcher_init(thread * thread)
+{
+       list pool;
+
+       /* allocate the sockpool */
+       pool = alloc_list(free_sock, dump_sock);
+
+       /* create the VRRP socket pool list */
+       vrrp_create_sockpool(pool);
+
+       /* open the VRRP socket pool */
+       vrrp_open_sockpool(pool);
+
+       /* set VRRP instance fds to sockpool */
+       vrrp_set_fds(pool);
+
+       /* register read dispatcher worker thread */
+       vrrp_register_workers(pool);
+
+       /* cleanup the temp socket pool */
+       dump_list(pool);
+       free_list(pool);
+
+       return 1;
+}
+
+static vrrp_rt *
+vrrp_search_instance(const int vrid)
+{
+       vrrp_rt *vrrp;
+       list l = conf_data->vrrp;
+       element e;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               vrrp = ELEMENT_DATA(e);
+               if (vrrp->vrid == vrid)
+                       return vrrp;
+       }
+       return NULL;
+}
+
+static void
+vrrp_backup(vrrp_rt * vrrp, char *vrrp_buffer, int len)
+{
+       struct iphdr *iph = (struct iphdr *) vrrp_buffer;
+       ipsec_ah *ah;
+
+       if (iph->protocol == IPPROTO_IPSEC_AH) {
+               ah = (ipsec_ah *) (vrrp_buffer + sizeof (struct iphdr));
+               if (ah->seq_number >= vrrp->ipsecah_counter->seq_number) {
+                       vrrp->ipsecah_counter->seq_number = ah->seq_number + 10;
+                       vrrp->ipsecah_counter->cycle = 0;
+               }
+       }
+
+       vrrp_state_backup(vrrp, vrrp_buffer, len);
+}
+
+static void
+vrrp_become_master(vrrp_rt * vrrp, char *vrrp_buffer, int len)
+{
+       struct iphdr *iph = (struct iphdr *) vrrp_buffer;
+       ipsec_ah *ah;
+
+       /*
+        * If we are in IPSEC AH mode, we must be sync
+        * with the remote IPSEC AH VRRP instance counter.
+        */
+       if (iph->protocol == IPPROTO_IPSEC_AH) {
+               syslog(LOG_INFO, "VRRP_Instance(%s) AH seq_num sync",
+                      vrrp->iname);
+               ah = (ipsec_ah *) (vrrp_buffer + sizeof (struct iphdr));
+               vrrp->ipsecah_counter->seq_number = ah->seq_number + 5;
+               vrrp->ipsecah_counter->cycle = 0;
+       }
+
+       /* Then jump to master state */
+       vrrp->wantstate = VRRP_STATE_MAST;
+       vrrp_state_goto_master(vrrp);
+       vrrp_smtp_notifier(vrrp);
+}
+
+static void
+vrrp_leave_master(vrrp_rt * vrrp, char *vrrp_buffer, int len)
+{
+       if (!IF_ISUP(vrrp->ifp)) {
+               syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN",
+                      IF_NAME(vrrp->ifp));
+               vrrp->wantstate = VRRP_STATE_GOTO_FAULT;
+               vrrp_state_leave_master(vrrp);
+       } else if (vrrp_state_master_rx(vrrp, vrrp_buffer, len)) {
+               vrrp->wantstate = VRRP_STATE_BACK;
+               vrrp_state_leave_master(vrrp);
+       }
+}
+
+static void
+vrrp_leave_fault(vrrp_rt * vrrp, char *vrrp_buffer, int len)
+{
+       if (vrrp_state_fault_rx(vrrp, vrrp_buffer, len)) {
+               if (vrrp->sync) {
+                       if (vrrp_sync_leave_fault(vrrp)) {
+                               syslog(LOG_INFO,
+                                      "VRRP_Instance(%s) prio is higher than received advert",
+                                      vrrp->iname);
+                               vrrp_become_master(vrrp, vrrp_buffer, len);
+                       }
+               } else {
+                       syslog(LOG_INFO,
+                              "VRRP_Instance(%s) prio is higher than received advert",
+                              vrrp->iname);
+                       vrrp_become_master(vrrp, vrrp_buffer, len);
+               }
+       } else {
+               vrrp->state = VRRP_STATE_BACK;
+       }
+}
+
+static void
+vrrp_leave_dummy_master(vrrp_rt * vrrp, char *vrrp_buffer, int len)
+{
+/*
+  vrrp_rt *vrrp_isync;
+
+  if (vrrp->isync) {
+    vrrp_isync = vrrp_search_instance_isync(vrrp->isync);
+
+    if (vrrp_isync->state == VRRP_STATE_FAULT &&
+        vrrp->wantstate   == VRRP_STATE_GOTO_DUMMY_MAST) {
+      vrrp->wantstate = VRRP_STATE_DUMMY_MAST;
+      syslog(LOG_INFO, "VRRP_Instance(%s) leaving DUMMY MASTER state"
+                      , vrrp->iname);
+      vrrp_state_leave_master(vrrp);
+    }
+
+    if (vrrp_isync->state != VRRP_STATE_FAULT) {
+      switch (vrrp_isync->state) {
+        case VRRP_STATE_BACK:
+          vrrp->state = VRRP_STATE_BACK;
+          break;
+        case VRRP_STATE_MAST:
+          vrrp_become_master(vrrp, vrrp_buffer, len);
+          break;
+      }
+    }
+  }
+*/
+}
+
+static void
+vrrp_goto_master(vrrp_rt * vrrp)
+{
+       if (!IF_ISUP(vrrp->ifp)) {
+               syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN",
+                      IF_NAME(vrrp->ifp));
+               syslog(LOG_INFO, "VRRP_Instance(%s) Now in FAULT state",
+                      vrrp->iname);
+               vrrp->state = VRRP_STATE_FAULT;
+               vrrp->ms_down_timer =
+                   3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
+       } else {
+               /* If becoming MASTER in IPSEC AH AUTH, we reset the anti-replay */
+               if (vrrp->ipsecah_counter->cycle) {
+                       vrrp->ipsecah_counter->cycle = 0;
+                       vrrp->ipsecah_counter->seq_number = 0;
+               }
+
+               if (vrrp->wantstate != VRRP_STATE_GOTO_DUMMY_MAST)
+                       vrrp->wantstate = VRRP_STATE_MAST;
+
+               /* handle master state transition */
+               vrrp_state_goto_master(vrrp);
+               vrrp_smtp_notifier(vrrp);
+       }
+}
+
+static void
+vrrp_master(vrrp_rt * vrrp)
+{
+       /* Check if interface we are running on is UP */
+       if (vrrp->wantstate != VRRP_STATE_GOTO_FAULT) {
+               if (!IF_ISUP(vrrp->ifp)) {
+                       syslog(LOG_INFO,
+                              "Kernel is reporting: interface %s DOWN",
+                              IF_NAME(vrrp->ifp));
+                       vrrp->wantstate = VRRP_STATE_GOTO_FAULT;
+               }
+       }
+
+       /* Then perform the state transition */
+       if (vrrp->wantstate == VRRP_STATE_GOTO_FAULT ||
+           vrrp->wantstate == VRRP_STATE_BACK ||
+           vrrp->ipsecah_counter->cycle) {
+               vrrp->ms_down_timer =
+                   3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
+
+               /* handle backup state transition */
+               vrrp_state_leave_master(vrrp);
+
+               if (vrrp->state == VRRP_STATE_BACK)
+                       syslog(LOG_INFO,
+                              "VRRP_Instance(%s) Now in BACKUP state",
+                              vrrp->iname);
+               if (vrrp->state == VRRP_STATE_FAULT)
+                       syslog(LOG_INFO, "VRRP_Instance(%s) Now in FAULT state",
+                              vrrp->iname);
+       } else if (vrrp->state == VRRP_STATE_MAST) {
+               /* send the VRRP advert */
+               vrrp_state_master_tx(vrrp, 0);
+       }
+}
+
+static void
+vrrp_fault(vrrp_rt * vrrp)
+{
+       vrrp_sgroup *vgroup = vrrp->sync;
+
+       if (vgroup) {
+               if (vrrp_sync_group_up(vgroup)) {
+                       if (vgroup->state == VRRP_STATE_FAULT) {
+                               syslog(LOG_INFO,
+                                      "VRRP_Group(%s) Leaving FAULT state",
+                                      GROUP_NAME(vgroup));
+                               notify_group_exec(vgroup, vrrp->init_state);
+                               vgroup->state = vrrp->init_state;
+                       }
+               } else
+                       return;
+       } else if (IF_ISUP(vrrp->ifp))
+               syslog(LOG_INFO, "Kernel is reporting: interface %s UP",
+                      IF_NAME(vrrp->ifp));
+       else
+               return;
+
+       /* refresh the multicast fd */
+       new_vrrp_socket(vrrp);
+
+       /*
+        * We force the IPSEC AH seq_number sync
+        * to be done in read advert handler.
+        * So we ignore this timeouted state until remote
+        * VRRP MASTER send its advert for the concerned
+        * instance.
+        */
+       if (vrrp->auth_type == VRRP_AUTH_AH) {
+               /*
+                * Transition to BACKUP state for AH
+                * seq number synchronization.
+                */
+               syslog(LOG_INFO,
+                      "VRRP_Instance(%s) in FAULT state jump to AH sync",
+                      vrrp->iname);
+               vrrp->wantstate = VRRP_STATE_BACK;
+               vrrp_state_leave_master(vrrp);
+       } else {
+               /* Otherwise, we transit to init state */
+               if (vrrp->init_state == VRRP_STATE_BACK)
+                       vrrp->state = VRRP_STATE_BACK;
+               else {
+                       vrrp_goto_master(vrrp);
+                       vrrp_smtp_notifier(vrrp);
+               }
+       }
+}
+
+static void
+vrrp_dummy_master(vrrp_rt * vrrp)
+{
+       /* Check if interface we are running on is UP */
+       if (!IF_ISUP(vrrp->ifp))
+               vrrp->wantstate = VRRP_STATE_GOTO_FAULT;
+
+       if (vrrp->wantstate == VRRP_STATE_GOTO_FAULT) {
+               vrrp->ms_down_timer =
+                   3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
+
+               /* handle backup state transition */
+               vrrp_state_leave_master(vrrp);
+       } else {
+               /* send the VRRP advert */
+               vrrp_state_master_tx(vrrp, 0);
+       }
+}
+
+/* Handle dispatcher read timeout */
+static int
+vrrp_dispatcher_read_to(int fd)
+{
+       vrrp_rt *vrrp;
+       int vrid = 0;
+       int prev_state = 0;
+
+       /* Searching for matching instance */
+       vrid = vrrp_timer_vrid_timeout(fd);
+       vrrp = vrrp_search_instance(vrid);
+
+       /* Run the FSM handler */
+       prev_state = vrrp->state;
+       VRRP_FSM_READ_TO(vrrp);
+
+       /* handle instance synchronization */
+       vrrp_sync_read_to(vrrp, prev_state);
+
+       /*
+        * We are sure the instance exist. So we can
+        * compute new sands timer safely.
+        */
+       vrrp_init_instance_sands(vrrp);
+       return vrrp->fd;
+}
+
+/* Handle dispatcher read packet */
+static int
+vrrp_dispatcher_read(int fd)
+{
+       vrrp_rt *vrrp;
+       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);
+
+       /* read & affect received buffer */
+       len = read(fd, vrrp_buffer, VRRP_PACKET_TEMP_LEN);
+       iph = (struct iphdr *) vrrp_buffer;
+
+       /* GCC bug : Workaround */
+       hd = (vrrp_pkt *) ((char *) iph + (iph->ihl << 2));
+       if (iph->protocol == IPPROTO_IPSEC_AH)
+               hd = (vrrp_pkt *) ((char *) hd + vrrp_ipsecah_len());
+       /* GCC bug : end */
+
+       /* Searching for matching instance */
+       vrrp = vrrp_search_instance(hd->vrid);
+
+       /* If no instance found => ignore the advert */
+       if (!vrrp) {
+               FREE(vrrp_buffer);
+               return fd;
+       }
+
+       /* Run the FSM handler */
+       prev_state = vrrp->state;
+       VRRP_FSM_READ(vrrp, vrrp_buffer, len);
+
+       /* handle instance synchronization */
+       vrrp_sync_read(vrrp, prev_state);
+
+       /*
+        * Refresh sands only if found matching instance.
+        * Otherwize the packet is simply ignored...
+        */
+       vrrp_init_instance_sands(vrrp);
+
+       /* cleanup the room */
+       FREE(vrrp_buffer);
+       return fd;
+}
+
+/* Our read packet dispatcher */
+int
+vrrp_read_dispatcher_thread(thread * thread)
+{
+       long vrrp_timer = 0;
+       int fd;
+
+       /* Dispatcher state handler */
+       if (thread->type == THREAD_READ_TIMEOUT)
+               fd = vrrp_dispatcher_read_to(thread->u.fd);
+       else if (thread->arg)
+               fd = vrrp_dispatcher_read_to(-1);
+       else
+               fd = vrrp_dispatcher_read(thread->u.fd);
+
+       /* register next dispatcher thread */
+       vrrp_timer = vrrp_timer_fd(fd);
+       TIMER_MICRO_ADJUST(vrrp_timer);
+       if (fd == -1)
+               thread_add_timer(thread->master, vrrp_read_dispatcher_thread,
+                                (int *)THREAD_TIMER, vrrp_timer);
+       else
+               thread_add_read(thread->master, vrrp_read_dispatcher_thread,
+                               NULL, fd, vrrp_timer);
+
+       return 0;
+}
+
+/* Register VRRP thread */
+void
+register_vrrp_thread(void)
+{
+       /* Init the packet dispatcher */
+       if (!LIST_ISEMPTY(conf_data->vrrp))
+               thread_add_event(master, vrrp_dispatcher_init, NULL,
+                                VRRP_DISPATCHER);
+}
diff --git a/keepalived/vrrp/vrrp_sync.c b/keepalived/vrrp/vrrp_sync.c
new file mode 100644 (file)
index 0000000..e0fd743
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * 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 synchronization framework.
+ *
+ * Version:     $Id: vrrp_sync.c,v 0.6.5 2002/07/01 23:41:28 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.
+ */
+
+#include "vrrp_sync.h"
+#include "vrrp_if.h"
+#include "vrrp_notify.h"
+#include "data.h"
+
+/* extern global vars */
+extern data *conf_data;
+
+/* 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 = conf_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;
+                       }
+       }
+       return NULL;
+}
+
+/* jointure between instance and group => iname */
+vrrp_rt *
+vrrp_get_instance(char *iname)
+{
+       vrrp_rt *vrrp;
+       list l = conf_data->vrrp;
+       element e;
+
+       for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+               vrrp = ELEMENT_DATA(e);
+               if (strcmp(vrrp->iname, iname) == 0)
+                       return vrrp;
+       }
+       return NULL;
+}
+
+/* All interface are UP in the same group */
+int
+vrrp_sync_group_up(vrrp_sgroup * vgroup)
+{
+       vrrp_rt *isync;
+       char *str;
+       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 (IF_ISUP(isync->ifp))
+                       is_up++;
+       }
+       return (is_up == VECTOR_SIZE(vgroup->iname)) ? 1 : 0;
+}
+
+/* Leaving fault state */
+int
+vrrp_sync_leave_fault(vrrp_rt * vrrp)
+{
+       vrrp_sgroup *vgroup = vrrp->sync;
+
+       if (vrrp_sync_group_up(vgroup)) {
+               syslog(LOG_INFO, "VRRP_Group(%s) Leaving FAULT state",
+                      GROUP_NAME(vgroup));
+               vgroup->state = VRRP_STATE_MAST;
+               notify_group_exec(vgroup, VRRP_STATE_MAST);
+               return 1;
+       }
+       return 0;
+}
+
+static void
+vrrp_sync_backup(vrrp_rt * vrrp)
+{
+       int i;
+       char *str;
+       vrrp_rt *isync;
+       vrrp_sgroup *vgroup = vrrp->sync;
+
+       syslog(LOG_INFO, "VRRP_Group(%s) Syncing instances to BACKUP 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 != vrrp)
+                       isync->wantstate = VRRP_STATE_BACK;
+       }
+       vgroup->state = VRRP_STATE_BACK;
+       notify_group_exec(vgroup, VRRP_STATE_BACK);
+}
+
+static void
+vrrp_sync_master_to(vrrp_rt * vrrp)
+{
+       int i;
+       char *str;
+       vrrp_rt *isync;
+       vrrp_sgroup *vgroup = vrrp->sync;
+
+       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);
+
+               /* Send the higher priority advert on all synced instances */
+               if (isync != vrrp) {
+                       syslog(LOG_INFO,
+                              "VRRP_Instance(%s) sending OWNER advert",
+                              isync->iname);
+                       vrrp_state_master_tx(isync, VRRP_PRIO_OWNER);
+                       isync->state = VRRP_STATE_MAST;
+               }
+       }
+       vgroup->state = VRRP_STATE_MAST;
+       notify_group_exec(vgroup, VRRP_STATE_MAST);
+}
+
+static void
+vrrp_sync_fault_to(vrrp_rt * vrrp)
+{
+       int i;
+       char *str;
+       vrrp_rt *isync;
+       vrrp_sgroup *vgroup = vrrp->sync;
+
+       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);
+
+               /*
+                * We force sync instance to backup mode.
+                * This reduce instance takeover to less than ms_down_timer.
+                * => by default ms_down_timer is set to 3secs.
+                * => Takeover will be less than 3secs !
+                */
+               if (isync != vrrp)
+                       if (isync->state == VRRP_STATE_MAST)
+                               isync->wantstate = VRRP_STATE_GOTO_FAULT;
+       }
+       vgroup->state = VRRP_STATE_FAULT;
+       notify_group_exec(vgroup, VRRP_STATE_FAULT);
+}
+
+static void
+vrrp_sync_dmaster_to(vrrp_rt * vrrp)
+{
+       int i;
+       char *str;
+       vrrp_rt *isync;
+       vrrp_sgroup *vgroup = vrrp->sync;
+
+       for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
+               str = VECTOR_SLOT(vgroup->iname, i);
+               isync = vrrp_get_instance(str);
+               if (isync != vrrp) {
+                       if (isync->state == VRRP_STATE_FAULT) {
+                               syslog(LOG_INFO,
+                                      "VRRP_Instance(%s) Transition to DUMMY MASTER",
+                                      isync->iname);
+                               isync->wantstate = VRRP_STATE_GOTO_DUMMY_MAST;
+                       }
+               }
+       }
+       vgroup->state = VRRP_STATE_DUMMY_MAST;
+}
+
+/* Read TimeOut synchronization handler */
+void
+vrrp_sync_read_to(vrrp_rt * vrrp, int prev_state)
+{
+       /* Nothing to sync */
+       if (!vrrp->sync)
+               return;
+
+       /* Sync the group instance to MASTER state */
+       if (prev_state == VRRP_STATE_BACK && vrrp->state == VRRP_STATE_MAST)
+               if (GROUP_STATE(vrrp->sync) == VRRP_STATE_BACK)
+                       vrrp_sync_master_to(vrrp);
+
+       /* sync the group instance to FAULT state */
+       if (prev_state == VRRP_STATE_MAST && vrrp->state == VRRP_STATE_FAULT)
+               if (GROUP_STATE(vrrp->sync) == VRRP_STATE_MAST)
+                       vrrp_sync_fault_to(vrrp);
+
+       /*
+        * Break a MASTER/BACKUP state loop after sync instance
+        * FAULT state transition.
+        * => We doesn't receive remote MASTER adverts.
+        * => Emulate a DUMMY master to break the loop.
+        */
+       if (prev_state == VRRP_STATE_MAST && vrrp->state == VRRP_STATE_BACK)
+               if (GROUP_STATE(vrrp->sync) == VRRP_STATE_FAULT)
+                       vrrp_sync_dmaster_to(vrrp);
+
+       /* previous state symetry */
+       if (vrrp->state == VRRP_STATE_DUMMY_MAST)
+               if (GROUP_STATE(vrrp->sync) == VRRP_STATE_MAST)
+                       vrrp->state = VRRP_STATE_MAST;
+}
+
+/* Read TimeOut synchronization handler */
+void
+vrrp_sync_read(vrrp_rt * vrrp, int prev_state)
+{
+       /* Nothing to sync */
+       if (!vrrp->sync)
+               return;
+
+       /* sync the group instance to BACKUP state */
+       if (prev_state == VRRP_STATE_MAST && vrrp->state == VRRP_STATE_BACK)
+               if (GROUP_STATE(vrrp->sync) == VRRP_STATE_MAST)
+                       vrrp_sync_backup(vrrp);
+
+       /* 
+        * Handle wanted transition to MASTER state.
+        * When Instance not in FAULT state, we received a remote
+        * lower priotity advert => Force a new VRRP election.
+        */
+       if (vrrp->state == VRRP_STATE_BACK &&
+           vrrp->wantstate == VRRP_STATE_GOTO_MASTER) {
+               if (GROUP_STATE(vrrp->sync) != VRRP_STATE_FAULT) {
+                       /* Force a new protocol master election */
+                       syslog(LOG_INFO,
+                              "VRRP_Instance(%s) forcing a new MASTER election",
+                              vrrp->iname);
+                       vrrp_send_adv(vrrp, vrrp->priority);
+               }
+       }
+}
diff --git a/layer4.c b/layer4.c
deleted file mode 100644 (file)
index f06e715..0000000
--- a/layer4.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * 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:        Layer4 checkers handling. Register worker threads &
- *              upper layer checkers.
- *
- * Version:     $Id: layer4.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "layer4.h"
-#include "check_api.h"
-#include "utils.h"
-
-enum connect_result
-tcp_connect (int fd, uint32_t addr_ip, uint16_t addr_port)
-{
-  struct linger li = { 0 };
-  int long_inet;
-  struct sockaddr_in adr_serv;
-  int ret;
-  int val;
-
-  /* free the tcp port after closing the socket descriptor */
-  li.l_onoff=1;
-  li.l_linger=0;
-  setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *)&li, sizeof(struct linger));
-
-  long_inet = sizeof(struct sockaddr_in);
-  memset(&adr_serv,0,long_inet);
-  adr_serv.sin_family      = AF_INET;
-  adr_serv.sin_port        = addr_port;
-  adr_serv.sin_addr.s_addr = addr_ip;
-
-  /* Make socket non-block. */
-  val = fcntl (fd, F_GETFL, 0);
-  fcntl (fd, F_SETFL, val|O_NONBLOCK);
-
-  /* Call connect function. */
-  ret = connect (fd, (struct sockaddr *)&adr_serv, long_inet);
-
-  /* Immediate success */
-  if (ret == 0) {
-    fcntl (fd, F_SETFL, val);
-    return connect_success;
-  }
-
-  /* If connect is in progress then return 1 else it's real error. */
-  if (ret < 0) {
-    if (errno != EINPROGRESS)
-      return connect_error;
-  }
-
-  /* restore previous fd args */
-  fcntl (fd, F_SETFL, val);
-  return connect_in_progress;
-}
-
-enum connect_result tcp_socket_state(int fd, thread *thread
-                                           , uint32_t addr_ip
-                                           , uint16_t addr_port
-                                           , int (*func) (struct _thread *))
-{
-  int status;
-  int slen;
-  int ret = 0;
-  TIMEVAL timer_min;
-
-  /* Handle connection timeout */
-  if(thread->type == THREAD_WRITE_TIMEOUT) {
-#ifdef _DEBUG_
-    syslog(LOG_DEBUG, "TCP connection timeout to [%s:%d]."
-                    , inet_ntop2(addr_ip)
-                    , ntohs(addr_port));
-#endif
-    close(thread->u.fd);
-    return connect_timeout;
-  }
-
-  /* Check file descriptor */
-  slen = sizeof(status);
-  if (getsockopt(thread->u.fd, SOL_SOCKET, SO_ERROR, (void *)&status, &slen) < 0)
-    ret = errno;
-
-  /* Connection failed !!! */
-  if (ret) {
-#ifdef _DEBUG_
-    syslog(LOG_DEBUG, "TCP connection failed to [%s:%d]."
-                    , inet_ntop2(addr_ip)
-                    , ntohs(addr_port));
-#endif
-    close(thread->u.fd);
-    return connect_error;
-  }
-
-  /* If status = 0, TCP connection to remote host is established.
-   * Otherwise register checker thread to handle connection in progress,
-   * and other error code until connection is established.
-   * Recompute the write timeout (or pending connection).
-   */
-  if (status != 0) {
-#ifdef _DEBUG_
-    syslog(LOG_DEBUG, "TCP connection to [%s:%d] still IN_PROGRESS."
-                    , inet_ntop2(addr_ip)
-                    , ntohs(addr_port));
-#endif
-
-    timer_min = timer_sub_now(thread->sands);
-
-    if (TIMER_SEC(timer_min) <= 0)
-      thread_add_write(thread->master, func
-                                     , THREAD_ARG(thread)
-                                     , thread->u.fd
-                                     , 0);
-    else
-      thread_add_write(thread->master, func
-                                     , THREAD_ARG(thread)
-                                     , thread->u.fd
-                                     , TIMER_SEC(timer_min));
-    return connect_in_progress;
-  }
-
-  return connect_success;
-}
-
-void tcp_connection_state(int fd, enum connect_result status
-                         , thread *thread
-                         , int (*func) (struct _thread *)
-                          , int timeout)
-{
-  checker *checker;
-
-  checker = THREAD_ARG(thread);
-
-  switch (status) {
-    case connect_error:
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "TCP connection ERROR to [%s:%d]."
-                      , inet_ntop2(SVR_IP(checker->rs))
-                      , ntohs(SVR_PORT(checker->rs)));
-#endif
-      close(fd);
-      break;
-
-    case connect_success:
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "TCP connection SUCCESS to [%s:%d]."
-                      , inet_ntop2(SVR_IP(checker->rs))
-                      , ntohs(SVR_PORT(checker->rs)));
-#endif
-      thread_add_write(thread->master, func, checker, fd, timeout);
-      break;
-
-    /* Checking non-blocking connect, we wait until socket is writable */
-    case connect_in_progress:
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "TCP connection to [%s:%d] now IN_PROGRESS."
-                      , inet_ntop2(SVR_IP(checker->rs))
-                      , ntohs(SVR_PORT(checker->rs)));
-#endif
-      thread_add_write(thread->master, func, checker, fd, timeout);
-      break;
-
-    default:
-      break;
-  }
-}
diff --git a/libipfwc/ipfwc_kernel_headers.h b/libipfwc/ipfwc_kernel_headers.h
deleted file mode 100644 (file)
index 9a64af7..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/* This is the userspace/kernel interface for Generic IP Chains,
-   required for libc6. */
-#ifndef _FWCHAINS_KERNEL_HEADERS_H
-#define _FWCHAINS_KERNEL_HEADERS_H
-
-#if defined(__GLIBC__) && __GLIBC__ == 2
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netinet/tcp.h>
-#include <netinet/udp.h>
-#include <net/if.h>
-#include <sys/types.h>
-
-typedef u_int64_t __u64;
-typedef u_int32_t __u32;
-typedef int32_t __s32;
-typedef u_int16_t __u16;
-typedef u_int8_t __u8;
-
-#else /* libc5 */
-#include <sys/socket.h>
-#include <linux/ip.h>
-#include <linux/in.h>
-#include <linux/if.h>
-#include <linux/icmp.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#endif
-
-#define IP_FW_MAX_LABEL_LENGTH 8
-typedef char ip_chainlabel[IP_FW_MAX_LABEL_LENGTH+1];
-
-struct ip_fw 
-{
-       struct in_addr fw_src, fw_dst;          /* Source and destination IP addr */
-       struct in_addr fw_smsk, fw_dmsk;        /* Mask for src and dest IP addr */
-       __u32 fw_mark;                          /* ID to stamp on packet */
-       __u16 fw_proto;                         /* Protocol, 0 = ANY */
-       __u16 fw_flg;                           /* Flags word */
-        __u16 fw_invflg;                        /* Inverse flags */
-       __u16 fw_spts[2];                       /* Source port range. */
-        __u16 fw_dpts[2];                       /* Destination port range. */
-       __u16 fw_redirpt;                       /* Port to redirect to. */ 
-       __u16 fw_outputsize;                    /* Max amount to output to
-                                                  NETLINK */
-       char           fw_vianame[IFNAMSIZ];    /* name of interface "via" */
-       __u8           fw_tosand, fw_tosxor;    /* Revised packet priority */
-};
-
-struct ip_fwuser
-{
-       struct ip_fw ipfw;
-       ip_chainlabel label;
-};
-
-/* Values for "fw_flg" field .  */
-#define IP_FW_F_PRN    0x0001  /* Print packet if it matches */
-#define IP_FW_F_TCPSYN 0x0002  /* For tcp packets-check SYN only */
-#define IP_FW_F_FRAG   0x0004  /* Set if rule is a fragment rule */
-#define IP_FW_F_MARKABS        0x0008  /* Set the mark to fw_mark, not add. */
-#define IP_FW_F_WILDIF 0x0010  /* Need only match start of interface name. */
-#define IP_FW_F_NETLINK 0x0020  /* Redirect to netlink: 2.1.x only */
-#define IP_FW_F_MASK   0x003F  /* All possible flag bits mask   */
-
-/* Values for "fw_invflg" field. */
-#define IP_FW_INV_SRCIP 0x0001  /* Invert the sense of fw_src. */
-#define IP_FW_INV_DSTIP 0x0002  /* Invert the sense of fw_dst. */
-#define IP_FW_INV_PROTO 0x0004  /* Invert the sense of fw_proto. */
-#define IP_FW_INV_SRCPT 0x0008  /* Invert the sense of source ports. */
-#define IP_FW_INV_DSTPT 0x0010  /* Invert the sense of destination ports. */
-#define IP_FW_INV_VIA   0x0020  /* Invert the sense of fw_vianame. */
-#define IP_FW_INV_SYN   0x0040  /* Invert the sense of IP_FW_F_TCPSYN. */
-#define IP_FW_INV_FRAG  0x0080  /* Invert the sense of IP_FW_F_FRAG. */
-
-/*    
- *     New IP firewall options for [gs]etsockopt at the RAW IP level.
- *     Unlike BSD Linux inherits IP options so you don't have to use
- * a raw socket for this. Instead we check rights in the calls.  */
-
-#define IP_FW_BASE_CTL         64      /* base for firewall socket options */
-
-#define IP_FW_APPEND           (IP_FW_BASE_CTL)    /* Takes ip_fwchange */
-#define IP_FW_REPLACE          (IP_FW_BASE_CTL+1)  /* Takes ip_fwnew */
-#define IP_FW_DELETE_NUM       (IP_FW_BASE_CTL+2)  /* Takes ip_fwdelnum */
-#define IP_FW_DELETE           (IP_FW_BASE_CTL+3)  /* Takes ip_fwchange */
-#define IP_FW_INSERT           (IP_FW_BASE_CTL+4)  /* Takes ip_fwnew */
-#define IP_FW_FLUSH            (IP_FW_BASE_CTL+5)  /* Takes ip_chainlabel */
-#define IP_FW_ZERO             (IP_FW_BASE_CTL+6)  /* Takes ip_chainlabel */
-#define IP_FW_CHECK            (IP_FW_BASE_CTL+7)  /* Takes ip_fwtest */
-#define IP_FW_MASQ_TIMEOUTS    (IP_FW_BASE_CTL+8)  /* Takes 3 ints */
-#define IP_FW_CREATECHAIN      (IP_FW_BASE_CTL+9)  /* Takes ip_chainlabel */
-#define IP_FW_DELETECHAIN      (IP_FW_BASE_CTL+10) /* Takes ip_chainlabel */
-#define IP_FW_POLICY           (IP_FW_BASE_CTL+11) /* Takes ip_fwpolicy */
-/* Masquerade controls */
-#define IP_FW_MASQ_INSERT      (IP_FW_BASE_CTL+12)
-#define IP_FW_MASQ_ADD         (IP_FW_BASE_CTL+13)
-#define IP_FW_MASQ_DEL         (IP_FW_BASE_CTL+14)
-#define IP_FW_MASQ_FLUSH       (IP_FW_BASE_CTL+15)
-
-/* Builtin chain labels */
-#define IP_FW_LABEL_FORWARD    "forward"
-#define IP_FW_LABEL_INPUT      "input"
-#define IP_FW_LABEL_OUTPUT     "output"
-
-/* Special targets */
-#define IP_FW_LABEL_MASQUERADE  "MASQ"
-#define IP_FW_LABEL_REDIRECT    "REDIRECT"
-#define IP_FW_LABEL_ACCEPT     "ACCEPT"
-#define IP_FW_LABEL_BLOCK      "DENY"
-#define IP_FW_LABEL_REJECT     "REJECT"
-#define IP_FW_LABEL_RETURN     "RETURN"
-
-/* Files in /proc/net */
-#define IP_FW_PROC_CHAINS      "ip_fwchains"
-#define IP_FW_PROC_CHAIN_NAMES "ip_fwnames"
-
-struct ip_fwpkt
-{
-       struct iphdr fwp_iph;                   /* IP header */
-       union {
-               struct tcphdr fwp_tcph;         /* TCP header or */
-               struct udphdr fwp_udph;         /* UDP header */
-               struct icmphdr fwp_icmph;       /* ICMP header */
-       } fwp_protoh;
-       struct in_addr fwp_via;                 /* interface address */
-       char           fwp_vianame[IFNAMSIZ];   /* interface name */
-};
-
-/* The argument to IP_FW_DELETE and IP_FW_APPEND */
-struct ip_fwchange
-{
-       struct ip_fwuser fwc_rule;
-       ip_chainlabel fwc_label;
-};     
-
-/* The argument to IP_FW_CHECK. */
-struct ip_fwtest
-{
-       struct ip_fwpkt fwt_packet; /* Packet to be tested */
-       ip_chainlabel fwt_label;   /* Block to start test in */
-};
-                                               
-/* The argument to IP_FW_DELETE_NUM */
-struct ip_fwdelnum
-{
-       __u32 fwd_rulenum;
-       ip_chainlabel fwd_label;
-};
-
-/* The argument to IP_FW_REPLACE and IP_FW_INSERT */
-struct ip_fwnew
-{
-       __u32 fwn_rulenum;
-       struct ip_fwuser fwn_rule;
-       ip_chainlabel fwn_label;
-};
-/* The argument to IP_FW_POLICY */
-struct ip_fwpolicy
-{
-       ip_chainlabel fwp_policy;
-       ip_chainlabel fwp_label;
-};
-/*      
- * timeouts for ip masquerading
- */
-
-struct ip_fw_masq;
-
-/* Masquerading stuff */
-#define IP_FW_MASQCTL_MAX 256
-#define IP_MASQ_MOD_NMAX  32
-
-struct ip_fw_masqctl
-{
-       int mctl_action;
-       union {
-               struct {
-                       char name[IP_MASQ_MOD_NMAX];
-                       char data[1];
-               } mod;
-       } u;
-};
-#endif
diff --git a/libipvs/Makefile b/libipvs/Makefile
deleted file mode 100644 (file)
index 8ae8576..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# Makefile to make libipvsc.
-
-CC     = gcc
-COPTS   = -g -O
-CFLAGS = -Wall -Wunused $(COPTS) -I/usr/src/linux/include
-
-libipvs.a: libipvs.a(libipvs.o)
-
-libipvsc.o: libipvs.h
-
-clean:
-       rm -f *.a *.o *~
diff --git a/list.c b/list.c
deleted file mode 100644 (file)
index 3a31b39..0000000
--- a/list.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* 
- * 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:        List structure manipulation.
- *  
- * Version:     $Id: list.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "list.h"
-#include "memory.h"
-
-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;
-}
-
-static element alloc_element(void)
-{
-  element new = (element)MALLOC(sizeof(struct _element));
-  return new;
-}
-
-void list_add(list l, void *data)
-{
-  element e = alloc_element();
-
-  e->prev = l->tail;
-  e->data = data;
-
-  if (l->head == NULL)
-    l->head = e;
-  else
-    l->tail->next = e;
-  l->tail = e;
-  l->count++;
-}
-
-void *list_element(list l, int num)
-{
-  element e;
-  int i = 0;
-
-  e = LIST_HEAD(l);
-
-  /* fetch element number num */
-  for (i = 0; i < num; i++)
-    if (e)
-      e = ELEMENT_NEXT(e);
-
-  if (e)
-    return ELEMENT_DATA(e);
-  return NULL;
-}
-
-void dump_list(list l)
-{
-  element e;
-
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e))
-    if (l->dump)
-      (*l->dump) (e->data);
-}
-
-void free_list(list l)
-{
-  element e;
-  element next;
-
-  for (e = LIST_HEAD(l); e; e = next) {
-    next = e->next;
-    if (l->free)
-      (*l->free) (e->data);
-    FREE(e);
-  }
-  FREE(l);
-}
diff --git a/main.c b/main.c
deleted file mode 100644 (file)
index 0d14ccb..0000000
--- a/main.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * 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:        Main program structure.
- *
- * Version:     $Id: main.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "main.h"
-
-/* SIGHUP handler */
-void sighup(int sig)
-{
-  syslog(LOG_INFO, "Terminating on signal");
-
-  /* register the terminate thread */
-  thread_add_terminate_event(master);
-}
-
-/* SIGCHLD handler */
-void sigchld(int sig)
-{
-  int child;
-  wait(&child);
-}
-
-/* Signal wrapper */
-void *signal_set(int signo, void (*func)(int))
-{
-  int ret;
-  struct sigaction sig;
-  struct sigaction osig;
-
-  sig.sa_handler = func;
-  sigemptyset (&sig.sa_mask);
-  sig.sa_flags = 0;
-#ifdef SA_RESTART
-  sig.sa_flags |= SA_RESTART;
-#endif /* SA_RESTART */
-
-  ret = sigaction (signo, &sig, &osig);
-
-  if (ret < 0)
-    return (SIG_ERR);
-  else
-    return (osig.sa_handler);
-}
-
-/* Initialize signal handler */
-void signal_init(void)
-{
-  signal_set(SIGHUP,  sighup);
-  signal_set(SIGINT,  sighup);
-  signal_set(SIGTERM, sighup);
-  signal_set(SIGKILL, sighup);
-  signal_set(SIGCHLD, sigchld);
-}
-
-/* Usage function */
-static void usage(const char *prog)
-{
-  fprintf(stderr, VERSION_STRING);
-  fprintf(stderr,
-    "\nUsage:\n"
-    "  %s\n"
-    "  %s -n\n"
-    "  %s -f keepalived.conf\n"
-    "  %s -d\n"
-    "  %s -h\n"
-    "  %s -v\n\n",
-    prog, prog, prog, prog, prog, prog);
-  fprintf(stderr,
-    "Commands:\n"
-    "Either long or short options are allowed.\n"
-    "  %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 --dump-conf       -d       Dump the configuration data.\n"
-    "  %s --log-console     -l       Log message to local console.\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);
-}
-
-/* Command line parser */
-static char *parse_cmdline(int argc, char **argv)
-{
-  poptContext context;
-  char *optarg = NULL;
-  char *conf_file = NULL;
-  int c;
-
-  struct poptOption options_table[] = {
-    {"version", 'v', POPT_ARG_NONE, NULL, 'v'},
-    {"help", 'h', POPT_ARG_NONE, NULL, 'h'},
-    {"log-console", 'l', POPT_ARG_NONE, NULL, 'l'},
-    {"dont-fork", 'n', POPT_ARG_NONE, NULL, 'n'},
-    {"dump-conf", 'd', POPT_ARG_NONE, NULL, 'd'},
-    {"use-file", 'f', POPT_ARG_STRING, &optarg, 'f'},
-    {NULL, 0, 0, NULL, 0}
-  };
-
-  context = poptGetContext(PROG, argc, (const char **)argv
-                                     , options_table, 0);
-  if ((c = poptGetNextOpt(context)) < 0) {
-    return NULL;
-  }
-
-  /* The first option car */
-  switch (c) {
-    case 'v':
-      fprintf(stderr, VERSION_STRING);
-      exit(0);
-      break;
-    case 'h':
-      usage(argv[0]);
-      exit(0);
-      break;
-    case 'l':
-      debug |= 1;
-      break;
-    case 'n':
-      debug |= 2;
-      break;
-    case 'd':
-      debug |= 4;
-      break;
-    case 'f':
-      conf_file = optarg;
-      break;
-  }
-
-  /* the others */
-  while ((c = poptGetNextOpt(context)) >= 0) {
-    switch (c) {
-      case 'l':
-        debug |= 1;
-        break;
-      case 'n':
-        debug |= 2;
-        break;
-      case 'd':
-        debug |= 4;
-        break;
-      case 'f':
-        conf_file = optarg;
-        break;
-    }
-  }
-
-  /* check unexpected arguments */
-  if ((optarg = (char *)poptGetArg(context))) {
-    fprintf(stderr, "unexpected argument %s\n", optarg);
-    return NULL;
-  }
-
-  /* free the allocated context */
-  poptFreeContext(context);
-
-  return((conf_file)?conf_file:NULL);
-}
-
-/* Entry point */
-int main(int argc, char **argv)
-{
-  char *conf_file = NULL;
-  thread thread;
-
-  /* Init debugging level */
-  debug = 0;
-
-  /*
-   * Parse command line and set debug level.
-   * bits 0..7 reserved by main.c
-   */
-  conf_file = parse_cmdline(argc, argv);
-
-  openlog(PROG, LOG_PID | (debug & 1)?LOG_CONS:0
-              , LOG_DAEMON);
-  syslog(LOG_INFO, "Starting "VERSION_STRING);
-
-  /* Check if keepalived is already running */
-  if (keepalived_running()) {
-    syslog(LOG_INFO, "Stopping "VERSION_STRING);
-    closelog();
-    exit(0);
-  }
-
-  /* daemonize process */
-  if (!(debug & 2))
-    xdaemon(0, 0, 0);
-
-  /* write the pidfile */
-  if (!pidfile_write(getpid())) {
-    syslog(LOG_INFO, "Stopping "VERSION_STRING);
-    closelog();
-    exit(0);
-  }
-
-  /* Signal handling initialization  */
-  signal_init();
-
-  /* Init interface queue */
-  init_interface_queue();
-
-  /* Parse the configuration file */
-#ifdef _WITH_LVS_
-  init_checkers_queue();
-#endif
-  init_data(conf_file);
-  if (!conf_data) {
-    syslog(LOG_INFO, "Stopping "VERSION_STRING);
-    closelog();
-#ifdef _DEBUG_
-    keepalived_free_final();
-#endif
-    exit(0);
-  }
-
-  /* SSL load static data & initialize common ctx context */
-#ifdef _WITH_LVS_
-  if (!init_ssl_ctx()) {
-    closelog();
-#ifdef _DEBUG_
-    keepalived_free_final();
-#endif
-    exit(0);
-  }
-#endif
-
-#ifdef _WITH_LVS_
-  if (!init_services()) {
-    syslog(LOG_INFO, "Stopping "VERSION_STRING);
-    closelog();
-    free_data();
-    exit(0);
-  }
-#endif
-
-  /* Create the master thread */
-  master = thread_make_master();
-
-  /* register workers threads */
-  kernel_netlink_init();
-  if_mii_poller_init();
-#ifdef _WITH_LVS_
-  register_checkers_thread();
-#endif
-  if (!vrrp_complete_init())
-    goto end;
-  register_vrrp_thread();
-
-  /* Dump the configuration */
-  if (debug & 4) 
-    dump_data();
-
-  /* processing the master thread queues, return and execute one ready thread */
-  while (thread_fetch(master, &thread)) {
-
-    /* Run until error, used for debuging only */
-#ifdef _DEBUG_
-    if ((debug & 520) == 520) {
-      debug &= ~520;
-      thread_add_terminate_event(master);
-    }
-#endif
-    thread_call(&thread);
-  }
-
-end:
-  /* Reached when terminate signal catched */
-  syslog(LOG_INFO, "Stopping "VERSION_STRING);
-
-  /* Just cleanup memory & exit */
-  thread_destroy_master(master);
-#ifdef _WITH_LVS_
-  free_checkers_queue();
-  clear_services();
-#endif
-  shutdown_vrrp_instances();
-  free_interface_queue();
-  free_data();
-
-  pidfile_rm();
-
-#ifdef _DEBUG_
-  keepalived_free_final();
-#endif
-
-  closelog();
-  /* finally return from system */
-  exit(0);
-}
diff --git a/memory.c b/memory.c
deleted file mode 100644 (file)
index 3325063..0000000
--- a/memory.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * 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:        Memory management framework. This framework is used to
- *              find any memory leak.
- *
- * Version:     $Id: memory.c,v 0.6.4 2002/06/25 20:18:34 acassen Exp $
- *
- * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
- *              Jan Holmberg, <jan@artech.net>
- *
- *              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.
- */
-
-#include "memory.h"
-
-void *xalloc(unsigned long size)
-{
-  void *mem;
-  if ((mem = malloc(size)))
-    mem_allocated += size;
-  return mem;
-}
-void *zalloc(unsigned long size)
-{
-  void *mem;
-  if ((mem = malloc(size))) {
-    memset(mem, 0, size);
-    mem_allocated += size;
-  }
-  return mem;
-}
-void xfree(void *p)
-{
-  mem_allocated -= sizeof(p);
-  free(p);
-}
-
-/* KeepAlived memory management. in debug mode,
- * help finding eventual memory leak.
- * Allocation memory types manipulated are :
- *
- * +type+--------meaning--------+
- * ! 0  ! Free slot             !
- * ! 1  ! Overrun               !
- * ! 2  ! free null             !
- * ! 3  ! realloc null          !
- * ! 4  ! Not previus allocated !
- * ! 8  ! Last free list        !
- * ! 9  ! Allocated             !
- * +----+-----------------------+
- *
- * global variabel debug bit 9 ( 512 ) used to
- * flag some memory error.
- *
- */
-
-#ifdef _DEBUG_
-extern void print_buffer(int,char *);
-
-typedef struct {
-  int           type;
-  int           line;
-  char          *func;
-  char          *file;
-  void          *ptr;
-  unsigned long size;
-  long          csum;
-} MEMCHECK;
-
-/* Last free pointers */
-static MEMCHECK free_list [256];
-
-static MEMCHECK alloc_list[512];
-static int number_alloc_list = 0;
-static int n                 = 0; /* Alloc list pointer */
-static int f                 = 0; /* Free list pointer */
-static int s                 = 0; /* Indent counter */
-
-static char * nspace(int n)
-{
-
-  return "";
-
-/*
- static char buf[64];
- int start = 0; 
- char *p;
- p = buf;
- while ( n-- > start ) {       
-  *p++ = ' '; 
- }
- *p=0;
-
- return buf;
-*/
-
-}
-
-char *keepalived_malloc(unsigned long size, char *file, char *function, int line)
-{
-  void *buf;
-  int i = 0;
-  long check;
-
-  buf = zalloc(size + sizeof(long));
-
-  check =  0xa5a5 + size;
-  *(long *)((char *)buf+size) = check;
-
-  while (i < number_alloc_list) {
-    if (alloc_list[i].type == 0)
-      break;
-    i++;
-  }
-
-  if (i == number_alloc_list)
-    number_alloc_list++;
-
-  alloc_list[i].ptr  = buf;
-  alloc_list[i].size = size;
-  alloc_list[i].file = file;
-  alloc_list[i].func = function;
-  alloc_list[i].line = line;
-  alloc_list[i].csum = check;
-  alloc_list[i].type = 9;
-
-  if (debug & 1)
-    printf("%szalloc[%3d:%3d], %p, %4ld at %s, %3d, %s\n"
-           ,nspace(s++), i, number_alloc_list, buf, size, file, line, function);
-
-  n++;
-  return buf;
-}
-
-int keepalived_free(void * buffer, char *file, char *function, int line)
-{
-  int i = 0;
-  void *buf;
-
-  /* If nullpointer remember */
-  if (buffer == NULL) {
-    i = number_alloc_list++;
-    alloc_list[i].ptr  = buffer;
-    alloc_list[i].size = 0;
-    alloc_list[i].file = file;
-    alloc_list[i].func = function;
-    alloc_list[i].line = line;
-    alloc_list[i].type = 2;
-    if (debug & 1)
-      printf("%sfree NULL in %s, %3d, %s\n", nspace(s),file, line, function);
-
-    debug |= 512;      /* Memory Error detect */
-
-    return n;
-  } else
-    buf = buffer;
-
-  while (i < number_alloc_list) {
-    if (alloc_list[i].type == 9 && alloc_list[i].ptr == buf) {
-      if (*((long *)((char *)alloc_list[i].ptr+alloc_list[i].size)) == alloc_list[i].csum)
-        alloc_list[i].type = 0; /* Release */
-      else {
-        alloc_list[i].type = 1; /* Overrun */
-        if (debug & 1) {  
-          printf("%sfree corrupt, buffer overrun [%3d:%3d], %p, %4ld at %s, %3d, %s\n"
-                 ,nspace(--s), i, number_alloc_list, buf, alloc_list[i].size, file, line, function);
-          print_buffer(alloc_list[i].size + sizeof(long), alloc_list[i].ptr);
-          printf("%sCheck_sum\n", nspace(i));
-          print_buffer(sizeof(long), (char *) & alloc_list[i].csum);
-
-          debug |= 512;   /* Memory Error detect */
-        }    
-      }
-      break;
-    }
-    i++;
-  }
-
-  /*  Not found */
-  if (i == number_alloc_list) {
-    printf("Free ERROR %p\n", buffer);
-    number_alloc_list++;
-    alloc_list[i].ptr  = buf;
-    alloc_list[i].size = 0;
-    alloc_list[i].file = file;
-    alloc_list[i].func = function;
-    alloc_list[i].line = line;
-    alloc_list[i].type = 4;
-    debug |= 512;
-
-    return n;
-  }
-
-  if (buffer != NULL)
-    free(buffer);
-
-  if (debug & 1)
-    printf("%sfree  [%3d:%3d], %p, %4ld at %s, %3d, %s\n"
-           , nspace(--s), i, number_alloc_list, buf, alloc_list[i].size, file, line, function);
-
-  free_list[f].file = file;
-  free_list[f].line = line;
-  free_list[f].func = function;
-  free_list[f].ptr  = buffer;
-  free_list[f].type = 8;
-  free_list[f].csum = i;  /* Using this field for row id */
-
-  f++;
-  f&=255;
-  n--;
-
-  return n;
-}
-
-void keepalived_free_final(void)
-{
-  unsigned int sum=0, overrun=0, badptr=0;
-  int i, j;
-  i = 0;
-
-  printf("\n---[Keepalived memory dump]---\n\n");
-
-  while (i < number_alloc_list) {
-    switch (alloc_list[i].type ) {
-      case 3:
-        badptr++;
-        printf("null pointer to realloc(nil,%ld)! at %s, %3d, %s\n"
-               , alloc_list[i].size
-               , alloc_list[i].file
-               , alloc_list[i].line
-               , alloc_list[i].func);
-        break;
-      case 4:
-        badptr++;
-        printf("pointer not found in table to free(%p) [%3d:%3d], at %s, %3d, %s\n"
-               , alloc_list[i].ptr
-               , i, number_alloc_list
-               , alloc_list[i].file
-               , alloc_list[i].line
-               , alloc_list[i].func);
-        for (j=0; j< 256; j++)
-          if (free_list[j].ptr == alloc_list[i].ptr)
-            if (free_list[j].type == 8)
-              printf("  -> pointer allready released at [%3d:%3d], at %s, %3d, %s\n"
-                     , (int) free_list[j].csum, number_alloc_list
-                     , free_list[j].file
-                     , free_list[j].line
-                     , free_list[j].func);
-        break;
-      case 2:
-        badptr++;
-        printf("null pointer to free(nil)! at %s, %3d, %s\n"
-               , alloc_list[i].file
-               , alloc_list[i].line
-               , alloc_list[i].func);
-        break;
-      case 1:
-        overrun ++;
-        printf("%p [%3d:%3d], %4ld buffer overrun!:\n"
-               , alloc_list[i].ptr
-               , i, number_alloc_list
-               , alloc_list[i].size);
-        printf(" --> source of malloc: %s, %3d, %s\n"
-               , alloc_list[i].file
-               , alloc_list[i].line
-               , alloc_list[i].func);
-        break;
-      case 9:
-        sum += alloc_list[i].size;
-        printf("%p [%3d:%3d], %4ld not released!:\n"
-               , alloc_list[i].ptr
-               , i, number_alloc_list
-               , alloc_list[i].size);
-        printf(" --> source of malloc: %s, %3d, %s\n"
-               , alloc_list[i].file
-               , alloc_list[i].line
-               , alloc_list[i].func);
-        break;
-    }
-    i++;
-  }
-
-  printf("\n\n---[Keepalived memory dump summary]---\n");
-  printf("Total number of bytes not freed...: %d\n", sum);
-  printf("Number of entries not freed.......: %d\n", n);
-  printf("Maximum allocated entries.........: %d\n", number_alloc_list);
-  printf("Number of bad entries.............: %d\n", badptr);
-  printf("Number of buffer overrun..........: %d\n\n", overrun);
-
-  if (sum || n || badptr || overrun)
-    printf("=> Program seems to have some memory problem !!!\n\n");
-  else
-    printf("=> Program seems to be memory allocation safe...\n\n");
-}
-
-void *keepalived_realloc(void * buffer, unsigned long size, char *file, char* function, int line)
-{
-  int i = 0;
-  void *buf, *buf2;
-  long check;
-
-  if (buffer == NULL) {
-    printf("realloc %p %s, %3d %s\n", buffer, file, line, function);
-    i = number_alloc_list++;
-    alloc_list[i].ptr  = NULL;
-    alloc_list[i].size = 0;
-    alloc_list[i].file = file;
-    alloc_list[i].func = function;
-    alloc_list[i].line = line;
-    alloc_list[i].type = 3;
-    return keepalived_malloc(size, file, function, line);
-  }
-
-  buf = buffer;
-
-  while (i < number_alloc_list) {
-    if (alloc_list[i].ptr == buf) {
-      buf = alloc_list[i].ptr;
-      break;
-    }
-    i++;
-  }
-
-  /* not found */
-  if (i == number_alloc_list) {
-    printf("realloc ERROR no matching zalloc %p \n", buffer);
-    number_alloc_list++;
-    alloc_list[i].ptr  = buf;
-    alloc_list[i].size = 0;
-    alloc_list[i].file = file;
-    alloc_list[i].func = function;
-    alloc_list[i].line = line;
-    alloc_list[i].type = 9;
-    debug |= 512;                     /* Memory Error detect */
-    return NULL;
-  }
-
-  buf2 = ((char *)buf)+alloc_list[i].size;
-
-  if (*(long *)(buf2) != alloc_list[i].csum) {
-    alloc_list[i].type = 1;
-    debug |= 512;                    /* Memory Error detect */
-  }
-  buf = realloc(buffer, size+sizeof(long));
-
-  check                       = 0xa5a5 + size;
-  *(long *)((char *)buf+size) = check;
-  alloc_list[i].csum          = check;
-
-  if (debug & 1)
-    printf("%srealloc [%3d:%3d] %p, %4ld %s %d %s -> %p %4ld %s %d %s\n"
-           , nspace(s),i, number_alloc_list
-           , alloc_list[i].ptr
-           , alloc_list[i].size, file, line, function, buf, size
-           , alloc_list[i].file
-           , alloc_list[i].line
-           , alloc_list[i].func);
-
-  alloc_list[i].ptr  = buf;
-  alloc_list[i].size = size;
-  alloc_list[i].file = file;
-  alloc_list[i].line = line;
-  alloc_list[i].func = function;
-
-  return buf;
-}
-
-#endif
diff --git a/parser.c b/parser.c
deleted file mode 100644 (file)
index 939cc35..0000000
--- a/parser.c
+++ /dev/null
@@ -1,772 +0,0 @@
-/* 
- * 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:        Configuration file parser/reader. Place into the dynamic
- *              data structure representation the conf file representing
- *              the loadbalanced server pool.
- *  
- * Version:     $Id: parser.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "parser.h"
-#include "memory.h"
-#include "vrrp.h"
-#include "vrrp_if.h"
-#include "check_api.h"
-
-/* global defs */
-static vector keywords;
-static int sublevel = 0;
-static FILE *stream;
-extern data *conf_data;
-extern unsigned long mem_allocated;
-
-static void keyword_alloc(vector keywords, char *string, void (*handler)(vector))
-{
-  struct keyword *keyword;
-
-  vector_alloc_slot(keywords);
-
-  keyword = (struct keyword *)MALLOC(sizeof(struct keyword));
-  keyword->string   = string;
-  keyword->handler  = handler;
-
-  vector_set_slot(keywords, keyword);
-}
-
-static void install_keyword_root(char *string, void (*handler)(vector))
-{
-  keyword_alloc(keywords, string, handler);
-}
-
-void install_sublevel(void)
-{
-  sublevel++;
-}
-void install_sublevel_end(void)
-{
-  sublevel--;
-}
-
-void install_keyword(char *string, void (*handler)(vector))
-{
-  int i = 0;
-  struct keyword *keyword;
-
-  /* fetch last keyword */
-  keyword = VECTOR_SLOT(keywords, VECTOR_SIZE(keywords)-1);
-
-  /* position to last sub level */
-  for (i = 0; i < sublevel; i++)
-    keyword = VECTOR_SLOT(keyword->sub, VECTOR_SIZE(keyword->sub)-1);
-
-  /* First sub level allocation */
-  if (!keyword->sub)
-    keyword->sub = vector_alloc();
-
-  /* add new sub keyword */
-  keyword_alloc(keyword->sub, string, handler);
-}
-
-static void dump_keywords(vector keydump, int level)
-{
-  int i, j;
-  struct keyword *keyword;
-
-  for (i = 0; i < VECTOR_SIZE(keydump); i++) {
-    keyword = VECTOR_SLOT(keydump, i);
-    for (j = 0; j < level; j++) printf("  ");
-    printf ("Keyword : %s\n", keyword->string);
-    if (keyword->sub)
-      dump_keywords(keyword->sub, level+1);
-  }
-}
-
-static void free_keywords(vector keywords)
-{
-  struct keyword *keyword;
-  int i;
-
-  for (i = 0; i < VECTOR_SIZE(keywords); i++) {
-    keyword = VECTOR_SLOT(keywords, i);
-    if (keyword->sub)
-      free_keywords(keyword->sub);
-    FREE(keyword);
-  }
-  vector_free(keywords);
-}
-
-static vector alloc_strvec(char *string)
-{
-  char *cp, *start, *token;
-  int strlen;
-  vector strvec;
-
-  if (!string)
-    return NULL;
-
-  cp = string;
-
-  /* Skip white spaces */
-  while (isspace((int) *cp) && *cp != '\0')
-    cp++;
-
-  /* Return if there is only white spaces */
-  if (*cp == '\0')
-    return NULL;
-
-  /* Return if string begin with a comment */
-  if (*cp == '!' || *cp == '#')
-    return NULL;
-
-  /* Create a vector and alloc each command piece */
-  strvec = vector_alloc();
-
-  while (1) {
-    start = cp;
-    if (*cp == '"') {
-      cp++;
-      token = MALLOC(2);
-      *(token)     = '"';
-      *(token + 1) = '\0';
-    } else {
-      while (!isspace((int) *cp) && *cp != '\0' && *cp != '"')
-        cp++;
-      strlen = cp - start;
-      token = MALLOC(strlen + 1);
-      memcpy(token, start, strlen);
-      *(token + strlen) = '\0';
-    }
-
-    /* Alloc & set the slot */
-    vector_alloc_slot(strvec);
-    vector_set_slot(strvec, token);
-
-    while (isspace((int) *cp) && *cp != '\0')
-      cp++;
-    if (*cp == '\0' || *cp == '!' || *cp == '#')
-      return strvec;
-  }
-}
-
-static int read_line(char *buf, int size)
-{
-  int ch;
-  int count = 0;
-
-  while ((ch = fgetc(stream)) != EOF && (int) ch != '\n'
-                                     && (int) ch != '\r') {
-    if (count < size)
-      buf[count] = (int) ch;
-    else
-      break;
-    count++;
-  }
-  return (ch == EOF)?0:1;
-}
-
-vector read_value_block(void)
-{
-  char *buf;
-  int i;
-  char *str = NULL;
-  char *dup;
-  vector vec = NULL;
-  vector elements = vector_alloc();
-
-  buf = (char *)MALLOC(MAXBUF);
-  while (read_line(buf, MAXBUF)) {
-    vec = alloc_strvec(buf);
-    if (vec) {
-      str = VECTOR_SLOT(vec, 0);
-      if (!strcmp(str, EOB)) {
-        free_strvec(vec);
-        break;
-      }
-
-      if (VECTOR_SIZE(vec))
-        for (i = 0; i < VECTOR_SIZE(vec); i++) {
-          str = VECTOR_SLOT(vec, i);
-          dup = (char *)MALLOC(strlen(str)+1);
-          memcpy(dup, str, strlen(str));
-          vector_alloc_slot(elements);
-          vector_set_slot(elements, dup);
-        }
-      free_strvec(vec);
-    }
-    memset(buf, 0, MAXBUF);
-  }
-  
-  FREE(buf);
-  return elements;
-}
-
-void *set_value(vector strvec)
-{
-  char *str = VECTOR_SLOT(strvec, 1);
-  int size = strlen(str);
-  int i = 0;
-  int len = 0;
-  char *alloc = NULL;
-
-  if (*str == '"') {
-    for (i = 2; i < VECTOR_SIZE(strvec); i++) {
-      str = VECTOR_SLOT(strvec, i);
-      len += strlen(str);
-      if (!alloc)
-        alloc = (char *)MALLOC(sizeof(char *) * (len + 1));
-      else {
-        alloc = REALLOC(alloc, sizeof(char *) * (len + 1));
-        strncat(alloc, " ", 1);
-      }
-      if (*str != '"')
-        strncat(alloc, str, strlen(str));
-    }
-  } else {
-    alloc = MALLOC(sizeof(char *) * (size + 1));
-    memcpy(alloc, str, size);
-  }
-  return alloc;
-}
-
-/* data handlers */
-/* Global def handlers */
-static void lvsid_handler(vector strvec)
-{
-  conf_data->lvs_id = set_value(strvec);
-}
-static void emailfrom_handler(vector strvec)
-{
-  conf_data->email_from = set_value(strvec);
-}
-static void smtpto_handler(vector strvec)
-{
-  conf_data->smtp_connection_to = atoi(VECTOR_SLOT(strvec, 1));
-}
-static void smtpip_handler(vector strvec)
-{
-  inet_ston(VECTOR_SLOT(strvec, 1), &conf_data->smtp_server);
-}
-static void email_handler(vector strvec)
-{
-  vector email = read_value_block();
-  int i;
-  char *str;
-
-  for (i = 0; i < VECTOR_SIZE(email); i++) {
-    str = VECTOR_SLOT(email, i);
-    alloc_email(str);
-  }
-
-  free_strvec(email);
-}
-
-/* SSL handlers */
-static void ssl_handler(vector strvec)
-{
-  conf_data->ssl = alloc_ssl();
-}
-static void sslpass_handler(vector strvec)
-{
-  conf_data->ssl->password = set_value(strvec);
-}
-static void sslca_handler(vector strvec)
-{
-  conf_data->ssl->cafile = set_value(strvec);
-}
-static void sslcert_handler(vector strvec)
-{
-  conf_data->ssl->certfile = set_value(strvec);
-}
-static void sslkey_handler(vector strvec)
-{
-  conf_data->ssl->keyfile = set_value(strvec);
-}
-
-/* VRRP handlers */
-static void vrrp_sync_group_handler(vector strvec)
-{
-  alloc_vrrp_sync_group(VECTOR_SLOT(strvec, 1));
-}
-static void vrrp_group_handler(vector strvec)
-{
-  vrrp_sgroup *vgroup = LIST_TAIL_DATA(conf_data->vrrp_sync_group);
-  vgroup->iname = read_value_block();
-}
-static void vrrp_gnotify_backup_handler(vector strvec)
-{
-  vrrp_sgroup *vgroup = LIST_TAIL_DATA(conf_data->vrrp_sync_group);
-  vgroup->script_backup = set_value(strvec);
-  vgroup->notify_exec = 1;
-}
-static void vrrp_gnotify_master_handler(vector strvec)
-{
-  vrrp_sgroup *vgroup = LIST_TAIL_DATA(conf_data->vrrp_sync_group);
-  vgroup->script_master = set_value(strvec);
-  vgroup->notify_exec = 1;
-}
-static void vrrp_gnotify_fault_handler(vector strvec)
-{
-  vrrp_sgroup *vgroup = LIST_TAIL_DATA(conf_data->vrrp_sync_group);
-  vgroup->script_fault = set_value(strvec);
-  vgroup->notify_exec = 1;
-}
-static void vrrp_handler(vector strvec)
-{
-  alloc_vrrp(VECTOR_SLOT(strvec, 1));
-}
-static void vrrp_state_handler(vector strvec)
-{
-  char *str = VECTOR_SLOT(strvec, 1);
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  vrrp_sgroup *vgroup = vrrp->sync;
-
-  if (!strcmp(str, "MASTER")) {
-    vrrp->wantstate  = VRRP_STATE_MAST;
-    vrrp->init_state = VRRP_STATE_MAST;
-  } else {
-    vrrp->wantstate  = VRRP_STATE_BACK;
-    vrrp->init_state = VRRP_STATE_BACK;
-  }
-
-  /* set eventual sync group */
-  if (vgroup)
-    vgroup->state = vrrp->wantstate;
-}
-static void vrrp_int_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  char *name = VECTOR_SLOT(strvec, 1);
-
-  vrrp->ifp = if_get_by_ifname(name);
-}
-static void vrrp_mcastip_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  inet_ston(VECTOR_SLOT(strvec, 1), &vrrp->mcast_saddr);
-}
-static void vrrp_vrid_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  vrrp->vrid = atoi(VECTOR_SLOT(strvec, 1));
-
-  if (VRRP_IS_BAD_VID(vrrp->vrid)) {
-    syslog(LOG_INFO, "VRRP Error : VRID not valid !\n");
-    syslog(LOG_INFO, "             must be between 1 & 255. reconfigure !\n");
-  }
-}
-static void vrrp_prio_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  vrrp->priority = atoi(VECTOR_SLOT(strvec, 1));
-
-  if (VRRP_IS_BAD_PRIORITY(vrrp->priority)) {
-    syslog(LOG_INFO, "VRRP Error : Priority not valid !\n");
-    syslog(LOG_INFO, "             must be between 1 & 255. reconfigure !\n");
-    syslog(LOG_INFO, "             Using default value : 100\n");
-    vrrp->priority = 100;
-  }
-}
-static void vrrp_adv_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  vrrp->adver_int = atoi(VECTOR_SLOT(strvec, 1));
-
-  if (VRRP_IS_BAD_ADVERT_INT(vrrp->adver_int)) {
-    syslog(LOG_INFO, "VRRP Error : Advert intervall not valid !\n");
-    syslog(LOG_INFO, "             must be between less than 1sec.\n");
-    syslog(LOG_INFO, "             Using default value : 1sec\n");
-    vrrp->adver_int = 1;
-  }
-  vrrp->adver_int *= TIMER_HZ;
-}
-static void vrrp_debug_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  vrrp->debug = atoi(VECTOR_SLOT(strvec, 1));
-
-  if (VRRP_IS_BAD_DEBUG_INT(vrrp->debug)) {
-    syslog(LOG_INFO, "VRRP Error : Debug intervall not valid !\n");
-    syslog(LOG_INFO, "             must be between 0-4\n");
-    vrrp->debug = 0;
-  }
-}
-static void vrrp_preempt_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  vrrp->preempt = !vrrp->preempt;
-}
-static void vrrp_notify_backup_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  vrrp->script_backup = set_value(strvec);
-  vrrp->notify_exec = 1;
-}
-static void vrrp_notify_master_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  vrrp->script_master = set_value(strvec);
-  vrrp->notify_exec = 1;
-}
-static void vrrp_notify_fault_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  vrrp->script_fault = set_value(strvec);
-  vrrp->notify_exec = 1;
-}
-static void vrrp_smtp_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  vrrp->smtp_alert = 1;
-}
-static void vrrp_lvs_syncd_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  vrrp->lvs_syncd_if = set_value(strvec);
-}
-static void vrrp_auth_type_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  char *str = VECTOR_SLOT(strvec, 1);
-
-  if (!strcmp(str, "AH"))
-    vrrp->auth_type = VRRP_AUTH_AH;
-  else
-    vrrp->auth_type = VRRP_AUTH_PASS;
-}
-static void vrrp_auth_pass_handler(vector strvec)
-{
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  char *str = VECTOR_SLOT(strvec, 1);
-  int max_size = sizeof(vrrp->auth_data);
-  int size;
-
-  size = (strlen(str) >= max_size)?max_size-1:strlen(str);
-  memcpy(vrrp->auth_data, str, size);
-}
-static void vrrp_vip_handler(vector strvec)
-{
-  vector vips   = read_value_block();
-  vrrp_rt *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
-  int i;
-  int nbvip = 0;
-
-  if (VECTOR_SIZE(vips) > VRRP_MAX_VIP) {
-    syslog(LOG_INFO, "VRRP_Instance(%s) use %d VIPs, trunc to the first %d VIPs."
-                   , vrrp->iname
-                   , VECTOR_SIZE(vips)
-                   , VRRP_MAX_VIP);
-    syslog(LOG_INFO, "  => Declare another VRRP instance to handle all the VIPs");
-    nbvip = VRRP_MAX_VIP;
-  } else
-    nbvip = VECTOR_SIZE(vips);
-
-  for (i = 0; i < nbvip; i++)
-    alloc_vrrp_vip(VECTOR_SLOT(vips, i));
-  free_strvec(vips);
-}
-static void vrrp_evip_handler(vector strvec)
-{
-  vector vips = read_value_block();
-  int i;
-
-  for (i = 0; i < VECTOR_SIZE(vips); i++)
-    alloc_vrrp_evip(VECTOR_SLOT(vips, i));
-  free_strvec(vips);
-}
-
-#ifdef _WITH_LVS_
-/* Real Servers groups handlers */
-static void group_handler(vector strvec)
-{
-  alloc_group(VECTOR_SLOT(strvec, 1));
-}
-static void rsgroup_handler(vector strvec)
-{
-  alloc_rsgroup(VECTOR_SLOT(strvec, 1), VECTOR_SLOT(strvec, 2));
-}
-static void group_weight_handler(vector strvec)
-{
-  real_server_group *group = LIST_TAIL_DATA(conf_data->group);
-  real_server *rs = LIST_TAIL_DATA(group->rs);
-  rs->weight = atoi(VECTOR_SLOT(strvec, 1));
-}
-
-/* Virtual Servers handlers */
-static void vs_handler(vector strvec)
-{
-  alloc_vs(VECTOR_SLOT(strvec, 1), VECTOR_SLOT(strvec, 2));
-}
-static void delay_handler(vector strvec)
-{
-  virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
-  vs->delay_loop = atoi(VECTOR_SLOT(strvec, 1));
-}
-static void lbalgo_handler(vector strvec)
-{
-  virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
-  char *str = VECTOR_SLOT(strvec, 1);
-  int size = sizeof(vs->sched);
-  
-  memcpy(vs->sched, str, size);
-}
-static void lbkind_handler(vector strvec)
-{
-  virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
-  char *str = VECTOR_SLOT(strvec, 1);
-
-#ifdef _KRNL_2_2_
-  if (!strcmp(str, "NAT"))
-    vs->loadbalancing_kind = 0;
-  else
-    if (!strcmp(str, "DR"))
-      vs->loadbalancing_kind = IP_MASQ_F_VS_DROUTE;
-    else
-      if (!strcmp(str, "TUN"))
-        vs->loadbalancing_kind = IP_MASQ_F_VS_TUNNEL;
-#else
-  if (!strcmp(str, "NAT"))
-    vs->loadbalancing_kind = IP_VS_CONN_F_MASQ;
-  else
-    if (!strcmp(str, "DR"))
-      vs->loadbalancing_kind = IP_VS_CONN_F_DROUTE;
-    else
-      if (!strcmp(str, "TUN"))
-        vs->loadbalancing_kind = IP_VS_CONN_F_TUNNEL;
-#endif
-      else
-        syslog(LOG_DEBUG, "PARSER : unknown [%s] routing method."
-                        , str);
-}
-static void natmask_handler(vector strvec)
-{
-  virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
-  inet_ston(VECTOR_SLOT(strvec, 1), &vs->nat_mask);
-}
-static void pto_handler(vector strvec)
-{
-  virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
-  char *str = VECTOR_SLOT(strvec, 1);
-  int size = sizeof(vs->timeout_persistence);
-  
-  memcpy(vs->timeout_persistence, str, size);
-}
-static void pgr_handler(vector strvec)
-{
-  virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
-  inet_ston(VECTOR_SLOT(strvec, 1), &vs->granularity_persistence);
-}
-static void proto_handler(vector strvec)
-{
-  virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
-  char *str = VECTOR_SLOT(strvec, 1);
-  vs->service_type = (!strcmp(str, "TCP"))?IPPROTO_TCP:IPPROTO_UDP;
-}
-static void virtualhost_handler(vector strvec)
-{
-  virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
-  vs->virtualhost = set_value(strvec);
-}
-
-/* Sorry Servers handlers */
-static void ssvr_handler(vector strvec)
-{
-  alloc_ssvr(VECTOR_SLOT(strvec, 1), VECTOR_SLOT(strvec, 2));
-}
-
-/* Real Servers handlers */
-static void rs_handler(vector strvec)
-{
-  alloc_rs(VECTOR_SLOT(strvec, 1), VECTOR_SLOT(strvec, 2));
-}
-static void weight_handler(vector strvec)
-{
-  virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
-  real_server *rs = LIST_TAIL_DATA(vs->rs);
-  rs->weight = atoi(VECTOR_SLOT(strvec, 1));
-}
-
-/* Real Servers Groups for VS handlers */
-static void realgroup_handler(vector strvec)
-{
-  set_rsgroup(VECTOR_SLOT(strvec, 1));
-}
-#endif
-
-/* recursive configuration stream handler */
-static void process_stream(vector keywords)
-{
-  int i;
-  struct keyword *keyword;
-  char *str;
-  char *buf;
-  vector strvec;
-
-  buf = MALLOC(MAXBUF);
-  if (!read_line(buf, MAXBUF)) {
-    FREE(buf);
-    return;
-  }
-
-  strvec = alloc_strvec(buf);
-  FREE(buf);
-
-  if (!strvec) {
-    process_stream(keywords);
-    return;
-  }
-
-  str = VECTOR_SLOT(strvec, 0);
-
-  if (!strcmp(str, EOB)) {
-    free_strvec(strvec);
-    return;
-  }
-
-  for (i = 0; i < VECTOR_SIZE(keywords); i++) {
-    keyword = VECTOR_SLOT(keywords, i);
-
-    if (!strcmp(keyword->string, str)) {
-      if (keyword->handler)
-        (*keyword->handler) (strvec);
-
-      if (keyword->sub)
-        process_stream(keyword->sub);
-      break;
-    }
-  }
-
-  free_strvec(strvec);
-  process_stream(keywords);
-}
-
-static vector init_keywords(void)
-{
-  keywords = vector_alloc();
-
-  /* global definitions mapping */
-  install_keyword_root("global_defs",          NULL);
-  install_keyword("lvs_id",                    &lvsid_handler);
-  install_keyword("notification_email_from",   &emailfrom_handler);
-  install_keyword("smtp_server",               &smtpip_handler);
-  install_keyword("smtp_connect_timeout",      &smtpto_handler);
-  install_keyword("notification_email",                &email_handler);
-
-  /* SSL mapping */
-  install_keyword_root("SSL",                  &ssl_handler);
-  install_keyword("password",                  &sslpass_handler);
-  install_keyword("ca",                                &sslca_handler);
-  install_keyword("certificate",               &sslcert_handler);
-  install_keyword("key",                       &sslkey_handler);
-
-  /* VRRP Instance mapping */
-  install_keyword_root("vrrp_sync_group",      &vrrp_sync_group_handler);
-  install_keyword("group",                     &vrrp_group_handler);
-  install_keyword("notify_backup",             &vrrp_gnotify_backup_handler);
-  install_keyword("notify_master",             &vrrp_gnotify_master_handler);
-  install_keyword("notify_fault",              &vrrp_gnotify_fault_handler);
-  install_keyword_root("vrrp_instance",                &vrrp_handler);
-  install_keyword("state",                     &vrrp_state_handler);
-  install_keyword("interface",                 &vrrp_int_handler);
-  install_keyword("mcast_src_ip",              &vrrp_mcastip_handler);
-  install_keyword("virtual_router_id",         &vrrp_vrid_handler);
-  install_keyword("priority",                  &vrrp_prio_handler);
-  install_keyword("advert_int",                        &vrrp_adv_handler);
-  install_keyword("virtual_ipaddress",         &vrrp_vip_handler);
-  install_keyword("virtual_ipaddress_excluded",        &vrrp_evip_handler);
-  install_keyword("preempt",                   &vrrp_preempt_handler);
-  install_keyword("debug",                     &vrrp_debug_handler);
-  install_keyword("notify_backup",             &vrrp_notify_backup_handler);
-  install_keyword("notify_master",             &vrrp_notify_master_handler);
-  install_keyword("notify_fault",              &vrrp_notify_fault_handler);
-  install_keyword("smtp_alert",                        &vrrp_smtp_handler);
-  install_keyword("lvs_sync_daemon_interface", &vrrp_lvs_syncd_handler);
-  install_keyword("authentication",            NULL);
-  install_sublevel();
-    install_keyword("auth_type",               &vrrp_auth_type_handler);
-    install_keyword("auth_pass",               &vrrp_auth_pass_handler);
-  install_sublevel_end();
-
-#ifdef _WITH_LVS_
-  /* Real server group mapping */
-  install_keyword_root("real_server_group",    &group_handler);
-  install_keyword("real_server",               &rsgroup_handler);
-  install_sublevel();
-    install_keyword("weight",                  &group_weight_handler);
-  install_sublevel_end();
-
-  /* Virtual server mapping */
-  install_keyword_root("virtual_server",       &vs_handler);
-  install_keyword("delay_loop",                &delay_handler);
-  install_keyword("lb_algo",                   &lbalgo_handler);
-  install_keyword("lb_kind",                   &lbkind_handler);
-  install_keyword("nat_mask",                  &natmask_handler);
-  install_keyword("persistence_timeout",       &pto_handler);
-  install_keyword("persistence_granularity",   &pgr_handler);
-  install_keyword("protocol",                  &proto_handler);
-  install_keyword("virtualhost",               &virtualhost_handler);
-
-  /* Real server mapping */
-  install_keyword("sorry_server",              &ssvr_handler);
-  install_keyword("real_server",               &rs_handler);
-  install_sublevel();
-    install_keyword("weight",                  &weight_handler);
-
-  /* Checkers mapping */
-    install_checkers_keyword();
-  install_sublevel_end();
-
-  /* VS group mapping */
-  install_keyword("real_group",                &realgroup_handler);
-  install_sublevel();
-    install_checkers_keyword();
-  install_sublevel_end();
-#endif
-
-  return keywords;
-}
-
-void init_data(char *conf_file)
-{
-  vector kw_root;
-  conf_data = NULL;
-  stream = fopen((conf_file)?conf_file:CONF, "r");
-  if (!stream) {
-    syslog(LOG_INFO, "Configuration file open problem...\n");
-    return;
-  }
-
-  /* Init Keywords structure */
-  kw_root = init_keywords();
-
-/* Dump configuration *
-  vector_dump(keywords);
-  dump_keywords(keywords, 0);
-*/
-
-  /* Init data structure */
-  conf_data = alloc_data();
-
-  /* Stream handling */
-  process_stream(keywords);
-
-  fclose(stream);
-  free_keywords(kw_root);
-
-  syslog(LOG_INFO, "Configuration is using : %lu Bytes"
-                 , mem_allocated);
-}
diff --git a/scheduler.c b/scheduler.c
deleted file mode 100644 (file)
index a3bf58e..0000000
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * 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:        Scheduling framework. This code is highly inspired from
- *              the thread management routine (thread.c) present in the 
- *              very nice zebra project (http://www.zebra.org).
- *
- * Version:     $Id: scheduler.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "scheduler.h"
-#include "memory.h"
-
-/* Make thread master. */
-thread_master *thread_make_master(void)
-{
-  thread_master *new;
-
-  new = (thread_master *)MALLOC(sizeof(thread_master));
-  return new;
-}
-
-/* Add a new thread to the list. */
-static void thread_list_add(thread_list *list, thread *thread)
-{
-  thread->next = NULL;
-  thread->prev = list->tail;
-  if (list->tail)
-    list->tail->next = thread;
-  else
-    list->head = thread;
-  list->tail = thread;
-  list->count++;
-}
-
-/* Add a new thread to the list. */
-void thread_list_add_before(thread_list *list
-                           , thread *point
-                           , thread *thread)
-{
-  thread->next = point;
-  thread->prev = point->prev;
-  if (point->prev)
-    point->prev->next = thread;
-  else
-    list->head = thread;
-  point->prev = thread;
-  list->count++;
-}
-
-/* Add a thread in the list sorted by timeval */
-void thread_list_add_timeval(thread_list *list, thread *thread)
-{
-  struct _thread *tt;
-
-  for (tt = list->head; tt; tt = tt->next)
-    if (timer_cmp (thread->sands, tt->sands) <= 0)
-      break;
-
-  if (tt)
-    thread_list_add_before (list, tt, thread);
-  else
-    thread_list_add (list, thread);
-}
-
-/* Delete a thread from the list. */
-thread *thread_list_delete(thread_list *list, thread *thread)
-{
-  if (thread->next)
-    thread->next->prev = thread->prev;
-  else
-    list->tail = thread->prev;
-  if (thread->prev)
-    thread->prev->next = thread->next;
-  else
-    list->head = thread->next;
-  thread->next = thread->prev = NULL;
-  list->count--;
-  return thread;
-}
-
-/* Free all unused thread. */
-static void thread_clean_unuse(thread_master *m)
-{
-  thread *thread;
-
-  thread = m->unuse.head;
-  while (thread) {
-    struct _thread *t;
-
-    t = thread;
-    thread = t->next;
-
-    thread_list_delete(&m->unuse, t);
-
-    /* free the thread */
-    FREE(t);
-    m->alloc--;
-  }
-}
-
-/* Move thread to unuse list. */
-static void thread_add_unuse(thread_master *m, thread *thread)
-{
-  assert(m != NULL);
-  assert(thread->next == NULL);
-  assert(thread->prev == NULL);
-  assert(thread->type == THREAD_UNUSED);
-  thread_list_add(&m->unuse, thread);
-}
-
-/* Move list element to unuse queue */
-void thread_destroy_list(thread_master *m, thread_list thread_list)
-{
-  thread *thread;
-
-  thread = thread_list.head;
-
-  while (thread) {
-    struct _thread *t;
-
-    t = thread;
-    thread = t->next;
-
-    thread_list_delete(&thread_list, t);
-    t->type = THREAD_UNUSED;
-    thread_add_unuse(m, t);
-  }
-}
-
-/* Stop thread scheduler. */
-void thread_destroy_master(thread_master *m)
-{
-  thread_destroy_list(m, m->read);
-  thread_destroy_list(m, m->write);
-  thread_destroy_list(m, m->timer);
-  thread_destroy_list(m, m->event);
-  thread_destroy_list(m, m->ready);
-
-  thread_clean_unuse(m);
-  FREE(m);
-}
-
-/* Delete top of the list and return it. */
-thread *thread_trim_head(thread_list *list)
-{
-  if (list->head)
-    return thread_list_delete (list, list->head);
-  return NULL;
-}
-
-/* Make new thread. */
-thread *thread_new(thread_master *m)
-{
-  thread *new;
-
-  /* If one thread is already allocated return it */
-  if (m->unuse.head) {
-    new = thread_trim_head(&m->unuse);
-    memset(new, 0, sizeof(thread));
-    return new;
-  }
-
-  new = (thread *)MALLOC(sizeof(thread));
-  m->alloc++;
-  return new;
-}
-
-/* Add new read thread. */
-thread *thread_add_read(thread_master *m
-                       , int (*func)(thread *)
-                       , void *arg
-                       , int fd
-                       , long timer)
-{
-  thread *thread;
-  TIMEVAL time_now;
-
-  assert(m != NULL);
-
-  if (FD_ISSET (fd, &m->readfd)) {
-    syslog(LOG_WARNING, "There is already read fd [%d]", fd);
-    return NULL;
-  }
-
-  thread = thread_new(m);
-  thread->type = THREAD_READ;
-  thread->id = 0;
-  thread->master = m;
-  thread->func = func;
-  thread->arg = arg;
-  FD_SET (fd, &m->readfd);
-  thread->u.fd = fd;
-
-  /* Compute read 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 the thread. */
-  thread_list_add_timeval(&m->read, thread); 
-
-  return thread;
-}
-
-/* Add new write thread. */
-thread *thread_add_write(thread_master *m
-                        , int (*func)(thread *)
-                        , void *arg
-                        , int fd
-                        , long timer)
-{
-  thread *thread;
-  TIMEVAL time_now;
-
-  assert(m != NULL);
-
-  if (FD_ISSET (fd, &m->writefd)) {
-    syslog(LOG_WARNING, "There is already write fd [%d]", fd);
-    return NULL;
-  }
-
-  thread = thread_new(m);
-  thread->type = THREAD_WRITE;
-  thread->id = 0;
-  thread->master = m;
-  thread->func = func;
-  thread->arg = arg;
-  FD_SET (fd, &m->writefd);
-  thread->u.fd = fd;
-
-  /* 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 the thread. */
-  thread_list_add_timeval(&m->write, thread); 
-
-  return thread;
-}
-
-/* Add timer event thread. */
-thread *thread_add_timer (thread_master *m
-                         , int (*func)(thread *)
-                         , void *arg
-                         , long timer)
-{
-  thread *thread;
-  TIMEVAL time_now;
-
-  assert(m != NULL);
-
-  thread = thread_new(m);
-  thread->type = THREAD_TIMER;
-  thread->id = 0;
-  thread->master = m;
-  thread->func = func;
-  thread->arg = arg;
-
-  /* Do we need jitter here? */
-  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->timer, thread); 
-
-  return thread;
-}
-
-/* Add simple event thread. */
-thread *thread_add_event(thread_master *m
-                        , int (*func)(thread *)
-                        , void *arg
-                        , int val)
-{
-  thread *thread;
-
-  assert(m != NULL);
-
-  thread = thread_new(m);
-  thread->type = THREAD_EVENT;
-  thread->id = 0;
-  thread->master = m;
-  thread->func = func;
-  thread->arg = arg;
-  thread->u.val = val;
-  thread_list_add (&m->event, thread);
-
-  return thread;
-}
-
-/* Add simple event thread. */
-thread *thread_add_terminate_event(thread_master *m)
-{
-  thread *thread;
-
-  assert(m != NULL);
-
-  thread = thread_new(m);
-  thread->type = THREAD_TERMINATE;
-  thread->id = 0;
-  thread->master = m;
-  thread->func = NULL;
-  thread->arg = NULL;
-  thread->u.val = 0;
-  thread_list_add(&m->event, thread);
-
-  return thread;
-}
-
-/* Cancel thread from scheduler. */
-void thread_cancel(thread *thread)
-{
-  switch (thread->type) {
-    case THREAD_READ:
-      assert (FD_ISSET (thread->u.fd, &thread->master->readfd));
-      FD_CLR (thread->u.fd, &thread->master->readfd);
-      thread_list_delete (&thread->master->read, thread);
-      break;
-    case THREAD_WRITE:
-      assert (FD_ISSET (thread->u.fd, &thread->master->writefd));
-      FD_CLR (thread->u.fd, &thread->master->writefd);
-      thread_list_delete (&thread->master->write, thread);
-      break;
-    case THREAD_TIMER:
-      thread_list_delete (&thread->master->timer, thread);
-      break;
-    case THREAD_EVENT:
-      thread_list_delete (&thread->master->event, thread);
-      break;
-    case THREAD_READY:
-      thread_list_delete (&thread->master->ready, thread);
-      break;
-    default:
-      break;
-  }
-
-  thread->type = THREAD_UNUSED;
-  thread_add_unuse(thread->master, thread);
-}
-
-/* Delete all events which has argument value arg. */
-void thread_cancel_event(thread_master *m, void *arg)
-{
-  thread *thread;
-
-  thread = m->event.head;
-  while (thread) {
-    struct _thread *t;
-
-    t = thread;
-    thread = t->next;
-
-    if (t->arg == arg) {
-      thread_list_delete (&m->event, t);
-      t->type = THREAD_UNUSED;
-      thread_add_unuse (m, t);
-    }
-  }
-}
-
-/* Compute the wait timer. Take care of timeouted fd */
-TIMEVAL *thread_compute_timer(thread_master *m, TIMEVAL *timer_wait)
-{
-  TIMEVAL time_now;
-  TIMEVAL timer_min;
-
-  TIMER_RESET(timer_min);
-  time_now = timer_now();
-
-  if (m->timer.head)
-    timer_min = m->timer.head->sands;
-
-  if (m->write.head) {
-    if (!TIMER_ISNULL(timer_min)) {
-      if (timer_cmp(m->write.head->sands, timer_min) <= 0)
-          timer_min = m->write.head->sands;
-    } else
-      timer_min = m->write.head->sands;
-  }
-
-  if (m->read.head) {
-    if (!TIMER_ISNULL(timer_min)) {
-      if (timer_cmp(m->read.head->sands, timer_min) <= 0)
-          timer_min = m->read.head->sands;
-    } else
-      timer_min = m->read.head->sands;
-  }
-
-  if (!TIMER_ISNULL(timer_min)) {
-    timer_min = timer_sub (timer_min, time_now);
-    if (timer_min.tv_sec < 0) {
-      timer_min.tv_sec = 0;
-      timer_min.tv_usec = 10;
-    }
-    timer_wait->tv_sec = timer_min.tv_sec;
-    timer_wait->tv_usec = timer_min.tv_usec;
-  } else
-    timer_wait = NULL;
-
-  return timer_wait;
-}
-
-/* Fetch next ready thread. */
-thread *thread_fetch(thread_master *m, thread *fetch)
-{
-  int ret;
-  thread *thread;
-  fd_set readfd;
-  fd_set writefd;
-  fd_set exceptfd;
-  TIMEVAL time_now;
-  TIMEVAL *timer_wait;
-
-  assert(m != NULL);
-
-  /* Timer allocation */
-  timer_wait = (TIMEVAL *)MALLOC(sizeof(TIMEVAL));
-
-retry:  /* When thread can't fetch try to find next thread again. */
-
-  /* If there is event process it first. */
-  while ((thread = thread_trim_head(&m->event))) {
-    *fetch = *thread;
-    FREE(timer_wait);
-
-    /* If daemon hanging event is received return NULL pointer */ 
-    if (thread->type == THREAD_TERMINATE) {
-      thread->type = THREAD_UNUSED;
-      thread_add_unuse(m, thread);
-      return NULL;
-    }
-    thread->type = THREAD_UNUSED;
-    thread_add_unuse(m, thread);
-    return fetch;
-  }
-
-  /* If there is ready threads process them */
-  while ((thread = thread_trim_head(&m->ready))) {
-    *fetch = *thread;
-    thread->type = THREAD_UNUSED;
-    thread_add_unuse(m, thread);
-    FREE(timer_wait);
-    return fetch;
-  }
-
-  /* Calculate select wait timer. Take care of timeouted fd */
-  timer_wait = thread_compute_timer(m, timer_wait);
-
-  /* Call select function. */
-  readfd   = m->readfd;
-  writefd  = m->writefd;
-  exceptfd = m->exceptfd;
-
-  ret = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
-  if (ret < 0) {
-    if (errno != EINTR) {
-      /* Real error. */
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "select error: %s", strerror (errno));
-#endif
-      assert (0);
-    }
-    /* Signal is coming. */
-    goto retry;
-  }
-
-  /* Read thead. */
-  time_now = timer_now();
-  thread = m->read.head;
-
-  while (thread) {
-    struct _thread *t;
-      
-    t = thread;
-    thread = t->next;
-
-    if (FD_ISSET (t->u.fd, &readfd)) {
-      assert (FD_ISSET (t->u.fd, &m->readfd));
-      FD_CLR(t->u.fd, &m->readfd);
-      thread_list_delete (&m->read, t);
-      thread_list_add (&m->ready, t);
-      t->type = THREAD_READY;
-    } else {
-      if (timer_cmp(time_now, t->sands) >= 0) {
-        FD_CLR(t->u.fd, &m->readfd);
-        thread_list_delete (&m->read, t);
-        thread_list_add (&m->ready, t);
-        t->type = THREAD_READ_TIMEOUT;
-      }
-    }
-  }
-
-  /* Write thead. */
-  time_now = timer_now();
-  thread = m->write.head;
-
-  while (thread) {
-    struct _thread *t;
-
-    t = thread;
-    thread = t->next;
-
-    if (FD_ISSET (t->u.fd, &writefd)) {
-      assert (FD_ISSET (t->u.fd, &writefd));
-      FD_CLR(t->u.fd, &m->writefd);
-      thread_list_delete (&m->write, t);
-      thread_list_add (&m->ready, t);
-      t->type = THREAD_READY;
-    } else {
-      if (timer_cmp(time_now, t->sands) >= 0) {
-        FD_CLR(t->u.fd, &m->writefd);
-        thread_list_delete (&m->write, t);
-        thread_list_add (&m->ready, t);
-        t->type = THREAD_WRITE_TIMEOUT;
-      }
-    }
-  }
-  /* Exception thead. */
-  /*...*/
-
-  /* Timer update. */
-  time_now = timer_now();
-
-  thread = m->timer.head;
-  while (thread) {
-    struct _thread *t;
-
-    t = thread;
-    thread = t->next;
-
-    if (timer_cmp (time_now, t->sands) >= 0) {
-      thread_list_delete (&m->timer, t);
-      thread_list_add (&m->ready, t);
-      t->type = THREAD_READY;
-    }
-  }
-
-  /* Return one event. */
-  thread = thread_trim_head (&m->ready);
-
-  /* There is no ready thread. */
-  if (!thread)
-    goto retry;
-
-  *fetch = *thread;
-  thread->type = THREAD_UNUSED;
-  thread_add_unuse (m, thread);
-  
-  FREE(timer_wait);
-  return fetch;
-}
-
-/* Make unique thread id for non pthread version of thread manager. */
-unsigned long int thread_get_id(void)
-{
-  static unsigned long int counter = 0;
-  return ++counter;
-}
-
-/* Call thread ! */
-void thread_call(thread *thread)
-{
-  thread->id = thread_get_id ();
-  (*thread->func) (thread);
-}
diff --git a/smtp.c b/smtp.c
deleted file mode 100644 (file)
index 6e7ed64..0000000
--- a/smtp.c
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * 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:        SMTP WRAPPER connect to a specified smtp server and send mail
- *              using the smtp protocol according to the RFC 821. A non blocking
- *              timeouted connection is used to handle smtp protocol.
- *
- * Version:     $Id: smtp.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "smtp.h"
-#include "memory.h"
-#include "list.h"
-#include "utils.h"
-
-extern data *conf_data;
-
-/* static prototype */
-static int smtp_send_cmd_thread(thread *);
-
-static void free_smtp_all(smtp_thread_arg *smtp_arg)
-{
-  FREE(smtp_arg->buffer);
-  FREE(smtp_arg->subject);
-  FREE(smtp_arg->body);
-  FREE(smtp_arg);
-}
-
-static char *fetch_next_email(smtp_thread_arg *smtp_arg)
-{
-  return list_element(conf_data->email, smtp_arg->email_it);
-}
-
-static int smtp_read_cmd_thread(thread *thread)
-{
-  smtp_thread_arg *smtp_arg;
-  char *fetched_email;
-  char *buffer;
-  char *reply;
-  int rcv_buffer_size = 0;
-  int status = -1;
-
-  smtp_arg = THREAD_ARG(thread);
-
-  if (thread->type == THREAD_READ_TIMEOUT) {
-#ifdef _DEBUG_
-    syslog(LOG_DEBUG, "Timeout reading data to remote SMTP server [%s:%d].",
-                      inet_ntop2(conf_data->smtp_server),
-                      SMTP_PORT);
-#endif
-    free_smtp_all(smtp_arg);
-    close(thread->u.fd);
-    return 0;
-  }
-
-  buffer = smtp_arg->buffer;
-
-  while ((rcv_buffer_size = read(thread->u.fd, buffer + smtp_arg->buflen, SMTP_BUFFER_LENGTH - smtp_arg->buflen)) != 0) {
-    if (rcv_buffer_size == -1) {
-      if (errno == EAGAIN) goto end;
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "Error reading data to remote SMTP server [%s:%d]."
-                      , inet_ntop2(conf_data->smtp_server)
-                      , SMTP_PORT);
-#endif
-      free_smtp_all(smtp_arg);
-      close(thread->u.fd);
-      return 0;
-    }
-
-    /* received data overflow buffer size ? */
-    if (smtp_arg->buflen >= SMTP_BUFFER_MAX) {
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "Received buffer from remote SMTP server [%s:%d]"
-                        " overflow our get read buffer length."
-                      , inet_ntop2(conf_data->smtp_server)
-                      , SMTP_PORT);
-#endif
-      free_smtp_all(smtp_arg);
-      close(thread->u.fd);
-      return 0;
-    } else {
-      smtp_arg->buflen += rcv_buffer_size;
-      buffer[smtp_arg->buflen] = 0;   /* NULL terminate */
-      if (rcv_buffer_size < SMTP_BUFFER_LENGTH) goto end;
-    }
-  }
-
-end:
-
-// printf("Received : %s", buffer);
-
-  /* parse the buffer, finding the last line of the response for the code */
-  reply = buffer;
-  while (reply < buffer + smtp_arg->buflen) {
-    char *p;
-
-    p = strstr(reply, "\r\n");
-    if (!p) {
-      memmove(buffer, reply, smtp_arg->buflen - (reply - buffer));
-      smtp_arg->buflen -= (reply - buffer);
-      buffer[smtp_arg->buflen] = 0;
-
-      thread_add_read(thread->master, smtp_read_cmd_thread
-                                    , smtp_arg
-                                    , thread->u.fd
-                                    , conf_data->smtp_connection_to);
-      return 0;
-    }
-
-    if (reply[3] == '-') {
-      /* Skip over the \r\n */
-      reply = p + 2;
-      continue;
-    }
-
-    status = ((reply[0] - '0') * 100) + ((reply[1] - '0') * 10) + (reply[2] - '0');
-
-    reply = p + 2;
-    break;
-  }
-
-  memmove(buffer, reply, smtp_arg->buflen - (reply - buffer));
-  smtp_arg->buflen -= (reply - buffer);
-  buffer[smtp_arg->buflen] = 0;
-
-  if (status == -1) {
-    thread_add_read(thread->master, smtp_read_cmd_thread
-                                  , smtp_arg
-                                  , thread->u.fd
-                                  , conf_data->smtp_connection_to);
-    return 0;
-  }
-
-  /* setting the next stage */
-  switch (smtp_arg->stage) {
-    case CONNECTION:
-      if (status == 220) {
-        smtp_arg->stage = HELO;
-      } else {
-        syslog(LOG_DEBUG, "Error connecting smtp server : [%s]", buffer);
-        smtp_arg->stage = ERROR;
-      }
-      break;
-
-    case HELO:
-      if (status == 250) {
-        smtp_arg->stage = MAIL;
-      } else {
-        syslog(LOG_DEBUG, "Error processing HELO cmd : [%s]", buffer);
-        smtp_arg->stage = ERROR;
-      }
-      break;
-
-    case MAIL:
-      if (status == 250) {
-        smtp_arg->stage = RCPT;
-      } else {
-        syslog(LOG_DEBUG, "Error processing MAIL FROM cmd : [%s]", buffer);
-        smtp_arg->stage = ERROR;
-      }
-      break;
-
-    case RCPT:
-      if (status == 250) {
-        smtp_arg->email_it++;
-
-        fetched_email = fetch_next_email(smtp_arg);
-
-        if (!fetched_email)
-          smtp_arg->stage = DATA;
-      } else {
-        syslog(LOG_DEBUG, "Error processing RCPT TO cmd : [%s]", buffer);
-        smtp_arg->stage = ERROR;
-      }
-      break;
-
-    case DATA:
-      if (status == 354) {
-        smtp_arg->stage = BODY;
-      } else {
-        syslog(LOG_DEBUG, "Error processing DATA cmd : [%s]", buffer);
-        smtp_arg->stage = ERROR;
-      }
-      break;
-
-    case BODY:
-      if (status == 250) {
-        smtp_arg->stage = QUIT;
-        syslog(LOG_INFO, "SMTP alert successfully sent.");
-      } else {
-        syslog(LOG_DEBUG, "Error processing DOT cmd : [%s]", buffer);
-        smtp_arg->stage = ERROR;
-      }
-      break;
-
-    case QUIT:
-      /* final state, we are disconnected from the remote host */
-      free_smtp_all(smtp_arg);
-      close(thread->u.fd);
-      return 0;
-
-    case ERROR:
-      break;
-  }
-
-  /* Registering next smtp command processing thread */
-  thread_add_write(thread->master, smtp_send_cmd_thread
-                                 , smtp_arg
-                                 , thread->u.fd
-                                 , conf_data->smtp_connection_to);
-  return 0;
-}
-
-/* Getting localhost official canonical name */
-static char *get_local_name(void)
-{
-  struct hostent *host;
-  struct utsname name;
-
-  if (uname(&name) < 0)
-    return NULL;
-
-  if (!(host = gethostbyname(name.nodename)))
-    return NULL;
-
-  return host->h_name;
-}
-
-static int smtp_send_cmd_thread(thread *thread)
-{
-  smtp_thread_arg *smtp_arg;
-  char *fetched_email;
-  char *buffer;
-
-  smtp_arg = THREAD_ARG(thread);
-
-  if (thread->type == THREAD_WRITE_TIMEOUT) {
-#ifdef _DEBUG_
-    syslog(LOG_DEBUG, "Timeout sending data to remote SMTP server [%s:%d]."
-                    , inet_ntop2(conf_data->smtp_server)
-                    , SMTP_PORT);
-#endif
-    free_smtp_all(smtp_arg);
-    close(thread->u.fd);
-    return 0;
-  }
-
-  /* allocate temporary command buffer */
-  buffer = (char *)MALLOC(SMTP_BUFFER_MAX);
-
-  switch (smtp_arg->stage) {
-    case CONNECTION:
-      break;
-
-    case HELO:
-      snprintf(buffer, SMTP_BUFFER_MAX, SMTP_HELO_CMD, get_local_name());
-      if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
-        smtp_arg->stage = ERROR;
-      break;
-
-    case MAIL:
-      snprintf(buffer, SMTP_BUFFER_MAX, SMTP_MAIL_CMD, conf_data->email_from);
-      if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
-        smtp_arg->stage = ERROR;
-      break;
-
-    case RCPT:
-      /* We send RCPT TO command multiple time to add all our email receivers.
-       * --rfc821.3.1
-       */
-      fetched_email = fetch_next_email(smtp_arg);
-
-      snprintf(buffer, SMTP_BUFFER_MAX, SMTP_RCPT_CMD, fetched_email);
-      if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
-        smtp_arg->stage = ERROR;
-      break;
-
-    case DATA:
-      if (send(thread->u.fd, SMTP_DATA_CMD, strlen(SMTP_DATA_CMD), 0) == -1)
-        smtp_arg->stage = ERROR;
-      break;
-
-    case BODY:
-      snprintf(buffer, SMTP_BUFFER_MAX, SMTP_HEADERS_CMD
-                     , conf_data->email_from
-                     , smtp_arg->subject);
-      /* send the subject field */
-      if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
-        smtp_arg->stage = ERROR;
-
-      memset(buffer, 0, SMTP_BUFFER_MAX);
-      snprintf(buffer, SMTP_BUFFER_MAX, SMTP_BODY_CMD, smtp_arg->body);
-      /* send the the body field */
-      if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
-        smtp_arg->stage = ERROR;
-
-      /* send the sending dot */
-      if (send(thread->u.fd, SMTP_SEND_CMD, strlen(SMTP_SEND_CMD), 0) == -1)
-        smtp_arg->stage = ERROR;
-      break;
-
-    case QUIT:
-      if (send(thread->u.fd, SMTP_QUIT_CMD, strlen(SMTP_QUIT_CMD), 0) == -1)
-        smtp_arg->stage = ERROR;
-      break;
-
-    case ERROR:
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "Can not send data to remote SMTP server [%s:%d]."
-                      , inet_ntop2(conf_data->smtp_server)
-                      , SMTP_PORT);
-#endif
-      /* we just cleanup the room */
-      free_smtp_all(smtp_arg);
-      close(thread->u.fd);
-      FREE(buffer);
-      return 0;
-      break;
-  }
-
-// printf("Sending : %s", buffer);
-
-  /* Registering next smtp command processing thread */
-  thread_add_read(thread->master, smtp_read_cmd_thread
-                                , smtp_arg
-                                , thread->u.fd
-                                , conf_data->smtp_connection_to);
-
-  FREE(buffer);
-  return 0;
-}
-
-/* SMTP checkers threads */
-static int smtp_check_thread(thread *thread)
-{
-  smtp_thread_arg *smtp_arg;
-  int status;
-
-  smtp_arg = THREAD_ARG(thread);
-
-  status = tcp_socket_state(thread->u.fd, thread
-                                        , conf_data->smtp_server
-                                        , htons(SMTP_PORT)
-                                        , smtp_check_thread);
-
-  switch (status) {
-    case connect_error:
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "Error connecting SMTP server [%s:%d]."
-                      , inet_ntop2(conf_data->smtp_server)
-                      , SMTP_PORT);
-#endif
-      free_smtp_all(smtp_arg);
-      break;
-
-    case connect_timeout:
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "Timeout writing data to SMTP server [%s:%d]."
-                      , inet_ntop2(conf_data->smtp_server)
-                      , SMTP_PORT);
-#endif
-      free_smtp_all(smtp_arg);
-      break;
-
-    case connect_success:
-      /* Remote SMTP server is connected.
-       * Register the next step thread smtp_cmd_thread.
-       */
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "Remote SMTP server [%s:%d] connected."
-                      , inet_ntop2(conf_data->smtp_server)
-                      , SMTP_PORT);
-#endif
-      thread_add_write(thread->master, smtp_send_cmd_thread
-                                     , smtp_arg
-                                     , thread->u.fd
-                                     , conf_data->smtp_connection_to);
-      break;
-  }
-
-  return 0;
-}
-
-static int smtp_connect_thread(thread *thread)
-{
-  smtp_thread_arg *smtp_arg;
-  enum connect_result status;
-  int fd;
-
-  smtp_arg = THREAD_ARG(thread);
-
-  /* Return if no smtp server is defined */
-  if (conf_data->smtp_server == 0) {
-    free_smtp_all(smtp_arg);
-    return 0;
-  }
-
-  if ( (fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
-#ifdef _DEBUG_
-    syslog(LOG_DEBUG, "SMTP connect fail to create socket.");
-#endif
-    return 0;
-  }
-
-  status = tcp_connect(fd, conf_data->smtp_server, htons(SMTP_PORT));
-
-  switch (status) {
-    case connect_error:
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "SMTP connection ERROR to [%s:%d]."
-                      , inet_ntop2(conf_data->smtp_server)
-                      , SMTP_PORT);
-#endif
-      free_smtp_all(smtp_arg);
-      close(fd);
-      return 0;
-      break;
-
-    case connect_timeout:
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "Timeout connecting SMTP server [%s:%d]."
-                      , inet_ntop2(conf_data->smtp_server)
-                      , SMTP_PORT);
-#endif
-      free_smtp_all(smtp_arg);
-      close(fd);
-      return 0;
-      break;
-
-    case connect_success:
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "SMTP connection SUCCESS to [%s:%d]."
-                      , inet_ntop2(conf_data->smtp_server)
-                      , SMTP_PORT);
-#endif
-      break;
-
-    /* Checking non-blocking connect, we wait until socket is writable */
-    case connect_in_progress:
-#ifdef _DEBUG_
-      syslog(LOG_DEBUG, "SMTP connection to [%s:%d] now IN_PROGRESS."
-                      , inet_ntop2(conf_data->smtp_server)
-                      , SMTP_PORT);
-#endif
-      break;
-  }
-
-  /* connection have succeeded or still in progress */
-  thread_add_write(thread->master, smtp_check_thread
-                                 , smtp_arg
-                                 , fd
-                                 , conf_data->smtp_connection_to);
-  return 1;
-}
-
-void smtp_alert(thread_master *master
-                , real_server *rs
-                , vrrp_rt *vrrp
-                , const char *subject
-                , const char *body)
-{
-  smtp_thread_arg *smtp_arg;
-
-  /* Only send mail if email specified */
-  if (!LIST_ISEMPTY(conf_data->email)) {
-    /* allocate & initialize smtp argument data structure */
-    smtp_arg          = (smtp_thread_arg *)MALLOC(sizeof(smtp_thread_arg));
-    smtp_arg->subject = (char *)MALLOC(MAX_HEADERS_LENGTH);
-    smtp_arg->body    = (char *)MALLOC(MAX_BODY_LENGTH);
-    smtp_arg->buffer  = (char *)MALLOC(SMTP_BUFFER_MAX);
-
-    smtp_arg->stage = CONNECTION; /* first smtp command set to HELO */
-
-    /* format subject if rserver is specified */
-    if (rs)
-      snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH
-                                , "[%s] Realserver %s:%d - %s"
-                                , conf_data->lvs_id
-                                , inet_ntop2(SVR_IP(rs))
-                                , ntohs(SVR_PORT(rs))
-                                , subject);
-    else if (vrrp)
-      snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH
-                                , "[%s] VRRP Instance %s - %s"
-                                , conf_data->lvs_id
-                                , vrrp->iname
-                                , subject);
-    else if (conf_data->lvs_id)
-      snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH, "[%s] %s"
-                                , conf_data->lvs_id
-                                , subject);
-    else
-      snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH, "%s"
-                                , subject);
-
-    strncpy(smtp_arg->body, body, MAX_BODY_LENGTH);
-
-    thread_add_event(master, smtp_connect_thread, smtp_arg, 0);
-  }
-}
diff --git a/utils.c b/utils.c
deleted file mode 100644 (file)
index 121fa99..0000000
--- a/utils.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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:        General program utils.
- *
- * Version:     $Id: utils.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "utils.h"
-
-/* Display a buffer into a HEXA formated output */
-void print_buffer(int count, char *buff)
-{
-  int i,j,c;
-  int printnext=1;
-
-  if(count) {
-    if(count%16)
-      c=count+(16-count%16);
-    else c=count;
-  } else
-    c=count;
-
-  for(i=0;i<c;i++) {
-    if(printnext) {
-      printnext--;
-      printf("%.4x ",i&0xffff);
-    }
-    if(i<count)
-      printf("%3.2x",buff[i]&0xff);
-    else
-      printf("   ");
-    if(!((i+1)%8)) {
-      if((i+1)%16)
-        printf(" -");
-      else {
-        printf("   ");
-        for(j=i-15;j<=i;j++)
-          if(j<count) {
-            if( (buff[j]&0xff) >= 0x20 && (buff[j]&0xff)<=0x7e)
-              printf("%c",buff[j]&0xff);
-            else printf(".");
-          } else printf(" ");
-        printf("\n"); printnext=1;
-      }
-    }
-  }
-}
-
-/* IP network to ascii representation */
-char *inet_ntop2(uint32_t ip)
-{
-  static char buf[16];
-  unsigned char *bytep;
-
-  bytep = (unsigned char *) &(ip);
-  sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]);
-  return buf;
-}
-
-/*
- * IP network to ascii representation. To use
- * for multiple IP address convertion into the same call.
- */
-char *inet_ntoa2(uint32_t ip, char *buf)
-{
-  unsigned char *bytep;
-
-  bytep = (unsigned char *) &(ip);
-  sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]);
-  return buf;
-}
-
-/* IP string to network mask representation */
-uint8_t inet_stom(char *addr)
-{
-  uint8_t mask = 32;
-  char *cp = addr;
-
-  if (!strstr(addr, "/"))
-    return mask;
-  while (*cp != '/' && *cp != '\0')
-    cp++;
-  if (*cp == '/')
-    return atoi(++cp);
-  return mask;
-}
-
-/*
- * IP string to network representation
- * Highly inspired from Paul Vixie code.
- */
-int inet_ston(const char *addr, uint32_t *dst)
-{
-  static char digits[] = "0123456789";
-  int saw_digit, octets, ch;
-  u_char tmp[INADDRSZ], *tp;
-
-  saw_digit = 0;
-  octets = 0;
-  *(tp = tmp) = 0;
-
-  while ((ch = *addr++) != '\0' && ch != '/') {
-    const char *pch;
-    if ((pch = strchr(digits, ch)) != NULL) {
-      u_int new = *tp * 10 + (pch - digits);
-      if (new > 255)
-        return 0;
-      *tp = new;
-      if (!saw_digit) {
-        if (++octets > 4)
-          return 0;
-        saw_digit = 1;
-      }
-    } else if (ch == '.' && saw_digit) {
-      if (octets == 4)
-        return 0;
-      *++tp = 0;
-      saw_digit = 0;
-    } else
-      return 0;
-  }
-
-  if (octets < 4)
-    return 0;
-
-  memcpy(dst, tmp, INADDRSZ);
-  return 1;
-}
diff --git a/vrrp.c b/vrrp.c
deleted file mode 100644 (file)
index 20b274a..0000000
--- a/vrrp.c
+++ /dev/null
@@ -1,1101 +0,0 @@
-/*
- * 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 implementation of VRRPv2 as specified in rfc2338.
- *              VRRP is a protocol which elect a master server on a LAN. If the
- *              master fails, a backup server takes over.
- *              The original implementation has been made by jerome etienne.
- *
- * Version:     $Id: vrrp.c,v 0.6.4 2002/06/25 20:18: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 <ctype.h>
-#include "vrrp_scheduler.h"
-#include "vrrp_notify.h"
-#include "ipvswrapper.h"
-#include "vrrp.h"
-#include "memory.h"
-#include "list.h"
-#include "data.h"
-
-extern data *conf_data;
-
-/* compute checksum */
-static u_short in_csum( u_short *addr, int len, u_short csum)
-{
-  register int nleft = len;
-  const u_short *w = addr;
-  register u_short answer;
-  register int sum = csum;
-
-  /*
-   *  Our algorithm is simple, using a 32 bit accumulator (sum),
-   *  we add sequential 16 bit words to it, and at the end, fold
-   *  back all the carry bits from the top 16 bits into the lower
-   *  16 bits.
-   */
-  while (nleft > 1)  {
-    sum += *w++;
-    nleft -= 2;
-  }
-
-  /* mop up an odd byte, if necessary */
-  if (nleft == 1)
-    sum += htons(*(u_char *)w << 8);
-
-  /*
-   * add back carry outs from top 16 bits to low 16 bits
-   */
-  sum = (sum >> 16) + (sum & 0xffff);  /* add hi 16 to low 16 */
-  sum += (sum >> 16);      /* add carry */
-  answer = ~sum;        /* truncate to 16 bits */
-  return (answer);
-}
-
-/*
- * add/remove VIP
- * retry must clear for each vip address Hoj:-
- */
-static int vrrp_handle_ipaddress(vrrp_rt *vrrp, int cmd, int type)
-{
-  int i, err = 0;
-  int retry = 0;
-  int num;
-  int ifindex = IF_INDEX(vrrp->ifp);
-
-  syslog(LOG_INFO, "VRRP_Instance(%s) %s protocol %s"
-                 , vrrp->iname
-                 , (cmd == VRRP_IPADDRESS_ADD)?"setting":"removing"
-                 , (type == VRRP_VIP_TYPE)?"VIPs.":"E-VIPs");
-
-  num = (type == VRRP_VIP_TYPE)?vrrp->naddr:vrrp->neaddr;
-  for(i = 0; i < num; i++ ) {
-    vip_addr *vadd = (type == VRRP_VIP_TYPE)?&vrrp->vaddr[i]:&vrrp->evaddr[i];
-    if(!cmd && !vadd->set) continue;
-retry:
-    if (netlink_address_ipv4(ifindex , vadd->addr, vadd->mask, cmd) < 0) {
-      err = 1;
-      vadd->set = 0;
-      syslog(LOG_INFO, "cant %s the address %s to %s\n"
-                     , cmd ? "set" : "remove"
-                     , inet_ntop2(vadd->addr)
-                     , IF_NAME(vrrp->ifp));
-      if (cmd == VRRP_IPADDRESS_ADD) {
-        syslog(LOG_INFO, "try to delete eventual stalled ip");
-        netlink_address_ipv4(ifindex, vadd->addr, vadd->mask, VRRP_IPADDRESS_DEL);
-        if (retry < 4) {
-          retry++;
-          goto retry;
-        }
-      }
-    } else {
-      vadd->set = 1;
-    }
-  }
-  return err;
-}
-
-/* ARP header length */
-static int vrrp_dlt_len( vrrp_rt *rt )
-{
-  return ETHER_HDR_LEN;  /* hardcoded for ethernet */
-}
-
-/* IP header length */
-static int vrrp_iphdr_len(vrrp_rt *vrrp)
-{
-  return sizeof(struct iphdr);
-}
-
-/* IPSEC AH header length */
-int vrrp_ipsecah_len(void)
-{
-  return sizeof(ipsec_ah);
-}
-
-/* VRRP header length */
-static int vrrp_hd_len(vrrp_rt *vrrp)
-{
-  return sizeof(vrrp_pkt)
-         + vrrp->naddr * sizeof(uint32_t)
-         + VRRP_AUTH_LEN;
-}
-
-/*
- * IPSEC AH incoming packet check.
- * return 0 for a valid pkt, != 0 otherwise.
- */
-static int vrrp_in_chk_ipsecah(vrrp_rt *vrrp, char *buffer)
-{
-  struct iphdr *ip = (struct iphdr*)(buffer);
-  ipsec_ah *ah = (ipsec_ah *)((char *)ip + (ip->ihl<<2));
-  unsigned char *digest;
-  uint32_t backup_auth_data[3];
-
-  /* first verify that the SPI value is equal to src IP */
-  if(ah->spi != ip->saddr) {
-    syslog(LOG_INFO, "IPSEC AH : invalid IPSEC SPI value. %d and expect %d"
-                   , ip->saddr, ah->spi);
-    return 1;
-  }
-
-  /*
-   * then proceed with the sequence number to prevent against replay attack.
-   * in inbound processing, we increment seq_number counter to audit 
-   * sender counter.
-   */
-  vrrp->ipsecah_counter->seq_number++;
-  if (ah->seq_number >= vrrp->ipsecah_counter->seq_number) {
-    vrrp->ipsecah_counter->seq_number = ah->seq_number;
-  } else {
-    syslog(LOG_INFO, "IPSEC AH : sequence number %d already proceeded."
-                     " Packet droped", ah->seq_number);
-    return 1;
-  }
-  /*
-   * then compute a ICV to compare with the one present in AH pkt.
-   * alloc a temp memory space to stock the ip mutable fields
-   */
-  digest = (unsigned char *)MALLOC(16*sizeof(unsigned char *));
-
-  /* zero the ip mutable fields */
-  ip->tos = 0;
-  ip->id = 0;
-  ip->frag_off = 0;
-  ip->check = 0;
-  memcpy(backup_auth_data, ah->auth_data, sizeof(ah->auth_data));
-  memset(ah->auth_data, 0, sizeof(ah->auth_data));
-
-  /* Compute the ICV */
-  hmac_md5(buffer, vrrp_iphdr_len(vrrp) + vrrp_ipsecah_len() + vrrp_hd_len(vrrp)
-                 , vrrp->auth_data
-                 , sizeof(vrrp->auth_data)
-                 , digest);
-
-  if (memcmp(backup_auth_data, digest, HMAC_MD5_TRUNC) != 0) {
-    syslog(LOG_INFO, "IPSEC AH : invalid IPSEC HMAC-MD5 value."
-                     " Due to fields mutation or bad password !");
-    return 1;
-  }
-
-  FREE(digest);
-  return 0;
-}
-
-/* check if ipaddr is present in VIP buffer */
-static int vrrp_in_chk_vips(vrrp_rt *vrrp, uint32_t ipaddr, unsigned char *buffer)
-{
-  int i;
-  uint32_t ipbuf;
-
-  for (i=0; i < vrrp->naddr; i++) {
-    bcopy(buffer+i*sizeof(uint32_t), &ipbuf, sizeof(uint32_t));
-    if (ipaddr == ntohl(ipbuf)) return 1;
-  }
-
-  return 0;
-}
-
-/*
- * VRRP incoming packet check.
- * return 0 if the pkt is valid, != 0 otherwise.
- */
-static int vrrp_in_chk(vrrp_rt *vrrp, char *buffer)
-{
-  struct iphdr *ip = (struct iphdr*)(buffer);
-  int ihl = ip->ihl << 2;
-  ipsec_ah *ah;
-  vrrp_pkt *hd;
-  unsigned char *vips;
-  int i;
-
-  if (vrrp->auth_type == VRRP_AUTH_AH) {
-    ah = (ipsec_ah *)(buffer + sizeof(struct iphdr));
-    hd = (vrrp_pkt *)(buffer + ihl + vrrp_ipsecah_len());
-  } else {
-    hd = (vrrp_pkt *)(buffer + ihl);
-  }
-
-  /* pointer to vrrp vips pkt zone */
-  vips = (unsigned char *)((char *)hd + sizeof(vrrp_pkt));
-
-  /* MUST verify that the IP TTL is 255 */
-  if( ip->ttl != VRRP_IP_TTL ) {
-    syslog(LOG_INFO, "invalid ttl. %d and expect %d"
-                   , ip->ttl, VRRP_IP_TTL);
-    return VRRP_PACKET_KO;
-  }
-
-  /* MUST verify the VRRP version */
-  if ((hd->vers_type >> 4) != VRRP_VERSION) {
-    syslog(LOG_INFO, "invalid version. %d and expect %d"
-                   , (hd->vers_type >> 4), VRRP_VERSION);
-    return VRRP_PACKET_KO;
-  }
-
-  /*
-   * MUST verify that the received packet length is greater than or
-   * equal to the VRRP header
-   */
-  if ((ntohs(ip->tot_len)-ihl) <= sizeof(vrrp_pkt)) {
-    syslog(LOG_INFO, "ip payload too short. %d and expect at least %d"
-                   , ntohs(ip->tot_len)-ihl, sizeof(vrrp_pkt));
-    return VRRP_PACKET_KO;
-  }
-
-  /* MUST verify the VRRP checksum */
-  if (in_csum( (u_short*)hd, vrrp_hd_len(vrrp), 0)) {
-    syslog(LOG_INFO, "Invalid vrrp checksum");
-    return VRRP_PACKET_KO;
-  }
-
-  /*
-   * MUST perform authentication specified by Auth Type 
-   * check the authentication type
-   */
-  if (vrrp->auth_type != hd->auth_type) {    
-    syslog(LOG_INFO, "receive a %d auth, expecting %d!", vrrp->auth_type
-                   , hd->auth_type);
-    return VRRP_PACKET_KO;
-  }
-
-  /* check the authentication if it is a passwd */
-  if (hd->auth_type == VRRP_AUTH_PASS) {
-    char *pw = (char *)ip + ntohs(ip->tot_len)
-                          - sizeof(vrrp->auth_data);
-    if (strncmp(pw, vrrp->auth_data, strlen(vrrp->auth_data)) != 0) {
-      syslog(LOG_INFO, "receive an invalid passwd!");
-      return VRRP_PACKET_KO;
-    }
-  }
-
-  /* MUST verify that the VRID is valid on the receiving interface */
-  if (vrrp->vrid != hd->vrid) {
-    syslog(LOG_INFO, "received VRID mismatch. Received %d, Expected %d"
-                   , hd->vrid
-                   , vrrp->vrid);
-    return VRRP_PACKET_DROP;
-  }
-
-  /*
-   * MAY verify that the IP address(es) associated with the
-   * VRID are valid
-   */
-  if (vrrp->naddr != hd->naddr) {
-    syslog(LOG_INFO, "receive an invalid ip number count associated with VRID!");
-    return VRRP_PACKET_KO;
-  }
-
-  for (i=0; i < vrrp->naddr; i++)
-    if (!vrrp_in_chk_vips(vrrp, vrrp->vaddr[i].addr,vips)) {
-      syslog(LOG_INFO, "ip address associated with VRID"
-                       " not present in received packet : %d"
-                     , vrrp->vaddr[i].addr);
-      syslog(LOG_INFO, "one or more VIP associated with"
-                       " VRID mismatch actual MASTER advert");
-      return VRRP_PACKET_KO;
-    }
-
-  /*
-   * MUST verify that the Adver Interval in the packet is the same as
-   * the locally configured for this virtual router
-   */
-  if (vrrp->adver_int/TIMER_HZ != hd->adver_int) {
-    syslog(LOG_INFO, "advertissement interval mismatch mine=%d rcved=%d"
-                   , vrrp->adver_int
-                   , hd->adver_int);
-    /* to prevent concurent VRID running => multiple master in 1 VRID */
-    return VRRP_PACKET_DROP;
-  }
-
-  /* check the authenicaion if it is ipsec ah */
-  if(hd->auth_type == VRRP_AUTH_AH)
-    return(vrrp_in_chk_ipsecah(vrrp, buffer));
-
-  return VRRP_PACKET_OK;
-}
-
-/* build ARP header */
-static void vrrp_build_arp(vrrp_rt *vrrp, char *buffer, int buflen)
-{
-  /* hardcoded for ethernet */
-  struct ether_header * eth = (struct ether_header *)buffer;
-
-  /* destination address --rfc1122.6.4*/
-  eth->ether_dhost[0] = 0x01;
-  eth->ether_dhost[1] = 0x00;
-  eth->ether_dhost[2] = 0x5E;
-  eth->ether_dhost[3] = (INADDR_VRRP_GROUP >> 16) & 0x7F;
-  eth->ether_dhost[4] = (INADDR_VRRP_GROUP >>  8) & 0xFF;
-  eth->ether_dhost[5] = INADDR_VRRP_GROUP & 0xFF;
-
-  /* source address -- rfc2338.7.3 */
-  memcpy(eth->ether_shost, vrrp->hwaddr, sizeof(vrrp->hwaddr));
-
-  /* type */
-  eth->ether_type = htons(ETHERTYPE_IP);
-}
-
-/* build IP header */
-static void vrrp_build_ip(vrrp_rt *vrrp, char *buffer, int buflen)
-{
-  struct iphdr *ip = (struct iphdr *)(buffer);
-
-  ip->ihl      = 5;
-  ip->version  = 4;
-  ip->tos      = 0;
-  ip->tot_len  = ip->ihl*4 + vrrp_hd_len(vrrp);
-  ip->tot_len  = htons(ip->tot_len);
-  ip->id       = ++vrrp->ip_id;
-  ip->frag_off = 0;
-  ip->ttl      = VRRP_IP_TTL;
-
-  /* fill protocol type --rfc2402.2 */
-  ip->protocol = (vrrp->auth_type == VRRP_AUTH_AH)?IPPROTO_IPSEC_AH:IPPROTO_VRRP;
-  ip->saddr    = VRRP_PKT_SADDR(vrrp);
-  ip->daddr    = htonl(INADDR_VRRP_GROUP);
-
-  /* checksum must be done last */
-  ip->check = in_csum((u_short*)ip, ip->ihl*4, 0);
-}
-
-/* build IPSEC AH header */
-static void vrrp_build_ipsecah(vrrp_rt *vrrp, char *buffer, int buflen)
-{
-  ICV_mutable_fields *ip_mutable_fields;
-  unsigned char *digest;
-  struct iphdr *ip = (struct iphdr *)(buffer);
-  ipsec_ah *ah = (ipsec_ah *)(buffer + sizeof(struct iphdr));
-
-  /* alloc a temp memory space to stock the ip mutable fields */
-  ip_mutable_fields = (ICV_mutable_fields *)MALLOC(sizeof(ICV_mutable_fields));
-
-  /* fill in next header filed --rfc2402.2.1 */
-  ah->next_header = IPPROTO_VRRP;
-
-  /* update IP header total length value */
-  ip->tot_len = ip->ihl*4 + vrrp_ipsecah_len() + vrrp_hd_len(vrrp);
-  ip->tot_len = htons(ip->tot_len);
-
-  /* update ip checksum */
-  ip->check = 0;
-  ip->check = in_csum((u_short*)ip, ip->ihl*4, 0);
-
-  /* backup the ip mutable fields */
-  ip_mutable_fields->tos      = ip->tos;
-  ip_mutable_fields->id       = ip->id;
-  ip_mutable_fields->frag_off = ip->frag_off;
-  ip_mutable_fields->check    = ip->check;
-
-  /* zero the ip mutable fields */
-  ip->tos      = 0;
-  ip->id       = 0;
-  ip->frag_off = 0;
-  ip->check    = 0;
-
-  /* fill in the Payload len field */
-  ah->payload_len = IPSEC_AH_PLEN;
-
-  /* The SPI value is filled with the ip header source address.
-     SPI uniquely identify the Security Association (SA). This value
-     is chosen by the recipient itself when setting up the SA. In a 
-     multicast environment, this becomes unfeasible.
-
-     If left to the sender, the choice of the SPI value should be done
-     so by the sender that it cannot possibly conflict with SPI values
-     chosen by other entities sending IPSEC traffic to any of the receivers.
-     To overpass this problem, the rule I have chosen to implement here is
-     that the SPI value chosen by the sender is based on unique information
-     such as its IP address.
-     -- INTERNET draft : <draft-paridaens-xcast-sec-framework-01.txt>
-  */
-  ah->spi = ip->saddr;
-
-  /* Processing sequence number.
-     Cycled assumed if 0xFFFFFFFD reached. So the MASTER state is free for another srv.
-     Here can result a flapping MASTER state owner when max seq_number value reached.
-     => Much work needed here.
-     In the current implementation if counter has cycled, we stop sending adverts and 
-     become BACKUP. If all the master are down we reset the counter for becoming MASTER.
-  */
-//  if (vrrp->ipsecah_counter->seq_number > 5) {
-  if (vrrp->ipsecah_counter->seq_number > 0xFFFFFFFD) {
-    vrrp->ipsecah_counter->cycle = 1;
-  } else {
-    vrrp->ipsecah_counter->seq_number++;
-  }
-
-  ah->seq_number = vrrp->ipsecah_counter->seq_number;
-
-  /* Compute the ICV & trunc the digest to 96bits
-     => No padding needed.
-     -- rfc2402.3.3.3.1.1.1 & rfc2401.5
-  */
-  digest = (unsigned char *)MALLOC(16*sizeof(unsigned char *));
-  hmac_md5(buffer, buflen
-                 , vrrp->auth_data
-                 , sizeof(vrrp->auth_data)
-                 , digest);
-  memcpy(ah->auth_data, digest, HMAC_MD5_TRUNC);
-
-  /* Restore the ip mutable fields */
-  ip->tos      = ip_mutable_fields->tos;
-  ip->id       = ip_mutable_fields->id;
-  ip->frag_off = ip_mutable_fields->frag_off;
-  ip->check    = ip_mutable_fields->check;
-
-  FREE(ip_mutable_fields);
-  FREE(digest);
-}
-
-/* build VRRP header */
-static int vrrp_build_vrrp(vrrp_rt *vrrp, int prio, char *buffer, int buflen)
-{
-  int  i;
-  vrrp_pkt *hd  = (vrrp_pkt *)buffer;
-  uint32_t *iparr  = (uint32_t *)((char *)hd+sizeof(*hd));
-  
-  hd->vers_type  = (VRRP_VERSION<<4) | VRRP_PKT_ADVERT;
-  hd->vrid       = vrrp->vrid;
-  hd->priority   = prio;
-  hd->naddr      = vrrp->naddr;
-  hd->auth_type  = vrrp->auth_type;
-  hd->adver_int  = vrrp->adver_int/TIMER_HZ;
-
-  /* copy the ip addresses */
-  for( i = 0; i < vrrp->naddr; i++ ){
-    iparr[i] = htonl(vrrp->vaddr[i].addr);
-  }
-
-  /* copy the passwd if the authentication is VRRP_AH_PASS */
-  if (vrrp->auth_type == VRRP_AUTH_PASS) {
-    char *pw = (char *)hd + sizeof(*hd) + vrrp->naddr*4;
-    memcpy(pw, vrrp->auth_data, sizeof(vrrp->auth_data));
-  }
-
-  /* finaly compute vrrp checksum */
-  hd->chksum  = in_csum( (u_short*)hd, vrrp_hd_len(vrrp), 0);
-
-  return(0);
-}
-
-/* build VRRP packet */
-static void vrrp_build_pkt(vrrp_rt *vrrp, int prio, char *buffer, int buflen)
-{
-  char *bufptr;
-
-  bufptr = buffer;
-
-  /* build the ethernet header */
-  vrrp_build_arp(vrrp, buffer, buflen);
-
-  /* build the ip header */
-  buffer += vrrp_dlt_len(vrrp);
-  buflen -= vrrp_dlt_len(vrrp);
-  vrrp_build_ip(vrrp, buffer, buflen);
-
-  /* build the vrrp header */
-  buffer += vrrp_iphdr_len(vrrp);
-
-  if (vrrp->auth_type == VRRP_AUTH_AH)
-    buffer += vrrp_ipsecah_len();
-  buflen -= vrrp_iphdr_len(vrrp);
-
-  if (vrrp->auth_type == VRRP_AUTH_AH)
-    buflen -= vrrp_ipsecah_len();
-  vrrp_build_vrrp(vrrp, prio, buffer, buflen);
-
-  /* build the IPSEC AH header */
-  if (vrrp->auth_type == VRRP_AUTH_AH) {
-    bufptr += vrrp_dlt_len(vrrp);
-    buflen += vrrp_ipsecah_len() + vrrp_iphdr_len(vrrp);;
-    vrrp_build_ipsecah(vrrp, bufptr, buflen);
-  }
-}
-
-/* send VRRP packet */
-static int vrrp_send_pkt(vrrp_rt *vrrp, char *buffer, int buflen)
-{
-  struct sockaddr from;
-  int len;
-  int fd = socket(PF_PACKET, SOCK_PACKET, 0x300); /* 0x300 is magic */
-
-  if( fd < 0 ){
-    syslog(LOG_INFO, "VRRP Error : socket creation");
-    return -1;
-  }
-
-  /* build the address */
-  memset(&from, 0 , sizeof(from));
-  strcpy(from.sa_data, IF_NAME(vrrp->ifp));
-
-//print_buffer(buflen, buffer);
-
-  /* send the data */
-  len = sendto(fd, buffer, buflen, 0, &from, sizeof(from));
-
-  close(fd);
-  return len;
-}
-
-/* send VRRP advertissement */
-int vrrp_send_adv(vrrp_rt *vrrp, int prio)
-{
-  int buflen, ret;
-  char *buffer;
-
-  /* alloc the memory */
-  buflen = vrrp_dlt_len(vrrp) + vrrp_iphdr_len(vrrp) + vrrp_hd_len(vrrp);
-  if (vrrp->auth_type == VRRP_AUTH_AH)
-    buflen += vrrp_ipsecah_len();
-
-  buffer = MALLOC(buflen);
-
-  /* build the packet  */
-  vrrp_build_pkt(vrrp, prio, buffer, buflen);
-
-  /* send it */
-  ret = vrrp_send_pkt(vrrp, buffer, buflen);
-
-  /* free the memory */
-  FREE(buffer);
-  return ret;
-}
-
-/* Received packet processing */
-int vrrp_check_packet(vrrp_rt *vrrp, char *buf, int buflen)
-{
-  int ret;
-
-  if (buflen > 0) {
-    ret = vrrp_in_chk(vrrp, buf);
-
-    if (ret == VRRP_PACKET_DROP) {
-      syslog(LOG_INFO, "Sync instance needed on %s !!!"
-                     , IF_NAME(vrrp->ifp));
-    }
-
-    if (ret == VRRP_PACKET_KO)
-      syslog(LOG_INFO, "bogus VRRP packet received on %s !!!"
-                     , IF_NAME(vrrp->ifp));
-    return ret;
-  }
-
-  return VRRP_PACKET_NULL;
-}
-
-/* send a gratuitous ARP packet */
-static int send_gratuitous_arp(vrrp_rt *vrrp, int addr)
-{
-  struct m_arphdr {
-    unsigned short int ar_hrd;          /* Format of hardware address.  */
-    unsigned short int ar_pro;          /* Format of protocol address.  */
-    unsigned char ar_hln;               /* Length of hardware address.  */
-    unsigned char ar_pln;               /* Length of protocol address.  */
-    unsigned short int ar_op;           /* ARP opcode (command).  */
-    /* Ethernet looks like this : This bit is variable sized however...  */
-    unsigned char __ar_sha[ETH_ALEN];   /* Sender hardware address.  */
-    unsigned char __ar_sip[4];          /* Sender IP address.  */
-    unsigned char __ar_tha[ETH_ALEN];   /* Target hardware address.  */
-    unsigned char __ar_tip[4];          /* Target IP address.  */
-  };
-
-  char buf[sizeof(struct m_arphdr) + ETHER_HDR_LEN];
-  char buflen = sizeof(struct m_arphdr) + ETHER_HDR_LEN;
-  struct ether_header *eth = (struct ether_header *)buf;
-  struct m_arphdr *arph = (struct m_arphdr *)(buf + vrrp_dlt_len(vrrp));
-  char  *hwaddr = IF_HWADDR(vrrp->ifp);
-  int  hwlen = ETH_ALEN;
-
-  /* hardcoded for ethernet */
-  memset(eth->ether_dhost, 0xFF, ETH_ALEN);
-  memcpy(eth->ether_shost, hwaddr, hwlen);
-  eth->ether_type = htons(ETHERTYPE_ARP);
-
-  /* build the arp payload */
-  memset(arph, 0, sizeof(*arph));
-  arph->ar_hrd = htons(ARPHRD_ETHER);
-  arph->ar_pro = htons(ETHERTYPE_IP);
-  arph->ar_hln = 6;
-  arph->ar_pln = 4;
-  arph->ar_op  = htons(ARPOP_REQUEST);
-  memcpy(arph->__ar_sha, hwaddr, hwlen);
-  memcpy(arph->__ar_sip, &addr, sizeof(addr));
-  memcpy(arph->__ar_tip, &addr, sizeof(addr));
-
-  return vrrp_send_pkt(vrrp, buf, buflen);
-}
-
-/* Gratuitous ARP on each VIP */
-void vrrp_send_gratuitous_arp(vrrp_rt *vrrp)
-{
-  int  i, j;
-
-  /* send gratuitous arp for each virtual ip */
-  syslog(LOG_INFO, "VRRP_Instance(%s) Sending gratuitous ARP on %s"
-                 , vrrp->iname
-                 , IF_NAME(vrrp->ifp));
-
-  for (j = 0; j < 5; j++) {
-    for (i = 0; i < vrrp->naddr; i++)
-      send_gratuitous_arp(vrrp, vrrp->vaddr[i].addr);
-    for (i = 0; i < vrrp->neaddr; i++)
-      send_gratuitous_arp(vrrp, vrrp->evaddr[i].addr);
-  }
-}
-
-/* becoming master */
-void vrrp_state_become_master(vrrp_rt *vrrp)
-{
-  /* add the ip addresses */
-  if (vrrp->naddr)
-    vrrp_handle_ipaddress(vrrp, VRRP_IPADDRESS_ADD, VRRP_VIP_TYPE);
-  if (vrrp->neaddr)
-    vrrp_handle_ipaddress(vrrp, VRRP_IPADDRESS_ADD, VRRP_EVIP_TYPE);
-  vrrp->vipset = 1;
-
-  /* remotes arp tables update */
-  vrrp_send_gratuitous_arp(vrrp);
-
-  /* Check if notify is needed */
-  notify_instance_exec(vrrp, VRRP_STATE_MAST);
-
-#ifdef _HAVE_IPVS_SYNCD_
-  /* Check if sync daemon handling is needed */
-  if (vrrp->lvs_syncd_if)
-    ipvs_syncd_master(vrrp->lvs_syncd_if);
-#endif
-}
-
-void vrrp_state_goto_master(vrrp_rt *vrrp)
-{
-  /*
-   * Send an advertisement. To force a new master
-   * election.
-   */
-  vrrp_send_adv(vrrp, vrrp->priority);
-
-  if (vrrp->wantstate == VRRP_STATE_MAST) {
-    vrrp->state = VRRP_STATE_MAST;
-    syslog(LOG_INFO, "VRRP_Instance(%s) Transition to MASTER STATE"
-                   , vrrp->iname);
-  } else {
-    vrrp->state = VRRP_STATE_DUMMY_MAST;
-    syslog(LOG_INFO, "VRRP_Instance(%s) Transition to DUMMY_MASTER STATE"
-                   , vrrp->iname);
-  }
-}
-
-/* leaving master state */
-static void vrrp_restore_interface(vrrp_rt *vrrp, int advF)
-{
-  /* remove the ip addresses */
-  if (VRRP_VIP_ISSET(vrrp)) {
-    if (vrrp->naddr)
-      vrrp_handle_ipaddress(vrrp, VRRP_IPADDRESS_DEL, VRRP_VIP_TYPE);
-    if (vrrp->neaddr)
-      vrrp_handle_ipaddress(vrrp, VRRP_IPADDRESS_DEL, VRRP_EVIP_TYPE);
-    vrrp->vipset = 0;
-  }
-
-  /* if we stop vrrp, warn the other routers to speed up the recovery */
-  if (advF)
-    vrrp_send_adv(vrrp, VRRP_PRIO_STOP);
-}
-
-void vrrp_state_leave_master(vrrp_rt *vrrp)
-{
-  if (VRRP_VIP_ISSET(vrrp)) {
-#ifdef _HAVE_IPVS_SYNCD_
-    /* Check if sync daemon handling is needed */
-    if (vrrp->lvs_syncd_if)
-      ipvs_syncd_backup(vrrp->lvs_syncd_if);
-#endif
-  }
-
-  /* set the new vrrp state */
-  switch (vrrp->wantstate) {
-    case VRRP_STATE_BACK:
-      syslog(LOG_INFO, "VRRP_Instance(%s) Entering BACKUP STATE"
-                     , vrrp->iname);
-      vrrp_restore_interface(vrrp, 0);
-      vrrp->state = vrrp->wantstate;
-      notify_instance_exec(vrrp, VRRP_STATE_BACK);
-      break;
-    case VRRP_STATE_GOTO_FAULT:
-      syslog(LOG_INFO, "VRRP_Instance(%s) Entering FAULT STATE"
-                     , vrrp->iname);
-      vrrp_restore_interface(vrrp, 0);
-      vrrp->state = VRRP_STATE_FAULT;
-      notify_instance_exec(vrrp, VRRP_STATE_FAULT);
-      break;
-  }
-}
-
-/* BACKUP state processing */
-void vrrp_state_backup(vrrp_rt *vrrp, char *buf, int buflen)
-{
-  struct iphdr *iph = (struct iphdr *)buf;
-  vrrp_pkt     *hd  = NULL;
-  int ret           = 0;
-
-  /* Fill the VRRP header */
-  switch (iph->protocol) {
-    case IPPROTO_IPSEC_AH:
-      hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2) + vrrp_ipsecah_len());
-      break;
-    case IPPROTO_VRRP:
-      hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2));
-      break;
-  }
-
-  /* Process the incoming packet */
-  ret = vrrp_check_packet(vrrp, buf, buflen);
-
-  if (ret == VRRP_PACKET_KO   || 
-      ret == VRRP_PACKET_NULL) {
-    syslog(LOG_INFO, "VRRP_Instance(%s) ignoring received advertisment..."
-                   , vrrp->iname);
-    vrrp->ms_down_timer = 3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
-  } else if (hd->priority == 0) {
-    vrrp->ms_down_timer = VRRP_TIMER_SKEW(vrrp);
-  } else if (!vrrp->preempt || hd->priority >= vrrp->priority) {
-    vrrp->ms_down_timer = 3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
-  } else if (hd->priority < vrrp->priority) {
-    vrrp->wantstate = VRRP_STATE_GOTO_MASTER;
-  }
-}
-
-/* MASTER state processing */
-void vrrp_state_master_tx(vrrp_rt *vrrp, const int prio)
-{
-  if (!VRRP_VIP_ISSET(vrrp)) {
-    syslog(LOG_INFO, "VRRP_Instance(%s) Entering MASTER STATE"
-                   , vrrp->iname);
-    vrrp_state_become_master(vrrp);
-  }
-
-  vrrp_send_adv(vrrp, (prio==VRRP_PRIO_OWNER)?VRRP_PRIO_OWNER:vrrp->priority);
-}
-
-int vrrp_state_master_rx(vrrp_rt *vrrp, char *buf, int buflen)
-{
-  int ret            = 0;
-  struct iphdr *iph  = (struct iphdr *)buf;
-  vrrp_pkt     *hd   = NULL; 
-
-  /* return on link failure */
-  if (vrrp->wantstate == VRRP_STATE_GOTO_FAULT) {
-    vrrp->ms_down_timer = 3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
-    vrrp->state = VRRP_STATE_FAULT;
-    return 1;
-  }
-
-  /* Fill the VRRP header */
-  switch (iph->protocol) {
-    case IPPROTO_IPSEC_AH:
-      hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2) + vrrp_ipsecah_len());
-      break;
-    case IPPROTO_VRRP:
-      hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2));
-      break;
-  }
-
-  /* Process the incoming packet */
-  ret = vrrp_check_packet(vrrp, buf, buflen);
-
-  if (ret == VRRP_PACKET_KO   ||
-      ret == VRRP_PACKET_NULL ||
-      ret == VRRP_PACKET_DROP) {
-    syslog(LOG_INFO, "VRRP_Instance(%s) Dropping received VRRP packet..."
-                   , vrrp->iname);
-    vrrp_send_adv(vrrp, vrrp->priority);
-    return 0;
-  } else if (hd->priority < vrrp->priority) {
-    /* We receive a lower prio adv we just refresh remote ARP cache */
-    syslog(LOG_INFO, "VRRP_Instance(%s) Received lower prio advert"
-                     ", forcing new election"
-                   , vrrp->iname);
-    vrrp_send_adv(vrrp, vrrp->priority);
-    vrrp_send_gratuitous_arp(vrrp);
-    return 0;
-  } else if (hd->priority == 0) {
-    vrrp_send_adv(vrrp, vrrp->priority);
-    return 0;
-  } else if (hd->priority > vrrp->priority   ||
-             (hd->priority == vrrp->priority &&
-             ntohl(iph->saddr) > VRRP_PKT_SADDR(vrrp))) {
-    syslog(LOG_INFO, "VRRP_Instance(%s) Received higher prio advert"
-                   , vrrp->iname);
-    vrrp->ms_down_timer = 3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
-    vrrp->state = VRRP_STATE_BACK;
-    return 1;
-  }
-
-  return 0;
-}
-
-int vrrp_state_fault_rx(vrrp_rt *vrrp, char *buf, int buflen)
-{
-  int ret            = 0;
-  struct iphdr *iph  = (struct iphdr *)buf;
-  vrrp_pkt     *hd   = NULL; 
-
-  /* Fill the VRRP header */
-  switch (iph->protocol) {
-    case IPPROTO_IPSEC_AH:
-      hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2) + vrrp_ipsecah_len());
-      break;
-    case IPPROTO_VRRP:
-      hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2));
-      break;
-  }
-
-  /* Process the incoming packet */
-  ret = vrrp_check_packet(vrrp, buf, buflen);
-
-  if (ret == VRRP_PACKET_KO   ||
-      ret == VRRP_PACKET_NULL ||
-      ret == VRRP_PACKET_DROP) {
-    syslog(LOG_INFO, "VRRP_Instance(%s) Dropping received VRRP packet..."
-                   , vrrp->iname);
-    vrrp_send_adv(vrrp, vrrp->priority);
-    return 0;
-  } else if (vrrp->priority > hd->priority ||
-             hd->priority == VRRP_PRIO_OWNER)
-    return 1;
-
-  return 0;
-}
-
-/* check for minimum configuration requirements */
-static int chk_min_cfg(vrrp_rt *vrrp)
-{
-  if (vrrp->naddr == 0) {
-    syslog(LOG_INFO, "provide at least one ip for the virtual server");
-    return 0;
-  }
-  if (vrrp->vrid == 0) {
-    syslog(LOG_INFO, "the virtual id must be set!");
-    return 0;
-  }
-  if (!vrrp->ifp) {
-    syslog(LOG_INFO, "Unknown interface for instance %s !"
-                   , vrrp->iname);
-    return 0;
-  }
-
-  return 1;
-}
-
-/* open the socket and join the multicast group. */
-int open_vrrp_socket(const int proto, const int index)
-{
-  struct ip_mreqn req_add;
-  interface *ifp;
-  int fd;
-  int ret;
-  int retry_num = 0;
-
-  /* Retreive interface */
-  ifp = if_get_by_ifindex(index);
-
-  if (!IF_ISUP(ifp)) {
-    syslog(LOG_INFO, "Kernel is reporting: Interface %s is DOWN"
-                   , IF_NAME(ifp));
-    return -1;
-  }
-
-  /* open the socket */
-  fd = socket(AF_INET, SOCK_RAW, proto);
-
-  if (fd < 0) {
-    int err = errno;
-    syslog(LOG_INFO, "cant open raw socket. errno=%d. (try to run it as root)"
-                   , err);
-    return -1;
-  }
-
-  /* -> inbound processing option
-   * Specify the bound_dev_if.
-   * why IP_ADD_MEMBERSHIP & IP_MULTICAST_IF doesnt set
-   * sk->bound_dev_if themself ??? !!!
-   * Needed for filter multicasted advert per interface.
-   * 
-   * -- If you read this !!! and know the answer to the question
-   *    please feel free to answer me ! :)
-   */
-  ret = setsockopt(fd, SOL_SOCKET
-                     , SO_BINDTODEVICE
-                     , IF_NAME(ifp)
-                     , strlen(IF_NAME(ifp))+1);
-  if (ret < 0) {
-    int  err = errno;
-    syslog(LOG_INFO, "cant bind to device %s. errno=%d. (try to run it as root)"
-                   , IF_NAME(ifp)
-                   , err);
-    close(fd);
-    return -1;
-  }
-
-  /* -> outbound processing option
-   * join the multicast group.
-   * binding the socket to the interface for outbound multicast
-   * traffic.
-   */
-  memset(&req_add, 0, sizeof (req_add));
-  req_add.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);
-  req_add.imr_address.s_addr   = IF_ADDR(ifp);
-  req_add.imr_ifindex          = IF_INDEX(ifp);
-
-  /* -> Need to handle multicast convergance after takeover.
-   * We retry until multicast is available on the interface.
-   * After VRRP_MCAST_RETRY we assume interface doesn't support
-   * multicast then exist with error.
-   * -> This can sound a little nasty since it degrade a little
-   * the global scheduling timers.
-   */
-moretry:
-  ret = setsockopt(fd, IPPROTO_IP
-                     , IP_ADD_MEMBERSHIP
-                     , (char *)&req_add
-                     , sizeof(struct ip_mreqn));
-  if (ret < 0) {
-    syslog(LOG_INFO, "cant do IP_ADD_MEMBERSHIP errno=%s (%d)"
-                   , strerror(errno)
-                   , errno);
-    if (errno == 19) {
-      retry_num++;
-      if (retry_num > VRRP_MCAST_RETRY) {
-        syslog(LOG_INFO, "cant do IP_ADD_MEMBERSHIP after %d retry errno=%s"
-                       , VRRP_MCAST_RETRY
-                       , strerror(errno));
-        return -1;
-      }
-      sleep(1); /* FIXME: Beurk... Very nasty... !!! */
-      goto moretry;
-    }
-    return -1;
-  }
-
-  return fd;
-}
-
-void close_vrrp_socket(vrrp_rt *vrrp)
-{
-  struct ip_mreqn req_add;
-  int ret = 0;
-
-  /* Leaving the VRRP multicast group */
-  memset(&req_add, 0, sizeof (req_add));
-  req_add.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);
-  req_add.imr_address.s_addr   = IF_ADDR(vrrp->ifp);
-  req_add.imr_ifindex          = IF_INDEX(vrrp->ifp);
-  ret = setsockopt(vrrp->fd, IPPROTO_IP
-                           , IP_DROP_MEMBERSHIP
-                           , (char *)&req_add
-                           , sizeof(struct ip_mreqn));
-  if (ret < 0) {
-    syslog(LOG_INFO, "cant do IP_DROP_MEMBERSHIP errno=%s (%d)"
-                   , strerror(errno)
-                   , errno);
-    return;
-  }
-
-  /* Finally close the desc */
-  close(vrrp->fd);
-}
-
-void new_vrrp_socket(vrrp_rt *vrrp)
-{
-  int old_fd = vrrp->fd;
-  list p = conf_data->vrrp;
-  vrrp_rt *vrrp_ptr;
-  element e;
-
-  /* close the desc & open a new one */
-  close_vrrp_socket(vrrp);
-  if (vrrp->auth_type == VRRP_AUTH_AH)
-    vrrp->fd = open_vrrp_socket(IPPROTO_IPSEC_AH, IF_INDEX(vrrp->ifp));
-  else
-    vrrp->fd = open_vrrp_socket(IPPROTO_VRRP, IF_INDEX(vrrp->ifp));
-
-  /* Sync the other desc */
-  for (e = LIST_HEAD(p); e; ELEMENT_NEXT(e)) {
-    vrrp_ptr = ELEMENT_DATA(e);
-    if (vrrp_ptr->fd == old_fd)
-      vrrp_ptr->fd = vrrp->fd;
-  }
-}
-
-/* handle terminate state */
-void shutdown_vrrp_instances(void)
-{
-  list l = conf_data->vrrp;
-  element e;
-  vrrp_rt *vrrp;
-
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-    vrrp = ELEMENT_DATA(e);
-
-    /* remove VIPs */
-    if (vrrp->state == VRRP_STATE_MAST ||
-        vrrp->state == VRRP_STATE_DUMMY_MAST)
-      vrrp_restore_interface(vrrp, 1);
-
-#ifdef _HAVE_IPVS_SYNCD_
-    /* Stop stalled syncd */
-    if (vrrp->lvs_syncd_if)
-      ipvs_syncd_cmd(IPVS_STOPDAEMON, NULL, 0);
-#endif
-  }
-}
-
-/* complete vrrp structure */
-static int vrrp_complete_instance(vrrp_rt *vrrp)
-{
-  /* complete the VMAC address */
-  vrrp->hwaddr[0] = 0x00;
-  vrrp->hwaddr[1] = 0x00;
-  vrrp->hwaddr[2] = 0x5E;
-  vrrp->hwaddr[3] = 0x00;
-  vrrp->hwaddr[4] = 0x01;
-  vrrp->hwaddr[5] = vrrp->vrid;
-
-  vrrp->state                           = VRRP_STATE_INIT;
-  if (!vrrp->adver_int) vrrp->adver_int = VRRP_ADVER_DFL * TIMER_HZ;
-  if (!vrrp->priority) vrrp->priority   = VRRP_PRIO_DFL;
-  if (!vrrp->preempt) vrrp->preempt     = VRRP_PREEMPT_DFL;
-
-  return(chk_min_cfg(vrrp));
-}
-
-int vrrp_complete_init(void)
-{
-  list l = conf_data->vrrp;
-  element e;
-  vrrp_rt *vrrp;
-
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-    vrrp = ELEMENT_DATA(e);
-    if (!vrrp_complete_instance(vrrp))
-      return 0;
-  }
-  return 1;
-}
diff --git a/vrrp_if.c b/vrrp_if.c
deleted file mode 100644 (file)
index b9181eb..0000000
--- a/vrrp_if.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Soft:        Keepalived is a failover program for the LVS project
- *              <www.linuxvirtualserver.org>. It monitor & manipulate
- *              a loadbalanced server pool using multi-layer checks.
- *
- * Part:        Interfaces manipulation.
- *
- * Version:     $Id: vrrp_if.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-/* global include */
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-  typedef __uint32_t u32;
-  typedef __uint16_t u16;
-  typedef __uint8_t  u8;
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <netinet/ip.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <syslog.h>
-#include <ctype.h>
-#ifdef use_linux_libc5
-  #include <linux/if_arp.h>
-  #include <linux/if_ether.h>
-#endif
-#include <stdlib.h>
-#include <stdio.h>
-#ifdef _KRNL_2_4_
-#include <linux/ethtool.h>
-#endif
-
-/* local include */
-#include "scheduler.h"
-#include "data.h"
-#include "vrrp_if.h"
-#include "vrrp_netlink.h"
-#include "memory.h"
-#include "utils.h"
-
-/* Global vars */
-extern thread_master *master;
-extern data *conf_data;
-static struct ifreq ifr;
-
-/* Helper functions */
-/* Return interface from interface index */
-interface *if_get_by_ifindex(const int ifindex)
-{
-  interface *ifp;
-  element e;
-
-  for (e = LIST_HEAD(if_queue); e; ELEMENT_NEXT(e)) {
-    ifp = ELEMENT_DATA(e);
-    if (ifp->ifindex == ifindex)
-      return ifp;
-  }
-  return NULL;
-}
-
-interface *if_get_by_ifname(const char *ifname)
-{
-  interface *ifp;
-  element e;
-
-  for (e = LIST_HEAD(if_queue); e; ELEMENT_NEXT(e)) {
-    ifp = ELEMENT_DATA(e);
-    if (!strcmp(ifp->ifname, ifname))
-      return ifp;
-  }
-  return NULL;
-}
-
-/* MII Transceiver Registers poller functions */
-static int if_mii_read(const int fd, const int phy_id, int location)
-{
-  uint16_t *data = (uint16_t *)(&ifr.ifr_data);
-
-  data[0] = phy_id;
-  data[1] = location;
-
-  if (ioctl(fd, SIOCGMIIREG, &ifr) < 0) {
-    syslog(LOG_ERR, "SIOCGMIIREG on %s failed: %s"
-                  , ifr.ifr_name
-                  , strerror(errno));
-    return -1;
-  }
-  return data[3];
-}
-
-/*
-static void if_mii_dump(const uint16_t mii_regs[32], unsigned phy_id)
-{
-  int mii_reg;
-
-  printf(" MII PHY #%d transceiver registers:\n", phy_id);
-  for (mii_reg = 0; mii_reg < 32; mii_reg++)
-    printf("%s %4.4x", (mii_reg % 8) == 0 ? "\n ":"", mii_regs[mii_reg]);
-}
-*/
-
-static int if_mii_status(const int fd)
-{
-  uint16_t *data = (uint16_t *)(&ifr.ifr_data);
-  unsigned phy_id = data[0];
-  uint16_t mii_regs[32];
-  int mii_reg;
-  uint16_t bmsr, new_bmsr;
-
-  /* Reset MII registers */
-  memset(mii_regs, 0, sizeof(mii_regs));
-
-  for (mii_reg = 0; mii_reg < 32; mii_reg++)
-    mii_regs[mii_reg] = if_mii_read(fd, phy_id, mii_reg);
-
-// if_mii_dump(mii_regs, phy_id);
-
-  if (mii_regs[0] == 0xffff) {
-    syslog(LOG_ERR, "No MII transceiver present for %s !!!"
-                  , ifr.ifr_name);
-    return -1;
-  }
-
-  bmsr = mii_regs[1];
-
-  /*
-   * For Basic Mode Status Register (BMSR).
-   * Sticky field (Link established & Jabber detected), we need to read
-   * a second time the BMSR to get current status.
-   */
-  new_bmsr = if_mii_read(fd, phy_id, 1);
-
-// printf(" \nBasic Mode Status Register 0x%4.4x ... 0x%4.4x\n", bmsr, new_bmsr);
-
-  if (bmsr & 0x0004)
-    return LINK_UP;
-  else if (new_bmsr & 0x0004)
-    return LINK_UP;
-  else
-    return LINK_DOWN;
-}
-
-int if_mii_probe(const char *ifname)
-{
-  int fd = socket(AF_INET, SOCK_DGRAM, 0);
-  int status = 0;
-
-  if (fd < 0) return -1;
-  memset(&ifr, 0, sizeof(struct ifreq));
-  strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-  if (ioctl(fd, SIOCGMIIPHY, &ifr) < 0) {
-    close(fd);
-    return -1;
-  }
-
-  /* Dump the MII transceiver */
-  status = if_mii_status(fd);
-  close(fd);
-  return status;
-}
-
-static int if_ethtool_status(const int fd)
-{
-#ifdef _KRNL_2_4_
-  struct ethtool_value edata;
-  int err = 0;
-
-  edata.cmd = ETHTOOL_GLINK;
-  ifr.ifr_data = (caddr_t)&edata;
-  err = ioctl(fd, SIOCETHTOOL, &ifr);
-  if (err == 0)
-    return (edata.data)?1:0;
-  else
-#endif
-    return -1;
-}
-
-int if_ethtool_probe(const char *ifname)
-{
-  int fd = socket(AF_INET, SOCK_DGRAM, 0);
-  int status = 0;
-
-  if (fd < 0) return -1;
-  memset(&ifr, 0, sizeof(struct ifreq));
-  strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-
-  status = if_ethtool_status(fd);
-  close(fd);
-  return status;
-}
-
-void if_ioctl_flags(interface *ifp)
-{
-  int fd = socket(AF_INET, SOCK_DGRAM, 0);
-
-  if (fd < 0) return;
-  memset(&ifr, 0, sizeof(struct ifreq));
-  strncpy(ifr.ifr_name, ifp->ifname, sizeof(ifr.ifr_name));
-  if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
-    close (fd);
-    return;
-  }
-  ifp->flags = ifr.ifr_flags;
-  close(fd);
-}
-
-/* Interfaces lookup */
-static void free_if(void *data)
-{
-  FREE(data);
-}
-void dump_if(void *data)
-{
-  interface *ifp = data;
-
-  syslog(LOG_INFO, "------< NIC >------");
-  syslog(LOG_INFO, " Name = %s", ifp->ifname);
-  syslog(LOG_INFO, " index = %d", ifp->ifindex);
-  syslog(LOG_INFO, " address = %s", inet_ntop2(ifp->address));
-
-  /* FIXME: Harcoded for ethernet */
-  if (ifp->hw_type == ARPHRD_ETHER)
-    syslog(LOG_INFO, " MAC = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x"
-                   , ifp->hw_addr[0], ifp->hw_addr[1], ifp->hw_addr[2]
-                   , ifp->hw_addr[3], ifp->hw_addr[4], ifp->hw_addr[5]);
-
-  if (ifp->flags & IFF_UP)
-    syslog(LOG_INFO, " is UP");
-
-  if (ifp->flags & IFF_RUNNING)
-    syslog(LOG_INFO, " is RUNNING");
-
-  if (!(ifp->flags & IFF_UP) && !(ifp->flags & IFF_RUNNING))
-    syslog(LOG_INFO, " is DOWN");
-
-  syslog(LOG_INFO, " MTU = %d", ifp->mtu);
-
-  switch (ifp->hw_type) {
-    case ARPHRD_LOOPBACK:
-      syslog(LOG_INFO, " HW Type = LOOPBACK");
-      break;
-    case ARPHRD_ETHER:
-      syslog(LOG_INFO, " HW Type = ETHERNET");
-      break;
-    default:
-      syslog(LOG_INFO, " HW Type = UNKNOWN");
-      break;
-  }
-
-  /* MII channel supported ? */
-  if (IF_MII_SUPPORTED(ifp))
-    syslog(LOG_INFO, " NIC support MII regs");
-  else if (IF_ETHTOOL_SUPPORTED(ifp))
-    syslog(LOG_INFO, " NIC support EHTTOOL GLINK interface");
-  else
-    syslog(LOG_INFO, " Enabling NIC ioctl refresh polling");
-}
-
-static void init_if_queue(void)
-{
-  if_queue = alloc_list(free_if, dump_if);
-}
-void if_add_queue(interface *ifp)
-{
-  list_add(if_queue, ifp);
-}
-
-static void init_if_mii(void)
-{
-  interface *ifp;
-  element e;
-  int status;
-
-  for (e = LIST_HEAD(if_queue); e; ELEMENT_NEXT(e)) {
-    ifp = ELEMENT_DATA(e);
-    ifp->lb_type = LB_IOCTL;
-    status = if_mii_probe(ifp->ifname);
-    if (status >= 0) {
-      ifp->lb_type = LB_MII;
-      ifp->linkbeat = (status)?1:0;
-    } else {
-      status = if_ethtool_probe(ifp->ifname);
-      if (status >= 0) {
-        ifp->lb_type = LB_ETHTOOL;
-        ifp->linkbeat = (status)?1:0;
-      }
-    }
-  }
-}
-
-static void if_linkbeat_refresh(void)
-{
-  interface *ifp;
-  element e;
-
-  for (e = LIST_HEAD(if_queue); e; ELEMENT_NEXT(e)) {
-    ifp = ELEMENT_DATA(e);
-    if (IF_MII_SUPPORTED(ifp))
-      ifp->linkbeat = (if_mii_probe(ifp->ifname))?1:0;
-    else if (IF_ETHTOOL_SUPPORTED(ifp))
-      ifp->linkbeat = (if_ethtool_probe(ifp->ifname))?1:0;
-    else
-      if_ioctl_flags(ifp);
-  }
-}
-
-int if_linkbeat(const interface *ifp)
-{
-  if (IF_MII_SUPPORTED(ifp) || IF_ETHTOOL_SUPPORTED(ifp))
-    return IF_LINKBEAT(ifp);
-  return 1;
-}
-
-/* Our interface Heartbeat thread */
-int if_monitor_thread(thread *thread)
-{
-  /* If present, refresh link beat status from MII BMSR */
-  if_linkbeat_refresh();
-
-  /* Register new monitor thread */
-  thread_add_timer(master, if_monitor_thread
-                         , NULL
-                         , POLLING_DELAY);
-  return 0;
-}
-
-/* Interface queue helpers*/
-void free_interface_queue(void)
-{
-  if (!LIST_ISEMPTY(if_queue))
-    free_list(if_queue);
-  netlink_close(&nl_kernel);
-}
-void init_interface_queue(void)
-{
-  init_if_queue();
-  netlink_interface_lookup();
-  init_if_mii();
-}
-void if_mii_poller_init(void)
-{
-//  dump_list(if_queue);
-
-  /* Register NIC Heartbeat monitoring thread */
-  thread_add_timer(master, if_monitor_thread
-                         , NULL
-                         , POLLING_DELAY);
-}
diff --git a/vrrp_ipsecah.c b/vrrp_ipsecah.c
deleted file mode 100644 (file)
index e1d92c4..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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:        IPSEC AH implementation according to RFC 2402. Processing
- *              authentication data encryption using HMAC MD5 according to
- *              RFCs 2085 & 2104.
- *
- * Version:     $Id: vrrp_ipsecah.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "vrrp_ipsecah.h"
-#include <openssl/md5.h>
-
-/* hmac_md5 computation according to the RFCs 2085 & 2104 */
-void hmac_md5(unsigned char *buffer, int buffer_len
-                                   , unsigned char *key
-                                   , int key_len
-                                   , unsigned char *digest)
-{
-  MD5_CTX context;
-  unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */
-  unsigned char k_opad[65]; /* outer padding - key XORd with opad */
-  unsigned char tk[16];
-  int i;
-
-  /* Initialize data */
-  memset(k_ipad,0,sizeof(k_ipad));
-  memset(k_opad,0,sizeof(k_opad));
-  memset(tk,0,sizeof(tk));
-
-  /* If the key is longer than 64 bytes => set it to key=MD5(key) */
-  if (key_len > 64) {
-    MD5_CTX tctx;
-
-    /* Compute the MD5 digest */
-    MD5_Init(&tctx);
-    MD5_Update(&tctx,key,key_len);
-    MD5_Final(tk,&tctx);
-
-    key = tk;
-    key_len = 16;
-  }
-
-  /* The global HMAC_MD5 algo looks like (rfc2085.2.2) :
-     MD5(K XOR opad, MD5(K XOR ipad, buffer))
-     K : an n byte key
-     ipad : byte 0x36 repeated 64 times
-     opad : byte 0x5c repeated 64 times
-     buffer : buffer being protected
-   */
-  memset(k_ipad,0,sizeof(k_ipad));
-  memset(k_opad,0,sizeof(k_opad));
-  memcpy(k_ipad,key,key_len);
-  memcpy(k_opad,key,key_len);
-
-  /* XOR key with ipad and opad values */
-  for (i=0;i<64;i++) {
-    k_ipad[i] ^=0x36;
-    k_opad[i] ^=0x5c;
-  }
-
-  /* Compute inner MD5 */
-  MD5_Init(&context);                     /* Init context for 1st pass */
-  MD5_Update(&context,k_ipad,64);         /* start with inner pad */
-  MD5_Update(&context,buffer,buffer_len); /* next with buffer datagram */
-  MD5_Final(digest,&context);             /* Finish 1st pass */
-
-  /* Compute outer MD5 */
-  MD5_Init(&context);                     /* Init context for 2nd pass */
-  MD5_Update(&context,k_opad,64);         /* start with inner pad */
-  MD5_Update(&context,digest,16);         /* next result of 1st pass */
-  MD5_Final(digest,&context);             /* Finish 2nd pass */
-}
diff --git a/vrrp_netlink.c b/vrrp_netlink.c
deleted file mode 100644 (file)
index 3194fa1..0000000
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * 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:        NETLINK kernel command channel.
- *
- * Version:     $Id: vrrp_netlink.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-/* global include */
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <fcntl.h>
-#include <net/if_arp.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <sys/uio.h>
-
-/* local include */
-#include "check_api.h"
-#include "vrrp_netlink.h"
-#include "vrrp_if.h"
-#include "memory.h"
-#include "scheduler.h"
-#include "utils.h"
-
-/* Global vars */
-extern thread_master *master;
-
-/* Create a socket to netlink interface */
-int netlink_socket(struct nl_handle *nl, unsigned long groups)
-{
-  int addr_len;
-  int ret;
-
-  memset(nl, 0, sizeof(nl));
-
-  nl->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-  if (nl->fd < 0) {
-    syslog(LOG_INFO, "Netlink: Cannot open netlink socket : (%s)"
-                   , strerror(errno));
-    return -1;
-  }
-
-  ret = fcntl(nl->fd, F_SETFL, O_NONBLOCK);
-  if (ret < 0) {
-    syslog(LOG_INFO, "Netlink: Cannot set netlink socket flags : (%s)"
-                   , strerror(errno));
-    close(nl->fd);
-    return -1;
-  }
-
-  memset(&nl->snl, 0, sizeof(nl->snl));
-  nl->snl.nl_family = AF_NETLINK;
-  nl->snl.nl_groups = groups;
-
-  ret = bind(nl->fd, (struct sockaddr*)&nl->snl, sizeof(nl->snl));
-  if (ret < 0) {
-    syslog(LOG_INFO, "Netlink: Cannot bind netlink socket : (%s)"
-                   , strerror(errno));
-    close(nl->fd);
-    return -1;
-  }
-
-  addr_len = sizeof(nl->snl);
-  ret = getsockname(nl->fd, (struct sockaddr *)&nl->snl, &addr_len);
-  if (ret < 0 || addr_len != sizeof(nl->snl)) {
-    syslog(LOG_INFO, "Netlink: Cannot getsockname : (%s)"
-                   , strerror(errno));
-    close(nl->fd);
-    return -1;
-  }
-
-  if (nl->snl.nl_family != AF_NETLINK) {
-    syslog(LOG_INFO, "Netlink: Wrong address family %d", nl->snl.nl_family);
-    close(nl->fd);
-    return -1;
-  }
-
-  nl->seq = time(NULL);
-
-  return ret;
-}
-
-/* Close a netlink socket */
-int netlink_close(struct nl_handle *nl)
-{
-  close(nl->fd);
-  return 0;
-}
-
-/* iproute2 utility function */
-int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
-{
-  int len = RTA_LENGTH(alen);
-  struct rtattr *rta;
-
-  if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
-    return -1;
-
-  rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));
-  rta->rta_type = type;
-  rta->rta_len = len;
-  memcpy(RTA_DATA(rta), data, alen);
-  n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
-
-  return 0;
-}
-
-static void parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len)
-{
-  while (RTA_OK(rta, len)) {
-    if (rta->rta_type <= max)
-      tb[rta->rta_type] = rta;
-    rta = RTA_NEXT(rta, len);
-  }
-}
-
-/* Our netlink parser */
-static int netlink_parse_info(int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
-                              struct nl_handle *nl)
-{
-  int status;
-  int ret = 0;
-  int error;
-
-  while (1) {
-    char buf[4096];
-    struct iovec iov = { buf, sizeof buf };
-    struct sockaddr_nl snl;
-    struct msghdr msg = {(void*)&snl, sizeof snl, &iov, 1, NULL, 0, 0};
-    struct nlmsghdr *h;
-
-    status = recvmsg (nl->fd, &msg, 0);
-
-    if (status < 0) {
-      if (errno == EINTR)
-        continue;
-      if (errno == EWOULDBLOCK)
-        break;
-      syslog(LOG_INFO, "Netlink: Received message overrun");
-      continue;
-    }
-
-    if (status == 0) {
-      syslog(LOG_INFO, "Netlink: EOF");
-      return -1;
-    }
-
-    if (msg.msg_namelen != sizeof snl) {
-      syslog(LOG_INFO, "Netlink: Sender address length error: length %d"
-                     , msg.msg_namelen);
-      return -1;
-    }
-
-    for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, status);
-         h = NLMSG_NEXT (h, status)) {
-      /* Finish of reading. */
-      if (h->nlmsg_type == NLMSG_DONE)
-        return ret;
-
-      /* Error handling. */
-      if (h->nlmsg_type == NLMSG_ERROR) {
-        struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
-        if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr))) {
-          syslog(LOG_INFO, "Netlink: error: message truncated");
-          return -1;
-        }
-        syslog (LOG_INFO, "Netlink: error: %s, type=(%u), seq=%u, pid=%d"
-                        , strerror (-err->error)
-                        , err->msg.nlmsg_type, err->msg.nlmsg_seq
-                        , err->msg.nlmsg_pid);
-
-        return -1;
-      }
-
-      error = (*filter) (&snl, h);
-      if (error < 0) {
-        syslog(LOG_INFO, "Netlink: filter function error");
-        ret = error;
-      }
-    }
-
-    /* After error care. */
-    if (msg.msg_flags & MSG_TRUNC) {
-      syslog(LOG_INFO, "Netlink: error: message truncated");
-      continue;
-    }
-    if (status) {
-      syslog(LOG_INFO, "Netlink: error: data remnant size %d", status);
-      return -1;
-    }
-  }
-
-  return ret;
-}
-
-/* Out talk filter */
-static int netlink_talk_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
-{
-  syslog(LOG_INFO, "Netlink: ignoring message type 0x%04x"
-                 , h->nlmsg_type);
-  return 0;
-}
-
-/* send message to netlink kernel socket, then receive response */
-int netlink_talk(struct nl_handle *nl, struct nlmsghdr *n)
-{
-  int status;
-  struct sockaddr_nl snl;
-  struct iovec iov = { (void*) n, n->nlmsg_len };
-  struct msghdr msg = {(void*) &snl, sizeof snl, &iov, 1, NULL, 0, 0};
-
-  memset(&snl, 0, sizeof snl);
-  snl.nl_family = AF_NETLINK;
-
-  n->nlmsg_seq = ++nl->seq;
-
-  /* Send message to netlink interface. */
-  status = sendmsg(nl->fd, &msg, 0);
-  if (status < 0) {
-    syslog(LOG_INFO, "Netlink: sendmsg() error: %s"
-                   , strerror (errno));
-    return -1;
-  }
-
-  status = netlink_parse_info(netlink_talk_filter, nl);
-  return status;
-}
-
-/* Fetch a specific type information from netlink kernel */
-static int netlink_request(struct nl_handle *nl, int family, int type)
-{
-  int status;
-  struct sockaddr_nl snl;
-  struct {
-    struct nlmsghdr nlh;
-    struct rtgenmsg g;
-  } req;
-
-  /* Cleanup the room */
-  memset(&snl, 0, sizeof(snl));
-  snl.nl_family = AF_NETLINK;
-
-  req.nlh.nlmsg_len = sizeof(req);
-  req.nlh.nlmsg_type = type;
-  req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
-  req.nlh.nlmsg_pid = 0;
-  req.nlh.nlmsg_seq = ++nl->seq;
-  req.g.rtgen_family = family;
-
-  status = sendto(nl->fd, (void *) &req
-                        , sizeof(req)
-                        , 0
-                        , (struct sockaddr *) &snl
-                        , sizeof(snl));
-  if (status < 0) {
-    syslog(LOG_INFO, "Netlink: sendto() failed: %s"
-                   , strerror(errno));
-    return -1;
-  }
-  return 0;
-}
-
-/* Netlink interface link lookup filter */
-static int netlink_if_link_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
-{
-  struct ifinfomsg *ifi;
-  struct rtattr *tb[IFLA_MAX + 1];
-  interface *ifp;
-  int i, len;
-  char *name;
-
-  ifi = NLMSG_DATA(h);
-
-  if (h->nlmsg_type != RTM_NEWLINK)
-    return 0;
-
-  len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
-  if (len < 0)
-    return -1;
-
-  /* Interface name lookup */
-  memset(tb, 0, sizeof(tb));
-  parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
-  if (tb[IFLA_IFNAME] == NULL)
-    return -1;
-  name = (char *)RTA_DATA(tb[IFLA_IFNAME]);
-
-  /* Return if loopback */
-  if (ifi->ifi_type == ARPHRD_LOOPBACK)
-    return 0;
-
-  /* Fill the interface structure */
-  ifp = (interface *)MALLOC(sizeof(interface));
-  memcpy(ifp->ifname, name, strlen(name));
-  ifp->ifindex = ifi->ifi_index;
-  ifp->flags = ifi->ifi_flags;
-  ifp->mtu = *(int *)RTA_DATA(tb[IFLA_MTU]);
-  ifp->hw_type = ifi->ifi_type;
-
-  if (tb[IFLA_ADDRESS]) {
-    int hw_addr_len = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
-
-    if (hw_addr_len > IF_HWADDR_MAX)
-      syslog(LOG_ERR, "MAC address for %s is too large: %d"
-                    , name
-                    , hw_addr_len);
-    else {
-      ifp->hw_addr_len = hw_addr_len;
-      memcpy(ifp->hw_addr, RTA_DATA(tb[IFLA_ADDRESS]), hw_addr_len);
-      for (i = 0; i < hw_addr_len; i++)
-        if (ifp->hw_addr[i] != 0)
-          break;
-      if (i == hw_addr_len)
-        ifp->hw_addr_len = 0;
-      else
-        ifp->hw_addr_len = hw_addr_len;
-    }
-  }
-
-  /* Queue this new interface */
-  if_add_queue(ifp);
-  return 0;
-}
-
-/*
- * Netlink interface address lookup filter
- * We need to handle multiple primary address and
- * multiple secondary address to the same interface.
- */
-static int netlink_if_address_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
-{
-  struct ifaddrmsg *ifa;
-  struct rtattr *tb[IFA_MAX + 1];
-  interface *ifp;
-  uint32_t address = 0;
-  int len;
-
-  ifa = NLMSG_DATA(h);
-
-  /* Only IPV4 are valid us */
-  if (ifa->ifa_family != AF_INET)
-    return 0;
-
-  if (h->nlmsg_type != RTM_NEWADDR &&
-      h->nlmsg_type != RTM_DELADDR)
-    return 0;
-
-  len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
-  if (len < 0)
-    return -1;
-
-  memset(tb, 0, sizeof(tb));
-  parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), len);
-
-  /* Fetch interface */
-  ifp = if_get_by_ifindex(ifa->ifa_index);
-  if (!ifp)
-    return 0;
-
-  if (tb[IFA_ADDRESS] == NULL)
-    tb[IFA_ADDRESS] = tb[IFA_LOCAL];
-
-  if (ifp->flags & IFF_POINTOPOINT) {
-    if (tb[IFA_LOCAL])
-      address = *(uint32_t *)RTA_DATA(tb[IFA_LOCAL]);
-  } else {
-    if (tb[IFA_ADDRESS])
-      address = *(uint32_t *)RTA_DATA(tb[IFA_ADDRESS]);
-  }
-
-  /* If no address is set on interface then set the first time */
-  if (!ifp->address)
-    ifp->address = address;
-
-#ifdef _WITH_LVS_
-  /* Refresh checkers state */
-  update_checker_activity(address, (h->nlmsg_type == RTM_NEWADDR)?1:0);
-#endif
-
-  return 0;
-}
-
-/* Interfaces lookup bootstrap function */
-int netlink_interface_lookup(void)
-{
-  struct nl_handle nlh;
-  int status = 0;
-
-  if (netlink_socket(&nlh, 0) < 0)
-    return -1;
-
-  /* Interface lookup */
-  if (netlink_request(&nlh, AF_PACKET, RTM_GETLINK) < 0) {
-    status = -1;
-    goto end_int;
-  }
-  status = netlink_parse_info(netlink_if_link_filter, &nlh); 
-
-end_int:
-  netlink_close(&nlh);
-  return status;
-}
-
-/* Adresses lookup bootstrap function */
-static int netlink_address_lookup(void)
-{
-  struct nl_handle nlh;
-  int status = 0;
-
-  if (netlink_socket(&nlh, 0) < 0)
-    return -1;
-
-  /* Address lookup */
-  if (netlink_request(&nlh, AF_INET, RTM_GETADDR) < 0) {
-    status = -1;
-    goto end_addr;
-  }
-  status = netlink_parse_info(netlink_if_address_filter, &nlh); 
-
-end_addr:
-  netlink_close(&nlh);
-  return status;
-}
-
-/* Netlink flag Link update */
-static int netlink_reflect_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
-{
-  struct ifinfomsg *ifi;
-  struct rtattr *tb[IFLA_MAX + 1];
-  interface *ifp;
-  int len;
-
-  ifi = NLMSG_DATA(h);
-  if ( !(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
-    return 0;
-
-  len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifinfomsg));
-  if (len < 0)
-    return -1;
-
-  /* Interface name lookup */
-  memset(tb, 0, sizeof(tb));
-  parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
-  if (tb[IFLA_IFNAME] == NULL)
-    return -1;
-
-  /* ignore loopback device */
-  if (ifi->ifi_type == ARPHRD_LOOPBACK)
-    return 0;
-
-  /* find the interface */
-  ifp = if_get_by_ifindex(ifi->ifi_index);
-  if (!ifp)
-    return -1;
-
-  /* Update flags */
-  ifp->flags = ifi->ifi_flags;
-
-  return 0;
-}
-
-/* Netlink kernel message reflection */
-static int netlink_broadcast_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
-{
-  switch (h->nlmsg_type) {
-    case RTM_NEWLINK:
-    case RTM_DELLINK:
-      return netlink_reflect_filter(snl, h);
-      break;
-    case RTM_NEWADDR:
-    case RTM_DELADDR:
-      return netlink_if_address_filter(snl, h);
-      break;
-    default:
-      syslog(LOG_INFO, "Kernel is reflecting an unknown netlink nlmsg_type: %d"
-                     , h->nlmsg_type);
-      break;
-  }
-  return 0;
-}
-
-int kernel_netlink(thread *thread)
-{
-  int status = 0;
-
-  if (thread->type != THREAD_READ_TIMEOUT)
-    status = netlink_parse_info(netlink_broadcast_filter, &nl_kernel);
-  thread_add_read(master, kernel_netlink
-                        , NULL
-                        , nl_kernel.fd
-                        , NETLINK_TIMER);
-  return 0;
-}
-
-void kernel_netlink_init(void)
-{
-  unsigned long groups;
-
-  /* Start with a netlink address lookup */
-  netlink_address_lookup();
-
-  /*
-   * Prepare netlink kernel broadcast channel
-   * subscribtion. We subscribe to LINK and ADDR
-   * netlink broadcast messages.
-   */
-  groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
-  netlink_socket(&nl_kernel, groups);
-
-  if (nl_kernel.fd > 0) {
-    syslog(LOG_INFO, "Registering Kernel netlink reflector");
-    thread_add_read(master, kernel_netlink
-                          , NULL
-                          , nl_kernel.fd
-                          , NETLINK_TIMER);
-  }
-}
diff --git a/vrrp_notify.c b/vrrp_notify.c
deleted file mode 100644 (file)
index 058bdd4..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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 state transition notification scripts handling.
- *
- * Version:     $Id: vrrp_notify.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-/* system include */
-#include <ctype.h>
-
-/* local include */
-#include "vrrp_notify.h"
-#include "memory.h"
-
-/* Close all FDs >= a specified value */
-void closeall(int fd)
-{
-  int fdlimit = sysconf(_SC_OPEN_MAX);
-  while (fd < fdlimit)
-    close(fd++);
-}
-
-static char *get_iscript(vrrp_rt *vrrp, int state)
-{
-  if (!vrrp->notify_exec)
-    return NULL;
-  if (state == VRRP_STATE_BACK)
-    return vrrp->script_backup;
-  if (state == VRRP_STATE_MAST)
-    return vrrp->script_master;
-  if (state == VRRP_STATE_FAULT)
-    return vrrp->script_fault;
-  return NULL;
-}
-
-static char *get_gscript(vrrp_sgroup *vgroup, int state)
-{
-  if (!vgroup->notify_exec)
-    return NULL;
-  if (state == VRRP_STATE_BACK)
-    return vgroup->script_backup;
-  if (state == VRRP_STATE_MAST)
-    return vgroup->script_master;
-  if (state == VRRP_STATE_FAULT)
-    return vgroup->script_fault;
-  return NULL;
-}
-
-static char *notify_script_name(char *cmdline)
-{
-  char *cp = cmdline;
-  char *script;
-  int strlen;
-
-  if (!cmdline)
-    return NULL;
-  while (!isspace((int) *cp) && *cp != '\0')
-    cp++;
-  strlen = cp - cmdline;
-  script = MALLOC(strlen + 1);
-  memcpy(script, cmdline, strlen);
-  *(script + strlen) = '\0';
-
-  return script;
-}
-
-/* Execute extern script/program */
-static int notify_exec(const char *cmd)
-{
-  int err;
-  pid_t pid;
-
-  pid = fork();
-
-  /* In case of fork is error. */
-  if (pid < 0) {
-    syslog(LOG_INFO, "Failed fork process");
-    return -1;
-  }
-
-  /* In case of this is parent process. */
-  if (pid)
-    return (0);
-
-  closeall(0);
-
-  open("/dev/null", O_RDWR);
-  dup(0);
-  dup(0);
-
-  err = system(cmd);
-  if (err != 0) {
-    if (err == 127)
-      syslog(LOG_ALERT, "Failed to exec [%s]", cmd);
-    else
-      syslog(LOG_ALERT, "Error running [%s], error: %d", cmd, err);
-  } else
-    syslog(LOG_INFO, "Success executing [%s]", cmd);
-
-  exit(0);
-}
-
-static int script_open(char *script)
-{
-  char *script_name = notify_script_name(script);
-  FILE *fOut;
-
-  fOut = fopen(script_name, "r");;
-  if (!fOut) {
-    syslog(LOG_INFO, "Can't open %s (errno %d %s)"
-                   , script_name
-                   , errno
-                   , strerror(errno));
-    return 0;
-  }
-  FREE(script_name);
-  fclose(fOut);
-  return 1;
-}
-
-int notify_instance_exec(vrrp_rt *vrrp, int state)
-{
-  char *script = get_iscript(vrrp, state);
-
-  if (!script || !script_open(script)) return 0;
-
-  /* Launch the script */
-  notify_exec(script);
-  return 1;
-}
-
-int notify_group_exec(vrrp_sgroup *vgroup, int state)
-{
-  char *script = get_gscript(vgroup, state);
-
-  if (!script || !script_open(script)) return 0;
-
-  /* Launch the script */
-  notify_exec(script);
-  return 1;
-}
diff --git a/vrrp_scheduler.c b/vrrp_scheduler.c
deleted file mode 100644 (file)
index 59356a6..0000000
+++ /dev/null
@@ -1,723 +0,0 @@
-/*
- * 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:        Sheduling framework for vrrp code.
- *
- * Version:     $Id: vrrp_scheduler.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#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"
-#include "memory.h"
-#include "list.h"
-#include "data.h"
-#include "smtp.h"
-
-extern thread_master *master;
-extern data *conf_data;
-
-/* VRRP FSM definition */
-static void vrrp_backup(vrrp_rt *, char *, int);
-static void vrrp_leave_master(vrrp_rt *, char *, int);
-static void vrrp_leave_fault(vrrp_rt *, char *, int);
-static void vrrp_become_master(vrrp_rt *, char *, int);
-static void vrrp_leave_dummy_master(vrrp_rt *, char *, int);
-
-static void vrrp_goto_master(vrrp_rt *);
-static void vrrp_master(vrrp_rt *);
-static void vrrp_fault(vrrp_rt *);
-static void vrrp_dummy_master(vrrp_rt *);
-
-struct {
-  void (*read) (vrrp_rt *, char *, int);
-  void (*read_to) (vrrp_rt *);
-} FSM[VRRP_MAX_FSM_STATE + 1] =
-{
-/* Stream Read Handlers    |    Stream Read_to handlers */
-/*-------------------------+----------------------------*/
-  {NULL,                       NULL},
-  {vrrp_backup,                        vrrp_goto_master},  /*  BACKUP          */
-  {vrrp_leave_master,          vrrp_master},       /*  MASTER          */
-  {vrrp_leave_fault,           vrrp_fault},        /*  FAULT           */
-  {vrrp_become_master,         vrrp_goto_master},  /*  GOTO_MASTER     */
-  {vrrp_leave_dummy_master,    vrrp_dummy_master}  /*  DUMMY_MASTER    */
-};
-
-/* SMTP alert notifier */
-static void vrrp_smtp_notifier(vrrp_rt *vrrp)
-{
-  if (vrrp->smtp_alert)
-    smtp_alert(master, NULL, vrrp
-                     , "Transition to MASTER state"
-                     , "=> VRRP Instance is now owning VRRP VIPs <=\n\n");
-}
-
-/*
- * Initialize state handling
- * --rfc2338.6.4.1
- */
-static void vrrp_init_state(list l)
-{
-  vrrp_rt *vrrp;
-  element e;
-
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-    vrrp = ELEMENT_DATA(e);
-
-    if (vrrp->priority == VRRP_PRIO_OWNER ||
-        vrrp->wantstate == VRRP_STATE_MAST) {
-#ifdef _HAVE_IPVS_SYNCD_
-      /* Check if sync daemon handling is needed */
-      if (vrrp->lvs_syncd_if)
-        ipvs_syncd_cmd(IPVS_STARTDAEMON, vrrp->lvs_syncd_if
-                                       , IPVS_MASTER);
-#endif
-      vrrp->state = VRRP_STATE_GOTO_MASTER;
-    } else {
-      vrrp->ms_down_timer = 3 * vrrp->adver_int
-                              + VRRP_TIMER_SKEW(vrrp);
-#ifdef _HAVE_IPVS_SYNCD_
-      /* Check if sync daemon handling is needed */
-      if (vrrp->lvs_syncd_if)
-        ipvs_syncd_cmd(IPVS_STARTDAEMON, vrrp->lvs_syncd_if
-                                       , IPVS_BACKUP);
-#endif
-      vrrp->state = VRRP_STATE_BACK;
-    }
-  }
-}
-
-static 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;
-  }
-  if (vrrp->state == VRRP_STATE_GOTO_MASTER     ||
-      vrrp->state == VRRP_STATE_GOTO_DUMMY_MAST ||
-      vrrp->state == VRRP_STATE_MAST            ||
-      vrrp->state == VRRP_STATE_DUMMY_MAST      ||
-      vrrp->state == VRRP_STATE_GOTO_FAULT) {
-    vrrp->sands.tv_sec = timer.tv_sec +
-                         vrrp->adver_int / TIMER_HZ;
-    vrrp->sands.tv_usec = timer.tv_usec;
-  }
-}
-
-static void vrrp_init_sands(list l)
-{
-  vrrp_rt *vrrp;
-  element e;
-
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-    vrrp = ELEMENT_DATA(e);
-    vrrp_init_instance_sands(vrrp);
-  }
-}
-
-/* Timer functions */
-static TIMEVAL vrrp_compute_timer(const int fd)
-{
-  vrrp_rt *vrrp;
-  TIMEVAL timer;
-  element e;
-  list l = conf_data->vrrp;
-
-  /* clean the memory */
-  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);
-    }
-  }
-
-  return timer;
-}
-
-static long vrrp_timer_fd(const int fd)
-{
-  TIMEVAL timer, vrrp_timer, now;
-
-  timer = vrrp_compute_timer(fd);
-  now = timer_now();
-  vrrp_timer = timer_sub(timer, now);
-
-  return (vrrp_timer.tv_sec*TIMER_HZ + vrrp_timer.tv_usec);
-}
-
-static int vrrp_timer_vrid_timeout(const int fd)
-{
-  vrrp_rt *vrrp;
-  list l = conf_data->vrrp;
-  element e;
-  TIMEVAL vrrp_timer;
-  int vrid = 0;
-
-  /* clean the memory */
-  memset(&vrrp_timer, 0, sizeof(struct timeval));
-  vrrp_timer = vrrp_compute_timer(fd);
-
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-    vrrp = ELEMENT_DATA(e);
-    if (timer_cmp(vrrp->sands, vrrp_timer) == 0)
-      vrid = vrrp->vrid;
-  }
-  return vrid;
-}
-
-/* Thread functions */
-static void vrrp_register_workers(list l)
-{
-  sock *sock;
-  TIMEVAL timer;
-  long vrrp_timer = 0;
-  element e;
-
-  /* Init compute timer */
-  memset(&timer, 0, sizeof(struct timeval));
-
-  /* Init the VRRP instances state */
-  vrrp_init_state(conf_data->vrrp);
-
-  /* Init VRRP instances sands */
-  vrrp_init_sands(conf_data->vrrp);
-
-  /* Register VRRP workers threads */
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-    sock = ELEMENT_DATA(e);
-    /* jump to asynchronous handling */
-    vrrp_timer = vrrp_timer_fd(sock->fd);
-    thread_add_read(master, vrrp_read_dispatcher_thread
-                          , NULL
-                          , sock->fd
-                          , vrrp_timer);
-  }
-}
-
-/* VRRP dispatcher functions */
-static int already_exist_sock(list l, int ifindex, int proto)
-{
-  sock *sock;
-  element e;
-
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-    sock = ELEMENT_DATA(e);
-    if ((sock->ifindex == ifindex) && (sock->proto == proto))
-      return 1;
-  }
-  return 0;
-}
-
-/* sockpool list primitives */
-void free_sock(void *data)
-{
-  FREE(data);
-}
-void dump_sock(void *data)
-{
-  sock *sock = data;
-  syslog(LOG_DEBUG, "sockpool -> ifindex(%d), proto(%d), fd(%d)"
-                  , sock->ifindex
-                  , sock->proto
-                  , sock->fd);
-}
-void alloc_sock(list l, int ifindex, int proto)
-{
-  sock *new;
-
-  new = (sock *)MALLOC(sizeof(sock));
-  new->ifindex = ifindex;
-  new->proto   = proto;
-
-  list_add(l, new);
-}
-
-static void vrrp_create_sockpool(list l)
-{
-  vrrp_rt *vrrp;
-  list p = conf_data->vrrp;
-  element e;
-  int ifindex;
-  int proto;
-
-  for (e = LIST_HEAD(p); e; ELEMENT_NEXT(e)) {
-    vrrp = ELEMENT_DATA(e);
-    ifindex = IF_INDEX(vrrp->ifp);
-    if (vrrp->auth_type == VRRP_AUTH_AH)
-      proto = IPPROTO_IPSEC_AH;
-    else
-      proto = IPPROTO_VRRP;
-
-    /* add the vrrp element if not exist */
-    if (!already_exist_sock(l, ifindex, proto))
-      alloc_sock(l, ifindex, proto);
-  }
-}
-
-static int vrrp_open_sockpool(list l)
-{
-  sock *sock;
-  element e;
-
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-    sock = ELEMENT_DATA(e);
-    sock->fd = open_vrrp_socket(sock->proto, sock->ifindex);
-    if (sock->fd == -1)
-      return -1;
-  }
-  return 1;
-}
-
-static void vrrp_set_fds(list l)
-{
-  sock *sock;
-  vrrp_rt *vrrp;
-  list p = conf_data->vrrp;
-  element e_sock;
-  element e_vrrp;
-  int proto;
-
-  for (e_sock = LIST_HEAD(l); e_sock; ELEMENT_NEXT(e_sock)) {
-    sock = ELEMENT_DATA(e_sock);
-    for (e_vrrp = LIST_HEAD(p); e_vrrp; ELEMENT_NEXT(e_vrrp)) {
-      vrrp = ELEMENT_DATA(e_vrrp);
-      if (vrrp->auth_type == VRRP_AUTH_AH)
-        proto = IPPROTO_IPSEC_AH;
-      else
-        proto = IPPROTO_VRRP;
-
-      if ((sock->ifindex == IF_INDEX(vrrp->ifp)) &&
-          (sock->proto == proto))
-        vrrp->fd = sock->fd;
-    }
-  }
-}
-
-/*
- * We create & allocate a socket pool here. The soft design
- * can be sum up by the following sketch :
- *
- *    fd1  fd2    fd3  fd4          fdi  fdi+1
- * -----\__/--------\__/---........---\__/---
- *    | ETH0 |    | ETH1 |          | ETHn |
- *    +------+    +------+          +------+
- *
- * Here we have n physical NIC. Each NIC own a maximum of 2 fds.
- * (one for VRRP the other for IPSEC_AH). All our VRRP instances
- * are multiplexed through this fds. So our design can handle 2*n
- * multiplexing points.
- */
-int vrrp_dispatcher_init(thread *thread)
-{
-  list pool;
-  int ret = 0;
-
-  /* allocate the sockpool */
-  pool = alloc_list(free_sock, dump_sock);
-
-  /* create the VRRP socket pool list */
-  vrrp_create_sockpool(pool);
-
-  /* open the VRRP socket pool */
-  ret = vrrp_open_sockpool(pool);
-  if (ret < 0) {
-    syslog(LOG_INFO, "Something is wrong with your hardware configuration");
-    free_list(pool);
-    thread_add_terminate_event(thread->master);
-    return -1;
-  }
-
-  /* set VRRP instance fds to sockpool */
-  vrrp_set_fds(pool);
-
-  /* register read dispatcher worker thread */
-  vrrp_register_workers(pool);
-
-  /* cleanup the temp socket pool */
-  dump_list(pool);
-  free_list(pool);
-
-  return 1;
-}
-
-static vrrp_rt *vrrp_search_instance(const int vrid)
-{
-  vrrp_rt *vrrp;
-  list l = conf_data->vrrp;
-  element e;
-
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-    vrrp = ELEMENT_DATA(e);
-    if (vrrp->vrid == vrid)
-      return vrrp;
-  }
-  return NULL;
-}
-
-static void vrrp_backup(vrrp_rt *vrrp
-                        , char *vrrp_buffer
-                        , int len)
-{
-  struct iphdr *iph = (struct iphdr *)vrrp_buffer;
-  ipsec_ah *ah;
-
-  if (iph->protocol == IPPROTO_IPSEC_AH) {
-    ah = (ipsec_ah *)(vrrp_buffer + sizeof(struct iphdr));
-    if (ah->seq_number >= vrrp->ipsecah_counter->seq_number) {
-      vrrp->ipsecah_counter->seq_number = ah->seq_number + 10;
-      vrrp->ipsecah_counter->cycle = 0;
-    }
-  }
-
-  vrrp_state_backup(vrrp, vrrp_buffer, len);
-}
-
-static void vrrp_become_master(vrrp_rt *vrrp
-                                     , char *vrrp_buffer
-                                     , int len)
-{
-  struct iphdr *iph = (struct iphdr *)vrrp_buffer;
-  ipsec_ah *ah;
-
-  /*
-   * If we are in IPSEC AH mode, we must be sync
-   * with the remote IPSEC AH VRRP instance counter.
-   */
-  if (iph->protocol == IPPROTO_IPSEC_AH) {
-    syslog(LOG_INFO, "VRRP_Instance(%s) AH seq_num sync"
-                   , vrrp->iname);
-    ah = (ipsec_ah *)(vrrp_buffer + sizeof(struct iphdr));
-    vrrp->ipsecah_counter->seq_number = ah->seq_number + 5;
-    vrrp->ipsecah_counter->cycle = 0;
-  }
-
-  /* Then jump to master state */
-  vrrp->wantstate = VRRP_STATE_MAST;
-  vrrp_state_goto_master(vrrp);
-  vrrp_smtp_notifier(vrrp);
-}
-
-static void vrrp_leave_master(vrrp_rt *vrrp
-                                     , char *vrrp_buffer
-                                     , int len)
-{
-  if (!IF_ISUP(vrrp->ifp)) {
-    syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN"
-                   , IF_NAME(vrrp->ifp));
-    vrrp->wantstate = VRRP_STATE_GOTO_FAULT;
-    vrrp_state_leave_master(vrrp);
-  } else if (vrrp_state_master_rx(vrrp, vrrp_buffer, len)) {
-    vrrp->wantstate = VRRP_STATE_BACK;
-    vrrp_state_leave_master(vrrp);
-  }
-}
-
-static void vrrp_leave_fault(vrrp_rt *vrrp
-                                    , char *vrrp_buffer
-                                    , int len)
-{
-  if (vrrp_state_fault_rx(vrrp, vrrp_buffer, len)) {
-    if (vrrp->sync) {
-      if (vrrp_sync_leave_fault(vrrp)) {
-        syslog(LOG_INFO, "VRRP_Instance(%s) prio is higher than received advert"
-                       , vrrp->iname);
-        vrrp_become_master(vrrp, vrrp_buffer, len);
-      }
-    } else {
-      syslog(LOG_INFO, "VRRP_Instance(%s) prio is higher than received advert"
-                     , vrrp->iname);
-      vrrp_become_master(vrrp, vrrp_buffer, len);
-    }
-  } else {
-    vrrp->state = VRRP_STATE_BACK;
-  }
-}
-
-static void vrrp_leave_dummy_master(vrrp_rt *vrrp
-                                           , char *vrrp_buffer
-                                           , int len)
-{
-/*
-  vrrp_rt *vrrp_isync;
-
-  if (vrrp->isync) {
-    vrrp_isync = vrrp_search_instance_isync(vrrp->isync);
-
-    if (vrrp_isync->state == VRRP_STATE_FAULT &&
-        vrrp->wantstate   == VRRP_STATE_GOTO_DUMMY_MAST) {
-      vrrp->wantstate = VRRP_STATE_DUMMY_MAST;
-      syslog(LOG_INFO, "VRRP_Instance(%s) leaving DUMMY MASTER state"
-                      , vrrp->iname);
-      vrrp_state_leave_master(vrrp);
-    }
-
-    if (vrrp_isync->state != VRRP_STATE_FAULT) {
-      switch (vrrp_isync->state) {
-        case VRRP_STATE_BACK:
-          vrrp->state = VRRP_STATE_BACK;
-          break;
-        case VRRP_STATE_MAST:
-          vrrp_become_master(vrrp, vrrp_buffer, len);
-          break;
-      }
-    }
-  }
-*/
-}
-
-static void vrrp_goto_master(vrrp_rt *vrrp)
-{
-  if (!IF_ISUP(vrrp->ifp)) {
-    syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN"
-                   , IF_NAME(vrrp->ifp));
-    vrrp->state = VRRP_STATE_FAULT;
-  } else {
-    /* If becoming MASTER in IPSEC AH AUTH, we reset the anti-replay */
-    if (vrrp->ipsecah_counter->cycle) {
-      vrrp->ipsecah_counter->cycle      = 0;
-      vrrp->ipsecah_counter->seq_number = 0;
-    }
-
-    if (vrrp->wantstate != VRRP_STATE_GOTO_DUMMY_MAST)
-      vrrp->wantstate = VRRP_STATE_MAST;
-
-    /* handle master state transition */
-    vrrp_state_goto_master(vrrp);
-    vrrp_smtp_notifier(vrrp);
-  }
-}
-
-static void vrrp_master(vrrp_rt *vrrp)
-{
-  /* Check if interface we are running on is UP */
-  if (vrrp->wantstate != VRRP_STATE_GOTO_FAULT) {
-    if (!IF_ISUP(vrrp->ifp)) {
-      syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN"
-                     , IF_NAME(vrrp->ifp));
-      vrrp->wantstate = VRRP_STATE_GOTO_FAULT;
-    }
-  }
-
-  /* Then perform the state transition */
-  if (vrrp->wantstate == VRRP_STATE_GOTO_FAULT ||
-      vrrp->wantstate == VRRP_STATE_BACK       ||
-      vrrp->ipsecah_counter->cycle) {
-    vrrp->ms_down_timer = 3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
-
-    /* handle backup state transition */
-    vrrp_state_leave_master(vrrp);
-
-    if (vrrp->state == VRRP_STATE_BACK)
-      syslog(LOG_INFO, "VRRP_Instance(%s) Now in BACKUP state"
-                     , vrrp->iname);
-    if (vrrp->state == VRRP_STATE_FAULT)
-      syslog(LOG_INFO, "VRRP_Instance(%s) Now in FAULT state"
-                     , vrrp->iname);
-  } else if (vrrp->state == VRRP_STATE_MAST) {
-    /* send the VRRP advert */
-    vrrp_state_master_tx(vrrp, 0);
-  }
-}
-
-static void vrrp_fault(vrrp_rt *vrrp)
-{
-  vrrp_sgroup *vgroup = vrrp->sync;
-
-  if (vgroup) {
-    if (vrrp_sync_group_up(vgroup)) {
-      if (vgroup->state == VRRP_STATE_FAULT) {
-        syslog(LOG_INFO, "VRRP_Group(%s) Leaving FAULT state"
-                       , GROUP_NAME(vgroup));
-        notify_group_exec(vgroup, vrrp->init_state);
-        vgroup->state = vrrp->init_state;
-      }
-    } else return;
-  } else if (IF_ISUP(vrrp->ifp))
-    syslog(LOG_INFO, "Kernel is reporting: interface %s UP"
-                   , IF_NAME(vrrp->ifp));
-  else return;
-
-  /* refresh the multicast fd */
-  new_vrrp_socket(vrrp);
-
-  /*
-   * We force the IPSEC AH seq_number sync
-   * to be done in read advert handler.
-   * So we ignore this timeouted state until remote
-   * VRRP MASTER send its advert for the concerned
-   * instance.
-   */
-  if (vrrp->auth_type == VRRP_AUTH_AH) {
-    /*
-     * Transition to BACKUP state for AH
-     * seq number synchronization.
-     */
-    syslog(LOG_INFO, "VRRP_Instance(%s) in FAULT state jump to AH sync"
-                   , vrrp->iname);
-    vrrp->wantstate = VRRP_STATE_BACK;
-    vrrp_state_leave_master(vrrp);
-  } else {
-    /* Otherwise, we transit to init state */
-    if (vrrp->init_state == VRRP_STATE_BACK)
-      vrrp->state = VRRP_STATE_BACK;
-    else {
-      vrrp_goto_master(vrrp);
-      vrrp_smtp_notifier(vrrp);
-    }
-  }
-}
-
-static void vrrp_dummy_master(vrrp_rt *vrrp)
-{
-  /* Check if interface we are running on is UP */
-  if (!IF_ISUP(vrrp->ifp))
-    vrrp->wantstate = VRRP_STATE_GOTO_FAULT;
-
-  if (vrrp->wantstate == VRRP_STATE_GOTO_FAULT) {
-    vrrp->ms_down_timer = 3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
-
-    /* handle backup state transition */
-    vrrp_state_leave_master(vrrp);
-  } else {
-    /* send the VRRP advert */
-    vrrp_state_master_tx(vrrp, 0);
-  }
-}
-
-/* Handle dispatcher read timeout */
-static int vrrp_dispatcher_read_to(int fd)
-{
-  vrrp_rt *vrrp;
-  int vrid = 0;
-  int prev_state = 0;
-
-  /* Searching for matching instance */
-  vrid = vrrp_timer_vrid_timeout(fd);
-  vrrp = vrrp_search_instance(vrid);
-
-  /* Run the FSM handler */
-  prev_state = vrrp->state;
-  VRRP_FSM_READ_TO(vrrp);
-
-  /* handle instance synchronization */
-  vrrp_sync_read_to(vrrp, prev_state);
-
-  /*
-   * We are sure the instance exist. So we can
-   * compute new sands timer safely.
-   */
-  vrrp_init_instance_sands(vrrp);
-  return vrrp->fd;
-}
-
-/* Handle dispatcher read packet */
-static int vrrp_dispatcher_read(int fd)
-{
-  vrrp_rt *vrrp;
-  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);
-
-  /* read & affect received buffer */
-  len = read(fd, vrrp_buffer, VRRP_PACKET_TEMP_LEN);
-  iph = (struct iphdr *)vrrp_buffer;
-
-  /* GCC bug : Workaround */
-  hd = (vrrp_pkt *) ((char *)iph + (iph->ihl << 2));
-  if (iph->protocol == IPPROTO_IPSEC_AH)
-    hd = (vrrp_pkt *) ((char *)hd + vrrp_ipsecah_len());
-  /* GCC bug : end */
-
-  /* Searching for matching instance */
-  vrrp = vrrp_search_instance(hd->vrid);
-
-  /* If no instance found => ignore the advert */
-  if (!vrrp) {
-    FREE(vrrp_buffer);
-    return fd;
-  }
-
-  /* Run the FSM handler */
-  prev_state = vrrp->state;
-  VRRP_FSM_READ(vrrp, vrrp_buffer, len);
-
-  /* handle instance synchronization */
-  vrrp_sync_read(vrrp, prev_state);
-
-  /*
-   * Refresh sands only if found matching instance.
-   * Otherwize the packet is simply ignored...
-   */
-  vrrp_init_instance_sands(vrrp);
-
-  /* cleanup the room */
-  FREE(vrrp_buffer);
-  return fd;
-}
-
-/* Our read packet dispatcher */
-int vrrp_read_dispatcher_thread(thread *thread)
-{
-  long vrrp_timer = 0;
-  int fd;
-
-  /* Dispatcher state handler */
-  if (thread->type == THREAD_READ_TIMEOUT)
-    fd = vrrp_dispatcher_read_to(thread->u.fd);
-  else
-    fd = vrrp_dispatcher_read(thread->u.fd);
-
-  /* register next dispatcher thread */
-  vrrp_timer = vrrp_timer_fd(fd);
-  TIMER_MICRO_ADJUST(vrrp_timer);
-  thread_add_read(thread->master, vrrp_read_dispatcher_thread
-                                , NULL
-                                , fd
-                                , vrrp_timer);
-  return 0;
-}
-
-/* Register VRRP thread */
-void register_vrrp_thread(void)
-{
-  /* Init the packet dispatcher */
-  if (!LIST_ISEMPTY(conf_data->vrrp))
-    thread_add_event(master, vrrp_dispatcher_init
-                           , NULL
-                           , VRRP_DISPATCHER);
-}
diff --git a/vrrp_sync.c b/vrrp_sync.c
deleted file mode 100644 (file)
index d589337..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * 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 synchronization framework.
- *
- * Version:     $Id: vrrp_sync.c,v 0.6.4 2002/06/25 20:18: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.
- */
-
-#include "vrrp_sync.h"
-#include "vrrp_if.h"
-#include "vrrp_notify.h"
-#include "data.h"
-
-/* extern global vars */
-extern data *conf_data;
-
-/* 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 = conf_data->vrrp_sync_group;
-
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-    vgroup = ELEMENT_DATA(e);
-    for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
-      str = VECTOR_SLOT(vgroup->iname, i);
-      if (strcmp(str, iname) == 0)
-        return vgroup;
-    }
-  }
-  return NULL;
-}
-
-/* jointure between instance and group => iname */
-vrrp_rt *vrrp_get_instance(char *iname)
-{
-  vrrp_rt *vrrp;
-  list l = conf_data->vrrp;
-  element e;
-
-  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
-    vrrp = ELEMENT_DATA(e);
-    if (strcmp(vrrp->iname, iname) == 0)
-      return vrrp;
-  }
-  return NULL;
-}
-
-/* All interface are UP in the same group */
-int vrrp_sync_group_up(vrrp_sgroup *vgroup)
-{
-  vrrp_rt *isync;
-  char *str;
-  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 (IF_ISUP(isync->ifp))
-      is_up++;
-  }
-  return (is_up == VECTOR_SIZE(vgroup->iname))?1:0;
-}
-
-/* Leaving fault state */
-int vrrp_sync_leave_fault(vrrp_rt *vrrp)
-{
-  vrrp_sgroup *vgroup = vrrp->sync;
-
-  if (vrrp_sync_group_up(vgroup)) {
-    syslog(LOG_INFO, "VRRP_Group(%s) Leaving FAULT state"
-                   , GROUP_NAME(vgroup));
-    vgroup->state = VRRP_STATE_MAST;
-    notify_group_exec(vgroup, VRRP_STATE_MAST);
-    return 1;
-  }
-  return 0;
-}
-
-static void vrrp_sync_backup(vrrp_rt *vrrp)
-{
-  int i;
-  char *str;
-  vrrp_rt *isync;
-  vrrp_sgroup *vgroup = vrrp->sync;
-
-  syslog(LOG_INFO, "VRRP_Group(%s) Syncing instances to BACKUP 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 != vrrp)
-      isync->wantstate = VRRP_STATE_BACK;
-  }
-  vgroup->state = VRRP_STATE_BACK;
-  notify_group_exec(vgroup, VRRP_STATE_BACK);
-}
-
-static void vrrp_sync_master_to(vrrp_rt *vrrp)
-{
-  int i;
-  char *str;
-  vrrp_rt *isync;
-  vrrp_sgroup *vgroup = vrrp->sync;
-
-  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);
-
-    /* Send the higher priority advert on all synced instances */
-    if (isync != vrrp) {
-      syslog(LOG_INFO, "VRRP_Instance(%s) sending OWNER advert"
-                     , isync->iname);
-      vrrp_state_master_tx(isync, VRRP_PRIO_OWNER);
-      isync->state = VRRP_STATE_MAST;
-    }
-  }
-  vgroup->state = VRRP_STATE_MAST;
-  notify_group_exec(vgroup, VRRP_STATE_MAST);
-}
-
-static void vrrp_sync_fault_to(vrrp_rt *vrrp)
-{
-  int i;
-  char *str;
-  vrrp_rt *isync;
-  vrrp_sgroup *vgroup = vrrp->sync;
-
-  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);
-
-    /*
-     * We force sync instance to backup mode.
-     * This reduce instance takeover to less than ms_down_timer.
-     * => by default ms_down_timer is set to 3secs.
-     * => Takeover will be less than 3secs !
-     */
-    if (isync != vrrp)
-      if (isync->state == VRRP_STATE_MAST)
-        isync->wantstate = VRRP_STATE_GOTO_FAULT;
-  }
-  vgroup->state = VRRP_STATE_FAULT;
-  notify_group_exec(vgroup, VRRP_STATE_FAULT);
-}
-
-static void vrrp_sync_dmaster_to(vrrp_rt *vrrp)
-{
-  int i;
-  char *str;
-  vrrp_rt *isync;
-  vrrp_sgroup *vgroup = vrrp->sync;
-
-  for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
-    str = VECTOR_SLOT(vgroup->iname, i);
-    isync = vrrp_get_instance(str);
-    if (isync != vrrp) {
-      if (isync->state == VRRP_STATE_FAULT) {
-        syslog(LOG_INFO, "VRRP_Instance(%s) Transition to DUMMY MASTER"
-                       , isync->iname);
-        isync->wantstate = VRRP_STATE_GOTO_DUMMY_MAST;
-      }
-    }
-  }
-  vgroup->state = VRRP_STATE_DUMMY_MAST;
-}
-
-/* Read TimeOut synchronization handler */
-void vrrp_sync_read_to(vrrp_rt *vrrp, int prev_state)
-{
-  /* Nothing to sync */
-  if (!vrrp->sync)
-    return;
-
-  /* Sync the group instance to MASTER state */
-  if (prev_state  == VRRP_STATE_BACK &&
-      vrrp->state == VRRP_STATE_MAST)
-    if (GROUP_STATE(vrrp->sync) == VRRP_STATE_BACK)
-      vrrp_sync_master_to(vrrp);
-
-  /* sync the group instance to FAULT state */
-  if (prev_state  == VRRP_STATE_MAST &&
-      vrrp->state == VRRP_STATE_FAULT)
-    if (GROUP_STATE(vrrp->sync) == VRRP_STATE_MAST)
-      vrrp_sync_fault_to(vrrp);
-
-  /*
-   * Break a MASTER/BACKUP state loop after sync instance
-   * FAULT state transition.
-   * => We doesn't receive remote MASTER adverts.
-   * => Emulate a DUMMY master to break the loop.
-   */
-  if (prev_state  == VRRP_STATE_MAST &&
-      vrrp->state == VRRP_STATE_BACK)
-    if (GROUP_STATE(vrrp->sync) == VRRP_STATE_FAULT)
-      vrrp_sync_dmaster_to(vrrp);
-
-  /* previous state symetry */
-  if (vrrp->state == VRRP_STATE_DUMMY_MAST)
-    if (GROUP_STATE(vrrp->sync) == VRRP_STATE_MAST)
-      vrrp->state = VRRP_STATE_MAST;
-}
-
-/* Read TimeOut synchronization handler */
-void vrrp_sync_read(vrrp_rt *vrrp, int prev_state)
-{
-  /* Nothing to sync */
-  if (!vrrp->sync)
-    return;
-
-  /* sync the group instance to BACKUP state */
-  if (prev_state  == VRRP_STATE_MAST &&
-      vrrp->state == VRRP_STATE_BACK)
-    if (GROUP_STATE(vrrp->sync) == VRRP_STATE_MAST)
-      vrrp_sync_backup(vrrp);
-
-  /* 
-   * Handle wanted transition to MASTER state.
-   * When Instance not in FAULT state, we received a remote
-   * lower priotity advert => Force a new VRRP election.
-   */ 
-  if (vrrp->state     == VRRP_STATE_BACK &&
-      vrrp->wantstate == VRRP_STATE_GOTO_MASTER) {
-    if (GROUP_STATE(vrrp->sync) != VRRP_STATE_FAULT) {
-      /* Force a new protocol master election */
-      syslog(LOG_INFO, "VRRP_Instance(%s) forcing a new MASTER election"
-                     , vrrp->iname);
-      vrrp_send_adv(vrrp, vrrp->priority);
-    }
-  }
-}