keepalived-0.5.3 v0.5.3
authorAlexandre Cassen <acassen@freebox.fr>
Sun, 24 Feb 2002 23:40:17 +0000 (00:40 +0100)
committerAlexandre Cassen <acassen@freebox.fr>
Mon, 28 Sep 2009 08:58:54 +0000 (10:58 +0200)
* keepalived-0.5.3 released.
* Added autoconf / automake generic scripts.
* Rewrite the configuration file stream parser.
  Using a generic keywords tree. Each keyword refer a specific
  stream handler. The main stream processor is a multilevel
  recursive function getting file stream and backtracking the
  keyword tree. Kind of global compiler structure using event driven
  stream processing.
* Re-design the global data structure to be much more generic and
  to dissociate LVS configuration related to checkers related. Remove
  static char lenght to use dynamic length strings.
* Created a global timer framework.
* Created a global vector template, used in cofiguration file
  parsing (both stream process & keywords tree generation).
* Created a global list template, used in most of the code.
* Review the global scheduler to remove repeated code.
* Created a global checkers API. The design and goal here is to
  facilitate new checkers creation by localizing specific checker
  code into a single file without any other global framework
  integration.
* Patched a SSL stream handling race condition finding end of stream.
* Jan Holmberg, review MISC checker to use forked process to not degrade
  global scheduler timer.
* Revisited the whole code to use new templates structures.
* Fixed a url lentgh bug into the genhash utility.
* Fabrice Bucher, <fabrice.bucher@urbanet.ch> fixed a timeout_persistence
  bug in the IPVS wrapper code.
* Bradley McLean, <bradlist@bradm.net> added support to '0' port number
  service in VS manipulation. Useful for balancing all services (host rather
  than service).
* Matthijs van der Klip, <matthijs.van.der.klip@nos.nl> enhanced smtp
  framework to use SMTP header and email enclosed with angle brackets.

71 files changed:
.data.c.swp [new file with mode: 0644]
AUTHORS
ChangeLog
INSTALL
Makefile [deleted file]
Makefile.in [new file with mode: 0644]
TODO
VERSION [new file with mode: 0644]
cfreader.c [deleted file]
cfreader.h [deleted file]
check.h [deleted file]
check_api.c [new file with mode: 0644]
check_api.h [new file with mode: 0644]
check_http.c
check_http.h
check_misc.c
check_misc.h
check_ssl.c
check_ssl.h
check_tcp.c
check_tcp.h
configure [new file with mode: 0755]
configure.in [new file with mode: 0644]
daemon.c [new file with mode: 0644]
daemon.h [new file with mode: 0644]
data.c [new file with mode: 0644]
data.h [new file with mode: 0644]
genhash/ChangeLog
genhash/Makefile [deleted file]
genhash/Makefile.in [new file with mode: 0644]
genhash/main.c
install-sh [new file with mode: 0755]
ipfwwrapper.c
ipfwwrapper.h
ipvswrapper.c
ipvswrapper.h
ipwrapper.c
ipwrapper.h
layer4.c
layer4.h
libipfwc/Makefile
list.c [new file with mode: 0644]
list.h [new file with mode: 0644]
main.c
main.h
memory.c
memory.h
parser.c [new file with mode: 0644]
parser.h [new file with mode: 0644]
pidfile.c
pidfile.h
scheduler.c
scheduler.h
smtp.c
smtp.h
timer.c [new file with mode: 0644]
timer.h [new file with mode: 0644]
utils.c
utils.h
vector.c [new file with mode: 0644]
vector.h [new file with mode: 0644]
vrrp.c
vrrp.h
vrrp_ipaddress.c
vrrp_ipaddress.h
vrrp_ipsecah.c
vrrp_ipsecah.h
vrrp_netlink.c
vrrp_netlink.h
vrrp_scheduler.c
vrrp_scheduler.h

diff --git a/.data.c.swp b/.data.c.swp
new file mode 100644 (file)
index 0000000..1602318
Binary files /dev/null and b/.data.c.swp differ
diff --git a/AUTHORS b/AUTHORS
index 4cb6c6c..66010a5 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1 +1 @@
-Alexandre Cassen <acassen@linux-vs.org>
+Alexandre Cassen, <acassen@linux-vs.org>
index 5a0fbcd..269b548 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2002-02-25  Alexandre Cassen  <acassen@linux-vs.org>
+       * keepalived-0.5.3 released.
+       * Added autoconf / automake generic scripts.
+       * Rewrite the configuration file stream parser.
+         Using a generic keywords tree. Each keyword refer a specific
+         stream handler. The main stream processor is a multilevel
+         recursive function getting file stream and backtracking the
+         keyword tree. Kind of global compiler structure using event driven
+         stream processing.
+       * Re-design the global data structure to be much more generic and
+         to dissociate LVS configuration related to checkers related. Remove
+         static char lenght to use dynamic length strings.
+       * Created a global timer framework.
+       * Created a global vector template, used in cofiguration file
+         parsing (both stream process & keywords tree generation).
+       * Created a global list template, used in most of the code.
+       * Review the global scheduler to remove repeated code.
+       * Created a global checkers API. The design and goal here is to
+         facilitate new checkers creation by localizing specific checker
+         code into a single file without any other global framework
+         integration.
+       * Patched a SSL stream handling race condition finding end of stream.
+       * Jan Holmberg, review MISC checker to use forked process to not degrade
+         global scheduler timer.
+       * Revisited the whole code to use new templates structures.
+       * Fixed a url lentgh bug into the genhash utility.
+       * Fabrice Bucher, <fabrice.bucher@urbanet.ch> fixed a timeout_persistence
+         bug in the IPVS wrapper code.
+       * Bradley McLean, <bradlist@bradm.net> added support to '0' port number
+         service in VS manipulation. Useful for balancing all services (host rather
+         than service).
+       * Matthijs van der Klip, <matthijs.van.der.klip@nos.nl> enhanced smtp
+         framework to use SMTP header and email enclosed with angle brackets.
+
 2001-12-20  Alexandre Cassen  <acassen@linux-vs.org>
        * keepalived-0.4.9a released.
        * Jan and I patched a memory pointer problems in vrrp_scheduler.c
diff --git a/INSTALL b/INSTALL
index ead6b25..1d4dc6c 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -8,6 +8,9 @@ Kernel needing
   Routing messages
   LinuxVirtualServer
 
+  Keepalived support all LVS code : including IPVS code for kernel 2.2
+  and kernel 2.4
+
 Library needing
 ===============
 
@@ -21,15 +24,23 @@ Installation
 
   1. uncompress the tarball
   2. cd into the directory
-  3. 'make' and 'make install'. This will install 
-     keepalived into your system (binary and configuration file).
-  4. cd into genhash directory (read the INSTALL file).
-  5. 'make' and 'make install'. This will install
-     the MD5 url digest generator. You need it to configure HTTP GET check
-     and SSL GET check in order to compute MD5SUM digest etalon.
+  3. './configure'
+  4. 'make'
+  5. 'make install'. This will install keepalived on your system,
+     binaries and configuration file :
+     * keepalived : The keepalived daemon program.
+     * genhash : The MD5 url digest generator. You need it to 
+                 configure HTTP GET check and SSL GET check in
+                 order to compute MD5SUM digest etalon.
+     * /etc/keepalived/keepalived.conf
   6. link keepalived.init into your runlevel directory. On redhat systems :
      ln -s /etc/rc.d/init.d/keepalived.init /etc/rc.d/rc3.d/S99keepalived
 
+  By default configure script use /usr/local as base directory. You can change
+  this value to your own by passing --prefix value to configure script
+
+  eg: './configure --prefix=/usr/'
+
 Configuration
 =============
 
@@ -42,4 +53,5 @@ Configuration
 
 
 Have fun with it !
-Alexandre
+
+Alexandre, <acassen@linux-vs.org>
diff --git a/Makefile b/Makefile
deleted file mode 100644 (file)
index 5306042..0000000
--- a/Makefile
+++ /dev/null
@@ -1,98 +0,0 @@
-# Makefile
-# Alexandre Cassen <acassen@linux-vs.org>
-
-EXEC = keepalived
-CC = gcc
-
-KERNEL := _KRNL_2_$(shell uname -r | cut -d'.' -f2)_
-
-# To compile with debug messages uncomment the following line
-CFLAGS= -g -O6 -Wall -Wunused -Wstrict-prototypes -D_DEBUG_ -D$(KERNEL)
-# CFLAGS= -g -Wall -O6 -D$(KERNEL) $(SSL)
-DEFS=
-
-SSL := -lssl -lcrypto
-LIB := $(LIB) $(SSL) -lpopt
-
-ifeq ($(KERNEL),_KRNL_2_2_)
-  LIB := $(LIB) libipfwc/libipfwc.a
-endif
-
-DEFS= main.h \
-       memory.h \
-        scheduler.h \
-        cfreader.h \
-        layer4.h \
-        check_tcp.h \
-        check_http.h \
-        check_ssl.h \
-        check_misc.h \
-       vrrp.h \
-       vrrp_scheduler.h \
-       vrrp_netlink.h \
-       vrrp_ipaddress.h \
-       vrrp_ipsecah.h \
-        smtp.h
-
-OBJECTS := main.o \
-       memory.o \
-       utils.o \
-       scheduler.o \
-       cfreader.o \
-       layer4.o \
-       check_tcp.o \
-       check_http.o \
-        check_ssl.o \
-       check_misc.o \
-       ipwrapper.o \
-       ipvswrapper.o
-ifeq ($(KERNEL),_KRNL_2_2_)
-  OBJECTS := $(OBJECTS) ipfwwrapper.o
-endif
-OBJECTS := $(OBJECTS) \
-       pidfile.o \
-       smtp.o \
-       vrrp.o \
-       vrrp_scheduler.o \
-       vrrp_netlink.o \
-       vrrp_ipaddress.o \
-       vrrp_ipsecah.o
-
-INCLUDE= -I/usr/src/linux/include
-
-.c.o:  
-       $(CC) -o $@ $(CFLAGS) $(INCLUDE) -c $*.c
-
-all:   $(EXEC)
-       strip $(EXEC)
-       @echo ""
-       @echo "Make complete"
-
-debug: $(EXEC)
-       @echo""
-       @echo "Make complete"
-
-$(EXEC):       $(OBJECTS) $(DEFS) $(LIB)
-       $(CC) -o $(EXEC) $(CFLAGS) $(OBJECTS) $(LIB)
-
-ifeq ($(KERNEL),_KRNL_2_2_)
-libipfwc/libipfwc.a:
-       cd libipfwc/ && $(MAKE) libipfwc.a
-endif
-
-subclean:
-ifeq ($(KERNEL),_KRNL_2_2_)
-       cd libipfwc/ && $(MAKE) clean
-endif
-
-clean: subclean
-       rm -f core *.o $(EXEC)
-
-install:
-       install -m 700 keepalived /usr/sbin/
-       install -m 755 etc/rc.d/init.d/keepalived.init /etc/rc.d/init.d/
-       mkdir /etc/keepalived
-       install -m 644 etc/keepalived/keepalived.conf /etc/keepalived/
-       mkdir /etc/keepalived/samples
-       install -m 644 samples/* /etc/keepalived/samples/
-
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..afe5e41
--- /dev/null
@@ -0,0 +1,103 @@
+# Makefile
+#
+# Keepalived OpenSource project.
+#
+# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
+
+EXEC = keepalived
+KERNEL := _KRNL_2_$(shell uname -r | cut -d'.' -f2)_
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+sbindir = @sbindir@
+
+init_dir            = /etc/rc.d/init.d
+init_script         = keepalived.init
+src_init_script     = etc/rc.d/init.d/$(init_script)
+src_conf_file       = etc/keepalived/keepalived.conf
+keepalived_conf_dir = /etc/keepalived
+
+CC = @CC@
+CFLAGS = @CFLAGS@ -Wall -Wunused -Wstrict-prototypes -D_DEBUG_ -D$(KERNEL)
+LDFLAGS = @LIBS@ @LDFLAGS@
+OBJS = @LIBOBJS@ \
+       main.o \
+       memory.o \
+       daemon.o \
+       utils.o \
+       timer.o \
+       scheduler.o \
+       vector.o \
+       list.o \
+       data.o \
+       parser.o \
+       layer4.o \
+       check_api.o \
+       check_tcp.o \
+       check_http.o \
+       check_ssl.o \
+       check_misc.o \
+       ipwrapper.o \
+       ipvswrapper.o \
+       pidfile.o \
+       smtp.o \
+       vrrp.o \
+       vrrp_scheduler.o \
+       vrrp_netlink.o \
+       vrrp_ipaddress.o \
+       vrrp_ipsecah.o
+
+INCLUDE= -I/usr/src/linux/include
+
+.c.o:
+       $(CC) -o $@ $(CFLAGS) $(INCLUDE) -c $*.c
+
+all:    $(EXEC)
+       strip $(EXEC)
+       @echo ""
+       cd genhash && $(MAKE)
+       @echo ""
+       @echo "Make complete"
+
+debug:  $(EXEC)
+       @echo ""
+       @echo "Make complete"
+
+$(EXEC): $(OBJS) $(LDFLAGS)
+       $(CC) -o $(EXEC) $(CFLAGS) $(OBJS) $(LDFLAGS)
+
+libipfwc/libipfwc.a:
+       cd libipfwc/ && $(MAKE) libipfwc.a
+
+subclean:
+ifeq ($(KERNEL),_KRNL_2_2_)
+       cd libipfwc/ && $(MAKE) clean
+endif
+       cd genhash/ && $(MAKE) 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)
+
+mrproper: clean clean-dist
+       rm -f config.*
+       rm -f Makefile
+       rm -f genhash/Makefile
+
+subinstall:
+       cd genhash/ && $(MAKE) install
+
+install: subinstall
+       install -m 700 $(EXEC) $(sbindir)/
+       install -m 755 $(src_init_script) $(init_dir)/
+       mkdir $(keepalived_conf_dir)
+       install -m 644 $(src_conf_file) $(keepalived_conf_dir)
+       mkdir $(keepalived_conf_dir)/samples
+       install -m 644 samples/* $(keepalived_conf_dir)/samples/
diff --git a/TODO b/TODO
index 7707ec3..eb73ee4 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,6 +1,4 @@
-* Synchronize IPVS topology with VRRP synchronization events.
 * Insert LDAP, FTP, SSH, IMAP, POP, RADIUS checkers.
-* Replave some unfixed len strcat & sprintf
 * Add minimum configuration verification (realserver must have
   a checker defined, ...)
 * Add system verification (must have LVS support in kernel, 
diff --git a/VERSION b/VERSION
new file mode 100644 (file)
index 0000000..be14282
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.5.3
diff --git a/cfreader.c b/cfreader.c
deleted file mode 100644 (file)
index 4991498..0000000
+++ /dev/null
@@ -1,1071 +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: cfreader.c,v 0.4.9a 2001/12/20 17:14:25 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 "cfreader.h"
-#include "memory.h"
-
-/* Global keyword structure defs */
-char *string; /* Temp read buffer */
-
-struct keyword keywords[] = {
-  {KW_BEGINFLAG,    "{"},
-  {KW_ENDFLAG,      "}"},
-
-  {KW_GLOBALDEFS,   "global_defs"},
-  {KW_EMAIL,        "notification_email"},
-  {KW_EMAILFROM,    "notification_email_from"},
-  {KW_LVSID,        "lvs_id"},
-  {KW_SMTP,         "smtp_server"},
-  {KW_STIMEOUT,     "smtp_connect_timeout"},
-
-  {KW_VS,           "virtual_server"},
-  {KW_DELAY,        "delay_loop"},
-  {KW_LBSCHED,      "lb_algo"},
-  {KW_LBKIND,       "lb_kind"},
-  {KW_NATMASK,      "nat_mask"},
-  {KW_PTIMEOUT,     "persistence_timeout"},
-  {KW_PROTOCOL,     "protocol"},
-  {KW_SSVR,         "sorry_server"},
-  {KW_FWMARK,       "fwmark"},
-
-  {KW_SVR,          "real_server"},
-  {KW_WEIGHT,       "weight"},
-  {KW_CTIMEOUT,     "connect_timeout"},
-  {KW_URL,          "url"},
-  {KW_URLPATH,      "path"},
-  {KW_DIGEST,       "digest"},
-  {KW_NBGETRETRY,   "nb_get_retry"},
-  {KW_DELAYRETRY,   "delay_before_retry"},
-
-  {KW_ICMPCHECK,    "ICMP_CHECK"},
-  {KW_TCPCHECK,     "TCP_CHECK"},
-  {KW_HTTPGET,      "HTTP_GET"},
-  {KW_SSLGET,       "SSL_GET"},
-  {KW_LDAPGET,      "LDAP_GET"},
-
-  {KW_MISCCHECK,   "MISC_CHECK"},
-  {KW_MISCPATH,    "misc_path"},
-
-  {KW_VRRP,         "vrrp_instance"},
-  {KW_VRRPSTATE,    "state"},
-  {KW_VRRPINT,      "interface"},
-  {KW_VRRPVRID,     "virtual_router_id"},
-  {KW_VRRPAUTH,     "authentication"},
-  {KW_VRRPAUTHTYPE, "auth_type"},
-  {KW_VRRPAUTHAH,   "AH"},
-  {KW_VRRPAUTHPWD,  "PASS"},
-  {KW_VRRPAUTHPASS, "auth_pass"},
-  {KW_VRRPPRIO,     "priority"},
-  {KW_VRRPADVERT,   "advert_int"},
-  {KW_VRRPIPADD,    "virtual_ipaddress"},
-  {KW_VRRPSYNC,     "sync_instance"},
-  {KW_VRRPPREEMPT,  "preempt"},
-  {KW_VRRPDEBUG,    "debug"},
-  {KW_VRRPNOTIFY,   "notify"},
-
-  {KW_SSLPASSWORD,  "password"},
-  {KW_SSLCAFILE,    "ca"},
-  {KW_SSLCERTFILE,  "certificate"},
-  {KW_SSLKEYFILE,   "key"},
-  {KW_SSL,          "SSL"},
-
-  {KW_UNKNOWN,     NULL}
-};
-
-int key(const char *word)
-{
-  int i;
-
-  for (i=0; keywords[i].word; i++)
-    if (strcmp(word, keywords[i].word) == 0)
-      return keywords[i].key;
-
-  return KW_UNKNOWN;
-}
-
-/* Dynamic data structure creation functions start here */
-int already_exist_vs(virtualserver *lstptr, uint32_t ip, uint16_t port)
-{
-  virtualserver *pointerptr=lstptr;
-
-  while(lstptr != NULL) {
-    if((lstptr->addr_ip.s_addr == ip) && (lstptr->addr_port == port)) {
-      lstptr = pointerptr;
-      return 1;
-    }
-    lstptr = (virtualserver *)lstptr->next;
-  }
-  lstptr = pointerptr;
-  return 0;
-}
-
-int already_exist_svr(realserver *lstptr, uint32_t ip, uint16_t port)
-{
-  realserver *pointerptr=lstptr;
-
-  while(lstptr != NULL) {
-    if((lstptr->addr_ip.s_addr == ip) && (lstptr->addr_port == port)) {
-      lstptr = pointerptr;
-      return 1;
-    }
-    lstptr = (realserver *)lstptr->next;
-  }
-  lstptr = pointerptr;
-  return 0;
-}
-
-vrrp_instance * add_item_vrrp(vrrp_instance *lstvrrp, vrrp_instance *vrrp)
-{
-  vrrp_instance *pointerlst = lstvrrp;
-
-  if (lstvrrp != NULL) {
-    while(lstvrrp->next != NULL) lstvrrp = (vrrp_instance *)lstvrrp->next;
-    lstvrrp->next = (struct vrrp_instance *)vrrp;
-    return pointerlst;
-  } else {
-    lstvrrp = vrrp;
-    return lstvrrp;
-  }
-}
-
-notification_email * add_item_email(notification_email *lstemail,notification_email *email)
-{
-  notification_email *pointerlst = lstemail;
-
-  if (lstemail != NULL) {
-    while(lstemail->next != NULL) lstemail = (notification_email *)lstemail->next;
-    lstemail->next = (struct notification_email *)email;
-    return pointerlst;
-  } else {
-    lstemail = email;
-    return lstemail;
-  }
-}
-
-virtualserver * add_item_vs(virtualserver *lstvs,virtualserver *vs)
-{
-  virtualserver *pointerlst = lstvs;
-
-  if(already_exist_vs(lstvs, vs->addr_ip.s_addr, vs->addr_port)) return lstvs;
-
-  if (lstvs != NULL) {
-    while(lstvs->next != NULL) lstvs = (virtualserver *)lstvs->next;
-    lstvs->next = (struct virtualserver *)vs;
-    return pointerlst;
-  } else {
-    lstvs = vs;
-    return lstvs;
-  }
-}
-
-realserver * add_item_svr(realserver *lstsvr,realserver *svr)
-{
-  realserver *pointerlst = lstsvr;
-
-  if(already_exist_svr(lstsvr, svr->addr_ip.s_addr, svr->addr_port)) return lstsvr;
-
-  if (lstsvr != NULL) {
-    while(lstsvr->next != NULL) lstsvr = (realserver *)lstsvr->next;
-    lstsvr->next = (struct realserver *)svr;
-    return pointerlst;
-  } else {
-    lstsvr = svr;
-    return lstsvr;
-  }
-}
-
-urls * add_item_url(urls *lsturls,urls *url)
-{
-  urls *pointerlst = lsturls;
-
-  if (lsturls != NULL) {
-    while(lsturls->next != NULL) lsturls = (urls *)lsturls->next;
-    lsturls->next = (struct urls *)url;
-    return pointerlst;
-  } else {
-    lsturls = url;
-    return lsturls;
-  }
-}
-
-/* Dynamic data structure cleanup functions start here */
-urls * remove_url(urls * lstptr)
-{
-  urls *t;
-
-  t = (urls *)lstptr->next;
-  FREE(lstptr);
-  return t;
-}
-
-realserver * remove_svr(realserver * lstptr)
-{
-  realserver *t;
-
-  t = (realserver *)lstptr->next;
-
-  if(lstptr->method->u.http_get != NULL) {
-    while(lstptr->method->u.http_get->check_urls != NULL)
-      lstptr->method->u.http_get->check_urls = remove_url(lstptr->method->u.http_get->check_urls);
-    FREE(lstptr->method->u.http_get);
-  }
-
-  FREE(lstptr->method);
-  FREE(lstptr);
-  return t;
-}
-
-virtualserver * remove_vs(virtualserver * lstptr)
-{
-  virtualserver *t;
-
-  t = (virtualserver *)lstptr->next;
-  while(lstptr->svr != NULL) lstptr->svr = remove_svr(lstptr->svr);
-
-  if (lstptr->s_svr)
-    FREE(lstptr->s_svr);
-  FREE(lstptr);
-  return t;
-}
-
-vrrp_instance *remove_vrrp(vrrp_instance *lstptr)
-{
-  vrrp_instance *t;
-
-  t = (vrrp_instance *)lstptr->next;
-  FREE(lstptr->vsrv->vaddr);
-  FREE(lstptr->vsrv->ipsecah_counter);
-  FREE(lstptr->vsrv->vif);
-  FREE(lstptr->vsrv);
-  FREE(lstptr);
-  return t;
-}
-
-notification_email * remove_email(notification_email *lstptr)
-{
-  notification_email *t;
-
-  t = (notification_email *)lstptr->next;
-  FREE(lstptr);
-  return t;
-}
-
-void clear_conf(configuration_data * lstptr)
-{
-  while(lstptr->email != NULL)
-    lstptr->email = remove_email(lstptr->email);
-
-  while(lstptr->vrrp != NULL)
-    lstptr->vrrp = remove_vrrp(lstptr->vrrp);
-
-  while(lstptr->lvstopology != NULL)
-    lstptr->lvstopology = remove_vs(lstptr->lvstopology);
-
-  /* All SSL GET use the same shared SSL context */
-  if (lstptr->ssldata)
-    FREE(lstptr->ssldata);
-
-  FREE(lstptr);
-}
-
-void clear_vrrp_instance(vrrp_instance *lstptr)
-{
-  while (lstptr) {
-    vrrp_state_stop_instance(lstptr->vsrv);
-    lstptr = (vrrp_instance *)lstptr->next;
-  }
-}
-
-/* Dynamic data structure dump functions start here */
-void dump_httpget(http_get_check *pointerhttpget)
-{
-  urls *pointerurls;
-
-  syslog(LOG_INFO,"       -> Nb get retry = %d",
-                   pointerhttpget->nb_get_retry);
-  syslog(LOG_INFO,"       -> Delay before retry = %d",
-                   pointerhttpget->delay_before_retry);
-
-  pointerurls = pointerhttpget->check_urls;
-  while(pointerhttpget->check_urls) {
-    syslog(LOG_INFO,"       -> Url = %s, Digest = %s",
-                     pointerhttpget->check_urls->url,
-                     pointerhttpget->check_urls->digest);
-
-    pointerhttpget->check_urls = (urls *)pointerhttpget->check_urls->next;
-  }
-  pointerhttpget->check_urls = pointerurls;
-}
-
-void dump_svr(realserver *pointersvr)
-{
-  while(pointersvr != NULL) {
-    syslog(LOG_INFO,"    -> SVR IP = %s, PORT = %d, WEIGHT = %d",
-                     inet_ntoa(pointersvr->addr_ip),
-                     ntohs(pointersvr->addr_port),
-                     pointersvr->weight);
-
-    switch (pointersvr->method->type) {
-      case ICMP_CHECK_ID: /* no more implemented... */
-        syslog(LOG_INFO,"       -> Keepalive method = ICMP_CHECK");
-        break;
-      case TCP_CHECK_ID:
-        syslog(LOG_INFO,"       -> Keepalive method = TCP_CHECK");
-        syslog(LOG_INFO,"       -> Connection timeout = %d",
-                         pointersvr->method->connection_to);
-        break;
-      case HTTP_GET_ID:
-        syslog(LOG_INFO,"       -> Keepalive method = HTTP_GET");
-        syslog(LOG_INFO,"       -> Connection timeout = %d",
-                         pointersvr->method->connection_to);
-        dump_httpget(pointersvr->method->u.http_get);
-        break;
-      case SSL_GET_ID:
-        syslog(LOG_INFO,"       -> Keepalive method = SSL_GET");
-        syslog(LOG_INFO,"       -> Connection timeout = %d",
-                         pointersvr->method->connection_to);
-        dump_httpget(pointersvr->method->u.http_get);
-        break;
-      case LDAP_GET_ID:
-        break;
-      case MISC_CHECK_ID:
-       syslog(LOG_INFO,"       -> Keepalive method = MISC_CHECK");
-       syslog(LOG_INFO,"       -> Check path = %s",
-                        pointersvr->method->u.misc_check_path);
-       break;
-    }
-
-    pointersvr = (realserver *)pointersvr->next;
-  }
-}
-
-void dump_vs(virtualserver *pointervs)
-{
-  while(pointervs != NULL) {
-    if (pointervs->vfwmark) {
-      syslog(LOG_INFO, " VS FWMARK = %d"
-                      , pointervs->vfwmark);
-    } else {
-      syslog(LOG_INFO, " VS IP = %s, PORT = %d"
-                      , inet_ntoa(pointervs->addr_ip)
-                      , ntohs(pointervs->addr_port));
-    }
-    syslog(LOG_INFO, " -> delay_loop = %d, lb_algo = %s, "
-                      "persistence = %s, protocol = %s",
-                      pointervs->delay_loop, pointervs->sched,
-                      pointervs->timeout_persistence,
-                      (pointervs->service_type == IPPROTO_TCP)?"TCP":"UDP");
-
-    switch (pointervs->loadbalancing_kind) {
-#ifdef _KRNL_2_2_
-      case 0:
-        syslog(LOG_INFO, " -> lb_kind = NAT");
-        syslog(LOG_INFO, " -> nat mask = %s", inet_ntoa(pointervs->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
-    }
-
-    if (pointervs->s_svr != NULL) {
-      syslog(LOG_INFO, " -> sorry server = [%s:%d]"
-                      , inet_ntoa(pointervs->s_svr->addr_ip)
-                      , ntohs(pointervs->s_svr->addr_port));
-    }
-
-    dump_svr(pointervs->svr);
-
-    pointervs = (virtualserver *)pointervs->next;
-  }
-}
-
-void dump_email(notification_email *pointeremail)
-{
-  while(pointeremail != NULL) {
-    syslog(LOG_INFO," Email notification = %s", pointeremail->addr);
-
-    pointeremail = (notification_email *)pointeremail->next;
-  }
-}
-
-void dump_vrrp(vrrp_instance *pointervrrp)
-{
-  int i;
-
-  while (pointervrrp != NULL) {
-    syslog(LOG_INFO, " VRRP Instance = %s", pointervrrp->iname);
-    if (pointervrrp->vsrv->init_state == VRRP_STATE_BACK)
-      syslog(LOG_INFO, "   Want State = BACKUP");
-    else
-      syslog(LOG_INFO, "   Want State = MASTER");
-    syslog(LOG_INFO, "   Device = %s", pointervrrp->vsrv->vif->ifname);
-    if (strlen(pointervrrp->isync) > 0)
-      syslog(LOG_INFO, "   Sync with instance = %s", pointervrrp->isync);
-    syslog(LOG_INFO, "   Virtual Router ID = %d", pointervrrp->vsrv->vrid);
-    syslog(LOG_INFO, "   Priority = %d", pointervrrp->vsrv->priority);
-    syslog(LOG_INFO, "   Advert interval = %dsec",
-                      pointervrrp->vsrv->adver_int/VRRP_TIMER_HZ);
-    if (pointervrrp->vsrv->preempt)
-      syslog(LOG_INFO, "   Preempt active");
-    if (pointervrrp->vsrv->vif->auth_type) {
-      syslog(LOG_INFO, "   Authentication type = %s", 
-            (pointervrrp->vsrv->vif->auth_type == VRRP_AUTH_AH)?"IPSEC_AH":"SIMPLE_PASSWORD" );
-      syslog(LOG_INFO, "   Password = %s", pointervrrp->vsrv->vif->auth_data);
-    }
-    syslog(LOG_INFO, "   VIP count = %d", pointervrrp->vsrv->naddr);
-    for (i = 0; i<pointervrrp->vsrv->naddr; i++)
-      syslog(LOG_INFO, "     VIP%d = %s", i+1, ip_ntoa(ntohl(pointervrrp->vsrv->vaddr[i].addr)));
-
-    pointervrrp = (vrrp_instance *)pointervrrp->next;
-  }
-}
-
-void dump_conf(configuration_data *lstconf)
-{
-  if (lstconf == NULL) {
-    syslog(LOG_INFO, "Empty data configuration !!!");
-  } else {
-    syslog(LOG_INFO, "------< Global definitions >------");
-    syslog(LOG_INFO, " LVS ID = %s",lstconf->lvs_id);
-    syslog(LOG_INFO, " Smtp server = %s", inet_ntoa(lstconf->smtp_server));
-    syslog(LOG_INFO, " Smtp server connection timeout = %d", lstconf->smtp_connection_to);
-    syslog(LOG_INFO, " Email notification from = %s", lstconf->email_from);
-    dump_email(lstconf->email);
-
-    if (lstconf->ssldata) {
-      syslog(LOG_INFO, "------< SSL definitions >------");
-      if (strlen(lstconf->ssldata->password) > 0)
-        syslog(LOG_INFO, " Password: %s", lstconf->ssldata->password);
-      if (strlen(lstconf->ssldata->cafile) > 0)
-        syslog(LOG_INFO, " CA-file: %s", lstconf->ssldata->cafile);
-      if (strlen(lstconf->ssldata->certfile) > 0)
-        syslog(LOG_INFO, " Certificate file: %s", lstconf->ssldata->certfile);
-      if (strlen(lstconf->ssldata->keyfile) > 0)
-        syslog(LOG_INFO, " Key file: %s", lstconf->ssldata->keyfile);
-      if (!strlen(lstconf->ssldata->keyfile)  &&
-          !strlen(lstconf->ssldata->certfile) &&
-          !strlen(lstconf->ssldata->cafile)   &&
-          !strlen(lstconf->ssldata->password)) 
-        syslog(LOG_INFO, " Using autogen SSL context");
-    }
-
-    if (lstconf->vrrp) {
-      syslog(LOG_INFO, "------< VRRP Topology >------");
-      dump_vrrp(lstconf->vrrp);
-    }
-
-    if (lstconf->lvstopology) {
-      syslog(LOG_INFO, "------< LVS Topology >------");
-      dump_vs(lstconf->lvstopology);
-    }
-  }
-}
-
-/* Dynamic data structure stream processing functions start here */
-void process_stream_icmpcheck(FILE *stream, realserver *svrfill)
-{
-  keepalive_check *methodfill;
-
-  /* Allocate new method structure */
-  methodfill = (keepalive_check *)MALLOC(sizeof(keepalive_check));
-
-  methodfill->type = ICMP_CHECK_ID;
-  methodfill->u.http_get = NULL;
-
-  svrfill->method = methodfill;
-}
-
-void process_stream_tcpcheck(FILE *stream, realserver *svrfill)
-{
-  keepalive_check *methodfill;
-
-  /* Allocate new method structure */
-  methodfill = (keepalive_check *)MALLOC(sizeof(keepalive_check));
-
-  methodfill->type = TCP_CHECK_ID;
-  methodfill->u.http_get = NULL;
-
-  do {
-    switch (key(string)) {
-      case KW_CTIMEOUT:
-        fscanf(stream, "%d", &methodfill->connection_to);
-        break;
-      case KW_UNKNOWN:
-        break;
-    }
-    fscanf(stream, "%s", string);
-  } while(key(string) != KW_ENDFLAG);
-
-  svrfill->method = methodfill;
-}
-
-void process_stream_misccheck(FILE *stream, realserver *svrfill)
-{
-  keepalive_check *methodfill;
-  char* pathstring = (char*)MALLOC(512);
-
-  /* Allocate new method structure */
-  methodfill = (keepalive_check *)MALLOC(sizeof(keepalive_check));
-
-  methodfill->type = MISC_CHECK_ID;
-  methodfill->u.misc_check_path = NULL;
-
-  do {
-    switch (key(string)) {
-      case KW_CTIMEOUT:
-        fscanf(stream, "%d", &methodfill->connection_to);
-        break;
-      case KW_MISCPATH:
-       fgets(pathstring,512,stream);
-       methodfill->u.misc_check_path=pathstring;
-       break;
-      case KW_UNKNOWN:
-        break;
-    }
-    fscanf(stream, "%s", string);
-  } while(key(string) != KW_ENDFLAG);
-
-  svrfill->method = methodfill;
-}
-
-void process_stream_url(FILE *stream, http_get_check *httpgetfill)
-{
-  urls *urlfill;
-
-  /* Allocate new url structure */
-  urlfill = (urls *)MALLOC(sizeof(urls));
-
-  urlfill->next = NULL;
-
-  do {
-    switch (key(string)) {
-      case KW_URLPATH:
-        fscanf(stream, "%s", urlfill->url);
-        break;
-      case KW_DIGEST:
-        fscanf(stream, "%s", urlfill->digest);
-        break;
-      case KW_UNKNOWN:
-        break;
-    }
-    fscanf(stream, "%s", string);
-  } while(key(string) != KW_ENDFLAG);
-
-  httpgetfill->check_urls = add_item_url(httpgetfill->check_urls, urlfill);
-}
-
-void process_stream_httpget(FILE *stream, realserver *svrfill, int type)
-{
-  keepalive_check *methodfill;
-  http_get_check *httpgetfill;
-
-  /* Allocate new method structure */
-  methodfill = (keepalive_check *)MALLOC(sizeof(keepalive_check));
-
-  /* Allocate new http get structure */
-  httpgetfill = (http_get_check *)MALLOC(sizeof(http_get_check));
-
-  methodfill->type = type;
-  methodfill->u.http_get = httpgetfill;
-
-  httpgetfill->check_urls = NULL;
-
-  do {
-    switch (key(string)) {
-      case KW_CTIMEOUT:
-        fscanf(stream, "%d", &methodfill->connection_to);
-        break;
-      case KW_NBGETRETRY:
-        fscanf(stream, "%d", &httpgetfill->nb_get_retry);
-        break;
-      case KW_DELAYRETRY:
-        fscanf(stream, "%d", &httpgetfill->delay_before_retry);
-        break;
-      case KW_URL:
-        process_stream_url(stream, httpgetfill);
-        break;
-      case KW_UNKNOWN:
-        break;
-    }
-    fscanf(stream, "%s", string);
-  } while(key(string) != KW_ENDFLAG);
-
-  svrfill->method = methodfill;
-}
-
-void process_stream_svr(FILE *stream, virtualserver *vsfill)
-{
-  realserver *svrfill;
-
-  /* Allocate new real server structure */
-  svrfill = (realserver *)MALLOC(sizeof(realserver));
-
-  /* Add the real server allocated to the virtual server
-   * data structure.
-   */
-  svrfill->next = NULL;                   /* not required */
-  svrfill->alive = 1;                     /* server is alive */
-  vsfill->svr = add_item_svr(vsfill->svr, svrfill);
-
-  fscanf(stream, "%s", string); 
-  svrfill->addr_ip.s_addr = inet_addr(string);
-  fscanf(stream, "%s", string);
-  svrfill->addr_port = htons(atoi(string));
-
-  do {
-    switch (key(string)) {
-      case KW_WEIGHT:
-        fscanf(stream, "%d", &svrfill->weight);
-        break;
-      case KW_ICMPCHECK:
-        process_stream_icmpcheck(stream, svrfill);
-        break;
-      case KW_TCPCHECK:
-        process_stream_tcpcheck(stream, svrfill);
-        break;
-      case KW_HTTPGET:
-        process_stream_httpget(stream, svrfill, HTTP_GET_ID);
-        break;
-      case KW_SSLGET: 
-        process_stream_httpget(stream, svrfill, SSL_GET_ID);
-        break;
-      case KW_LDAPGET: /* not yet implemented */
-        break;
-      case KW_MISCCHECK:
-       process_stream_misccheck(stream, svrfill);
-       break;
-      case KW_UNKNOWN:
-        break;
-    }
-    fscanf(stream, "%s", string);
-  } while(key(string) != KW_ENDFLAG);
-}
-
-void process_stream_ssvr(FILE *stream, virtualserver *vsfill)
-{
-  realserver *ssvrfill;
-
-  /* Allocate new sorry server structure */
-  ssvrfill = (realserver *)MALLOC(sizeof(realserver));
-
-  /* direct affectation, we can use add_item_svr, so
-   * can specify more than 1 sorry_server...
-   * Not really needed !
-   */
-  vsfill->s_svr = ssvrfill;
-
-  ssvrfill->alive = 0;
-  ssvrfill->weight = 1;
-  ssvrfill->method = NULL;
-  ssvrfill->next = NULL;
-
-  fscanf(stream, "%s", string);
-  ssvrfill->addr_ip.s_addr = inet_addr(string);
-  fscanf(stream, "%s", string);
-  ssvrfill->addr_port = htons(atoi(string));
-}
-
-void process_stream_vs(FILE *stream, configuration_data *conf_data)
-{
-  virtualserver *vsfill;
-
-  /* Allocate new virtual server structure */
-  vsfill = (virtualserver *)MALLOC(sizeof(virtualserver));
-
-  /* Add the virtual server allocated to the configuration
-   * data structure.
-   */
-  vsfill->next = NULL;                      /* not required */
-  vsfill->s_svr = NULL;
-  conf_data->lvstopology = add_item_vs(conf_data->lvstopology, vsfill);
-
-  fscanf(stream, "%s", string);
-  if (!strcmp(string, "fwmark")) {
-    fscanf(stream, "%s", string);
-    vsfill->vfwmark = atoi(string);
-  } else {
-    vsfill->vfwmark = 0;
-    vsfill->addr_ip.s_addr = inet_addr(string);
-    fscanf(stream, "%s", string);
-    vsfill->addr_port = htons(atoi(string));
-  }
-
-  /* Setting default value */
-  vsfill->delay_loop = KEEPALIVED_DEFAULT_DELAY;
-
-  do {
-    switch (key(string)) {
-      case KW_DELAY:
-        fscanf(stream, "%d", &vsfill->delay_loop);
-        break;
-      case KW_LBSCHED:
-        fscanf(stream, "%s", vsfill->sched);
-        break;
-      case KW_LBKIND:
-        fscanf(stream, "%s", string);
-
-#ifdef _KRNL_2_2_
-        if (strcmp(string, "NAT") == 0)
-          vsfill->loadbalancing_kind = 0;
-        else
-          if (strcmp(string, "DR") == 0)
-            vsfill->loadbalancing_kind = IP_MASQ_F_VS_DROUTE;
-          else
-            if (strcmp(string, "TUN") == 0)
-              vsfill->loadbalancing_kind = IP_MASQ_F_VS_TUNNEL;
-            else
-              syslog(LOG_DEBUG,"CFREADER : unknown [%s] routing method."
-                              , string);
-#else
-        if (strcmp(string, "NAT") == 0)
-          vsfill->loadbalancing_kind = IP_VS_CONN_F_MASQ;
-        else
-          if (strcmp(string, "DR") == 0)
-            vsfill->loadbalancing_kind = IP_VS_CONN_F_DROUTE;
-          else
-            if (strcmp(string, "TUN") == 0)
-              vsfill->loadbalancing_kind = IP_VS_CONN_F_TUNNEL;
-            else
-              syslog(LOG_DEBUG,"CFREADER : unknown [%s] routing method."
-                              , string);
-#endif
-
-        break;
-      case KW_NATMASK:
-        fscanf(stream, "%s", string);
-        vsfill->nat_mask.s_addr = inet_addr(string);
-        break;
-      case KW_PTIMEOUT:
-        fscanf(stream, "%s", vsfill->timeout_persistence);
-        break;
-      case KW_PROTOCOL:
-        fscanf(stream, "%s", string);
-        vsfill->service_type = (strcmp(string,"TCP") == 0)?IPPROTO_TCP:IPPROTO_UDP;
-        break;
-      case KW_SSVR:
-        process_stream_ssvr(stream, vsfill);
-        break;
-      case KW_SVR:
-        process_stream_svr(stream, vsfill);
-        break;
-      case KW_UNKNOWN:
-        break;
-    }
-    fscanf(stream, "%s", string);
-  } while(key(string) != KW_ENDFLAG);
-}
-
-void process_stream_email(FILE *stream, configuration_data *conf_data)
-{
-  notification_email *emailfill;
-
-  /* Fill in email liste */
-  do {
-    fscanf(stream, "%s", string);
-    if(key(string) != KW_BEGINFLAG && key(string) != KW_ENDFLAG) {
-      emailfill = (notification_email *)MALLOC(sizeof(notification_email));
-      strncat(emailfill->addr, string, sizeof(emailfill->addr));
-      emailfill->next = NULL;
-      conf_data->email = add_item_email(conf_data->email, emailfill);
-    }
-  } while(key(string) != KW_ENDFLAG);
-}
-
-void process_stream_globaldefs(FILE *stream, configuration_data *conf_data)
-{
-  /* Fill in the global defs structure */
-  do {
-    switch (key(string)) {
-      case KW_LVSID:
-        fscanf(stream, "%s", conf_data->lvs_id);
-        break;
-      case KW_SMTP:
-        fscanf(stream, "%s", string);
-        conf_data->smtp_server.s_addr = inet_addr(string);
-        break;
-      case KW_STIMEOUT:
-        fscanf(stream, "%d", &conf_data->smtp_connection_to);
-        break;
-      case KW_EMAILFROM:
-        fscanf(stream, "%s", conf_data->email_from);
-        break;
-      case KW_EMAIL:
-        process_stream_email(stream, conf_data);
-        break;
-      case KW_UNKNOWN:
-        break;
-    }
-    fscanf(stream, "%s", string);
-  } while(key(string) != KW_ENDFLAG);
-}
-
-int process_stream_ssl(FILE *stream, configuration_data *conf_data)
-{
-  /* Fill in the global defs structure */
-  do {
-    switch (key(string)) {
-      case KW_SSLPASSWORD:
-        fscanf(stream, "%s", conf_data->ssldata->password);
-        conf_data->ssldata->enable |= 1;
-        break;
-      case KW_SSLCAFILE:
-        fscanf(stream, "%s", conf_data->ssldata->cafile);
-        conf_data->ssldata->enable |= 2;
-        break;
-      case KW_SSLKEYFILE:
-        fscanf(stream, "%s", conf_data->ssldata->keyfile);
-        conf_data->ssldata->enable |= 4;
-        break;
-      case KW_SSLCERTFILE:
-        fscanf(stream, "%s", conf_data->ssldata->certfile);
-        conf_data->ssldata->enable |= 8;
-        break;
-      case KW_UNKNOWN:
-        break;
-    }
-    fscanf(stream, "%s", string);
-  } while(key(string) != KW_ENDFLAG);
-
-  return conf_data->ssldata->enable;
-}
-
-static void add_item_vrrp_vip(vrrp_rt *vsrv, uint32_t ipaddr)
-{
-  vsrv->naddr++;
-  /* alloc the room */
-  if( vsrv->vaddr ){
-    vsrv->vaddr = REALLOC(vsrv->vaddr, vsrv->naddr*sizeof(*vsrv->vaddr));
-  } else {
-    vsrv->vaddr = (vip_addr *)MALLOC(sizeof(*vsrv->vaddr));
-  }
-  /* store the data */
-  vsrv->vaddr[vsrv->naddr-1].addr = ipaddr;
-  vsrv->vaddr[vsrv->naddr-1].deletable = 0;
-}
-
-void process_stream_vrrp_ipaddress(FILE *stream, vrrp_rt *vrrp)
-{
-  uint32_t ipaddr;
-
-  do {
-    fscanf(stream, "%s", string);
-    if(key(string) != KW_BEGINFLAG && key(string) != KW_ENDFLAG) {
-      ipaddr = inet_addr(string);
-      add_item_vrrp_vip(vrrp, ntohl(ipaddr));
-    }
-  } while(key(string) != KW_ENDFLAG);
-}
-
-void process_stream_vrrp_auth(FILE *stream, vrrp_if *vif)
-{
-  do {
-    switch (key(string)) {
-      case KW_VRRPAUTHTYPE:
-        fscanf(stream, "%s", string);
-        vif->auth_type = (key(string) == KW_VRRPAUTHAH)?VRRP_AUTH_AH:VRRP_AUTH_PASS;
-        break;
-      case KW_VRRPAUTHPASS:
-        fscanf(stream, "%s", vif->auth_data);
-        break;
-      case KW_UNKNOWN:
-        break;
-    }
-    fscanf(stream, "%s", string);
-  } while(key(string) != KW_ENDFLAG);
-}
-
-int process_stream_vrrp(FILE *stream, configuration_data *conf_data)
-{
-  vrrp_instance *vrrpfill;
-  vrrp_rt *rtfill;
-  vrrp_if *viffill;
-  seq_counter *counterfill;
-
-  /* Allocate new VRRP structure */
-  vrrpfill     = (vrrp_instance *)MALLOC(sizeof(vrrp_instance));
-  rtfill       = (vrrp_rt *)      MALLOC(sizeof(vrrp_rt));
-  viffill      = (vrrp_if *)      MALLOC(sizeof(vrrp_if));
-  counterfill  = (seq_counter *)  MALLOC(sizeof(seq_counter));
-
-  /* Add the vrrp instance allocated to the configuration
-   * data structure.
-   */
-  vrrpfill->vsrv          = rtfill;
-  vrrpfill->vsrv->vif     = viffill;
-  vrrpfill->vsrv->ipsecah_counter = counterfill;
-  vrrpfill->vsrv->vaddr   = NULL;
-  vrrpfill->vsrv->vaddr   = NULL;
-  vrrpfill->next          = NULL;
-
-  /* default value */
-  rtfill->wantstate       = VRRP_STATE_BACK;
-  rtfill->init_state      = VRRP_STATE_BACK;
-
-  conf_data->vrrp = add_item_vrrp(conf_data->vrrp, vrrpfill);
-
-  fscanf(stream, "%s", vrrpfill->iname);
-
-  /* Fill in the VRRP structure */
-  do {
-    switch (key(string)) {
-      case KW_VRRPSYNC:
-        fscanf(stream, "%s", vrrpfill->isync);
-        break;
-      case KW_VRRPSTATE:
-        fscanf(stream, "%s", string);
-        if (strcmp(string, "MASTER") == 0) {
-          rtfill->wantstate = VRRP_STATE_MAST;
-          rtfill->init_state = VRRP_STATE_MAST;
-        } else {
-          rtfill->wantstate = VRRP_STATE_BACK;
-          rtfill->init_state = VRRP_STATE_BACK;
-        }
-        break;
-      case KW_VRRPINT:
-        fscanf(stream, "%s", viffill->ifname);
-        break;
-      case KW_VRRPVRID:
-        fscanf(stream, "%d", &rtfill->vrid);
-        if (VRRP_IS_BAD_VID(rtfill->vrid)) {
-          syslog(LOG_DEBUG, "VRRP Error : VRID not valid !");
-          syslog(LOG_DEBUG, "VRRP Error : must be between 1 & 255. reconfigure !");
-          return 0;
-        }
-        break;
-      case KW_VRRPPRIO:
-        fscanf(stream, "%d", &rtfill->priority);
-        if (VRRP_IS_BAD_PRIORITY(rtfill->priority)) {
-          syslog(LOG_DEBUG, "VRRP Error : priority not valid !");
-          syslog(LOG_DEBUG, "VRRP Error : must be between 1 & 255. reconfigure !");
-          return 0;
-        }
-        break;
-      case KW_VRRPADVERT:
-        fscanf(stream, "%d", &rtfill->adver_int);
-        if (VRRP_IS_BAD_ADVERT_INT(rtfill->adver_int)) {
-          syslog(LOG_DEBUG, "VRRP Error : Advert intervall not valid !");
-          syslog(LOG_DEBUG, "VRRP Error : must be between less than 1sec. reconfigure !");
-          return 0;
-        }
-        rtfill->adver_int *= VRRP_TIMER_HZ;
-        break;
-      case KW_VRRPAUTH:
-        process_stream_vrrp_auth(stream, viffill);
-        break;
-      case KW_VRRPIPADD:
-        process_stream_vrrp_ipaddress(stream, rtfill);
-        break;
-      case KW_VRRPPREEMPT:
-        rtfill->preempt = !rtfill->preempt;
-        break;
-      case KW_VRRPDEBUG:
-        fscanf(stream, "%d", &rtfill->debug);
-        if (VRRP_IS_BAD_DEBUG_INT(rtfill->debug)) {
-          syslog(LOG_DEBUG, "VRRP Error : Debug intervall not valid !");
-          syslog(LOG_DEBUG, "VRRP Error : must be between 0-4");
-          return 0;
-        }
-        break;
-      case KW_VRRPNOTIFY:
-        fscanf(stream, "%s", rtfill->notify_file);
-        rtfill->notify_exec = 1;
-        break;
-      case KW_UNKNOWN:
-        break;
-    }
-    fscanf(stream, "%s", string);
-  } while(key(string) != KW_ENDFLAG);
-
-  /* Compute the static values to finish initialization */
-  if (!complete_vrrp_init(rtfill))
-    return 0;
-
-  return 1;
-}
-
-configuration_data *conf_reader(char *conf_file)
-{
-  configuration_data *conf_data;
-  FILE *stream;
-
-  /* Parse the confuguration file */
-  stream = fopen((conf_file)?conf_file:CONFFILE, "r");
-  if(!stream) {
-    syslog(LOG_INFO, "ConfReader : Can not read the configuration file...");
-    return(NULL);
-  }
-
-  /* Allocate configuration data memory */
-  conf_data = (configuration_data *)MALLOC(sizeof(configuration_data));
-
-  /* Allocate temp buffer string */
-  string = (char *)MALLOC(TEMP_BUFFER_LENGTH);
-
-  /* Initialise the dynamic data structure */
-  conf_data->email = NULL;
-  conf_data->lvstopology = NULL;
-  conf_data->ssldata = NULL;
-
-  while (!feof(stream)) {
-    switch (key(string)) {
-      case KW_GLOBALDEFS:
-        process_stream_globaldefs(stream, conf_data);
-        break;
-      case KW_VS:
-        process_stream_vs(stream, conf_data);
-        break;
-      case KW_VRRP:
-        if (!process_stream_vrrp(stream, conf_data))
-          return NULL;
-        break;
-      case KW_SSL:
-        conf_data->ssldata = (ssl_data *)MALLOC(sizeof(ssl_data));
-        conf_data->ssldata->enable = 0;
-        if ((process_stream_ssl(stream, conf_data) & 7) != 7)
-          return NULL;
-        break;
-      case KW_UNKNOWN:
-        break;
-    }
-    fscanf(stream, "%s", string);
-  }
-
-  FREE(string);
-  fclose(stream);
-  return(conf_data);
-}
diff --git a/cfreader.h b/cfreader.h
deleted file mode 100644 (file)
index ec714e4..0000000
+++ /dev/null
@@ -1,233 +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:        cfreader.c include file.
- *  
- * Version:     $Id: cfreader.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
- *
- * Author:      Alexandre Cassen, <acassen@linux-vs.org>
- *
- *              This program is distributed in the hope that it will be useful,
- *              but WITHOUT ANY WARRANTY; without even the implied warranty of
- *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *              See the GNU General Public License for more details.
- *
- *              This program is free software; you can redistribute it and/or
- *              modify it under the terms of the GNU General Public License
- *              as published by the Free Software Foundation; either version
- *              2 of the License, or (at your option) any later version.
- */
-
-
-#ifndef _CFREADER_H
-#define _CFREADER_H
-
-/* system includes */
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <syslog.h>
-#include <arpa/inet.h>
-#include <openssl/ssl.h>
-#ifdef _KRNL_2_2_
-  #include <linux/ip_masq.h>
-  #include <net/ip_masq.h>
-#else
-  #include <net/ip_vs.h>
-#endif
-
-/* local includes */
-#include "utils.h"
-#include "vrrp.h"
-
-#define CONFFILE "/etc/keepalived/keepalived.conf"
-
-#define TEMP_BUFFER_LENGTH 100
-#define MAX_EMAIL_LENGTH   45
-#define MAX_LVSID_LENGTH   20
-#define MAX_URL_LENGTH     110
-#define DIGEST_LENGTH      32+1
-#define MAX_TIMEOUT_LENGTH 5
-#define MAX_INT_LENGTH     10
-
-#define MAX_SSL_PASSWORD    48
-#define MAX_SSL_PATH        240
-
-#ifdef _KRNL_2_2_
-  #define SCHED_MAX_LENGTH IP_MASQ_TNAME_MAX
-#else
-  #define SCHED_MAX_LENGTH IP_VS_SCHEDNAME_MAXLEN
-#endif
-
-/* Keywords definition */
-struct keyword {
-  int key;
-  char *word;
-};
-
-/* configuration file keyword definition */
-#define KW_GLOBALDEFS  0
-#define KW_VS          1
-#define KW_SVR         2
-#define KW_SSVR                3
-#define KW_BEGINFLAG   4
-#define KW_ENDFLAG     5
-#define KW_DELAY       6
-#define KW_EMAIL       7
-#define KW_EMAILFROM   8
-#define KW_LVSID       9
-#define KW_SMTP                10
-#define KW_STIMEOUT    11
-#define KW_LBSCHED     12
-#define KW_LBKIND      13
-#define KW_NATMASK     14
-#define KW_PTIMEOUT    15
-#define KW_PROTOCOL    16
-#define KW_WEIGHT      17
-#define KW_URL         18
-#define KW_URLPATH     19
-#define KW_DIGEST      20
-#define KW_CTIMEOUT    21
-#define KW_NBGETRETRY  22
-#define KW_DELAYRETRY  23
-
-#define KW_ICMPCHECK   24
-#define KW_TCPCHECK    25
-#define KW_HTTPGET     26
-#define KW_SSLGET      27
-#define KW_LDAPGET     28
-#define KW_MISCCHECK    29
-#define KW_MISCPATH     30
-
-#define KW_VRRP                31
-#define KW_VRRPSTATE   32
-#define KW_VRRPINT     33
-#define KW_VRRPVRID    34
-#define KW_VRRPAUTH    35
-#define KW_VRRPAUTHTYPE        36
-#define KW_VRRPAUTHAH  37
-#define KW_VRRPAUTHPWD 38
-#define KW_VRRPAUTHPASS        39
-#define KW_VRRPPRIO    40
-#define KW_VRRPADVERT  41
-#define KW_VRRPIPADD   42
-#define KW_VRRPSYNC    43
-#define KW_VRRPPREEMPT 44
-
-#define KW_VRRPDEBUG    45
-#define KW_VRRPNOTIFY   46
-#define KW_FWMARK       47
-
-#define KW_SSLPASSWORD  48
-#define KW_SSLCAFILE    49
-#define KW_SSLKEYFILE   50
-#define KW_SSLCERTFILE  51
-#define KW_SSL          52
-
-#define KW_UNKNOWN     53
-
-#define KEEPALIVED_DEFAULT_DELAY 60
-
-/* Structure definition  */
-
-/* SSL common data */
-typedef struct _ssl_data SSL_DATA;
-typedef struct _ssl_data {
-  int        enable;
-  int        strong_check;
-  SSL_CTX    *ctx;
-  SSL_METHOD *meth;
-  char       password[MAX_SSL_PASSWORD];
-  char       cafile[MAX_SSL_PATH];
-  char       certfile[MAX_SSL_PATH];
-  char       keyfile[MAX_SSL_PATH];
-} ssl_data;
-
-typedef struct _urls {
-  char url[MAX_URL_LENGTH];
-  char digest[DIGEST_LENGTH];
-
-  struct urls *next;
-} urls;
-
-typedef struct _http_get_check {
-  int nb_get_retry;
-  int delay_before_retry;
-  urls *check_urls;
-} http_get_check;
-
-typedef struct _keepalive_check {
-  int type;
-#define ICMP_CHECK_ID  (1 << 0)
-#define TCP_CHECK_ID   (1 << 1)
-#define HTTP_GET_ID    (1 << 2)
-#define SSL_GET_ID     (1 << 3)
-#define LDAP_GET_ID    (1 << 4)
-#define MISC_CHECK_ID  (1 << 5)
-  int connection_to;
-  union {
-    http_get_check *http_get;
-    char *misc_check_path;
-  } u;
-} keepalive_check;
-
-typedef struct _real_server {
-  struct in_addr addr_ip;
-  uint16_t addr_port;
-  int weight;
-  keepalive_check *method;
-  int alive;
-
-  struct realserver *next;
-} realserver;
-
-typedef struct _virtual_server {
-  struct in_addr addr_ip;
-  uint32_t vfwmark;
-  uint16_t addr_port;
-  uint16_t service_type;
-  int delay_loop;
-  char sched[SCHED_MAX_LENGTH];
-  unsigned loadbalancing_kind;
-  struct in_addr nat_mask;
-  char timeout_persistence[MAX_TIMEOUT_LENGTH];
-  realserver *s_svr;
-  realserver *svr;
-
-  struct virtualserver *next;
-} virtualserver;
-
-typedef struct _vrrp_instance {
-  char iname[MAX_INT_LENGTH];  /* Instance Name */
-  char isync[MAX_INT_LENGTH];  /* Instance Name to synchronize with */
-  vrrp_rt *vsrv;               /* VRRP data */
-
-  struct vrrp_instance *next;
-} vrrp_instance;
-
-typedef struct _notification_email {
-  char addr[MAX_EMAIL_LENGTH];
-
-  struct notification_email *next;
-} notification_email;
-
-typedef struct _configuration_data {
-  char lvs_id[MAX_LVSID_LENGTH];
-  char email_from[MAX_EMAIL_LENGTH];
-  struct in_addr smtp_server;
-  int smtp_connection_to;
-  notification_email *email;
-  vrrp_instance *vrrp;
-  virtualserver *lvstopology;
-  ssl_data      *ssldata;
-} configuration_data;
-
-/* prototypes */
-extern configuration_data *conf_reader(char *conf_file);
-extern void clear_conf(configuration_data * lstptr);
-extern void clear_vrrp_instance(vrrp_instance *lstptr);
-extern void dump_conf(configuration_data * lstptr);
-
-#endif
diff --git a/check.h b/check.h
deleted file mode 100644 (file)
index 9fdec9b..0000000
--- a/check.h
+++ /dev/null
@@ -1,56 +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 arguments structures definitions.
- *
- * Version:     $Id: check.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
- *
- * Author:      Alexandre Cassen, <acassen@linux-vs.org>
- *
- *              This program is distributed in the hope that it will be useful,
- *              but WITHOUT ANY WARRANTY; without even the implied warranty of
- *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *              See the GNU General Public License for more details.
- *
- *              This program is free software; you can redistribute it and/or
- *              modify it under the terms of the GNU General Public License
- *              as published by the Free Software Foundation; either version
- *              2 of the License, or (at your option) any later version.
- */
-
-#ifndef _CHECK_H
-#define _CHECK_H
-
-/* system includes */
-#include <openssl/md5.h>
-#include <openssl/ssl.h>
-
-/* ssl specific thread arguments defs */
-typedef struct {
-  char *buffer;
-  char *extracted;
-  int   error;
-  int   len;
-  SSL   *ssl;
-  BIO   *bio;
-  MD5_CTX context;
-} REQ;
-
-/* http specific thread arguments defs */
-typedef struct _http_thread_arg {
-  int retry_it;                /* current number of get retry */
-  int url_it;                  /* current url checked index */
-  REQ *req;                    /* GET buffer and SSL args */
-} http_thread_arg;
-
-/* global thread arguments defs */
-typedef struct _thread_arg {
-  configuration_data *root;    /* pointer to the configuration root data */
-  virtualserver *vs;           /* pointer to the checker thread virtualserver */
-  realserver *svr;             /* pointer to the checker thread realserver */
-  void *checker_arg;           /* pointer to the specific checker arg */
-} thread_arg;
-
-#endif
diff --git a/check_api.c b/check_api.c
new file mode 100644 (file)
index 0000000..d7973aa
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * 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.5.3 2002/02/24 23:50:11 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 "check_misc.h"
+#include "check_tcp.h"
+#include "check_http.h"
+#include "check_ssl.h"
+
+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"
+                 , ip_ntoa(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);
+  }
+}
+
+/* Install checkers keywords */
+void install_checkers_keyword(void)
+{
+  install_misc_check_keyword();
+  install_tcp_check_keyword();
+  install_http_check_keyword();
+  install_ssl_check_keyword();
+}
diff --git a/check_api.h b/check_api.h
new file mode 100644 (file)
index 0000000..391f99d
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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 arguments structures definitions.
+ *
+ * Version:     $Id: check_api.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ *
+ * Author:      Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _CHECK_API_H
+#define _CHECK_API_H
+
+/* local includes */
+#include "data.h"
+#include "scheduler.h"
+
+/* 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;
+} checker;
+
+/* Checkers queue */
+list checkers_queue;
+
+/* utility macro */
+#define CHECKER_ARG(X) ((X)->data)
+#define CHECKER_DATA(X) (((checker *)X)->data)
+#define CHECKER_GET() (CHECKER_DATA(LIST_TAIL_DATA(checkers_queue)))
+#define CHECKER_VALUE_INT(X) (atoi(VECTOR_SLOT(X,1)))
+#define CHECKER_VALUE_STRING(X) (set_value(X))
+#define CHECKER_RIP(C)   (SVR_IP((C)->rs))
+#define CHECKER_RPORT(C) (SVR_PORT((C)->rs))
+
+/* Prototypes definition */
+extern void init_checkers_queue(void);
+extern void queue_checker(void (*free) (void *), void (*dump) (void *)
+                                        , int (*launch) (struct _thread *)
+                                        , void *data);
+extern void dump_checkers_queue(void);
+extern void free_checkers_queue(void);
+extern void register_checkers_thread(void);
+extern void install_checkers_keyword(void);
+
+#endif
index 2f4a182..0216f8a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        WEB CHECK. Common HTTP/SSL checker primitives.
  *
- * Version:     $Id: check_http.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: check_http.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Jan Holmberg, <jan@artech.net>
 #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");
+  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);
+}
+void http_get_handler(vector strvec)
+{
+  http_get_checker *http_get_chk;
+  char *str = VECTOR_SLOT(strvec, 0);
+
+  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(str, "HTTP_GET"))?PROTO_HTTP:PROTO_SSL;
+  http_get_chk->url   = alloc_list(free_url, dump_url);
+
+  /* queue new checker */
+  queue_checker(free_http_get_check, dump_http_get_check
+                                   , http_connect_thread
+                                   , http_get_chk);
+}
+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_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_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 :
  */
 int epilog(thread *thread, int metod, int t, int c)
 {
-  thread_arg *thread_arg = THREAD_ARG(thread);
-  http_thread_arg *checker_arg;
+  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;
-  REQ *req;
-  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-  req = checker_arg->req;
  
   if (metod) {
-    checker_arg->url_it   += t ? t : -checker_arg->url_it;
-    checker_arg->retry_it += c ? c : -checker_arg->retry_it;
+    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 = thread_arg->vs->delay_loop;
+        delay = checker->vs->delay_loop;
       else
-        delay = thread_arg->vs->delay_loop -
-                thread_arg->svr->method->u.http_get->delay_before_retry;
-      thread_add_timer(thread->master, http_connect_thread, thread_arg, delay);
+        delay = checker->vs->delay_loop - http_get_check->delay_before_retry;
+      thread_add_timer(thread->master, http_connect_thread
+                                     , checker
+                                     , delay);
       break; 
     case 2:
-      delay = thread_arg->svr->method->u.http_get->delay_before_retry;
-      thread_add_timer(thread->master, http_connect_thread, thread_arg, delay);
+      delay = http_get_check->delay_before_retry;
+      thread_add_timer(thread->master, http_connect_thread
+                                     , checker
+                                     , delay);
       break;
   }
 
   /* If req == NULL, fd is not created */
-  if (req != NULL) {
+  if (req) {
     if (req->ssl)
       SSL_free(req->ssl);
     if (req->buffer)
@@ -106,11 +234,9 @@ int epilog(thread *thread, int metod, int t, int c)
 
 int timeout_epilog(thread *thread, char *smtp_msg, char *debug_msg)
 {
-  thread_arg *thread_arg;
-  http_thread_arg *checker_arg;
-
-  thread_arg  = THREAD_ARG(thread);
-  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+  checker *checker                 = THREAD_ARG(thread);
+  http_get_checker *http_get_check = CHECKER_ARG(checker);
+  http_arg *http_arg               = HTTP_ARG(http_get_check);
 
   /*
    * The get retry implementation mean that we retry performing
@@ -118,27 +244,32 @@ int timeout_epilog(thread *thread, char *smtp_msg, char *debug_msg)
    * html buffer. This is sometime needed with some applications
    * servers.
    */
-  if (++checker_arg->retry_it <=
-      thread_arg->svr->method->u.http_get->nb_get_retry) {
+  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_ntoa(thread_arg->svr->addr_ip),
-                      ntohs(thread_arg->svr->addr_port),
-                      checker_arg->retry_it - 1);
+    syslog(LOG_DEBUG, "Retry %s server [%s:%d] after %d retry."
+                    , debug_msg
+                    , ip_ntoa(CHECKER_RIP(checker))
+                    , ntohs(CHECKER_RPORT(checker))
+                    , http_arg->retry_it - 1);
 #endif
     return epilog(thread,2,0,1);
+
   } else {
+
 #ifdef _DEBUG_
-    if (thread_arg->svr)
-      syslog(LOG_DEBUG, "Timeout %s server [%s:%d].", debug_msg,
-                          inet_ntoa(thread_arg->svr->addr_ip),
-                          ntohs(thread_arg->svr->addr_port));
+    if (checker->rs)
+      syslog(LOG_DEBUG, "Timeout %s server [%s:%d]."
+                      , debug_msg
+                      , ip_ntoa(CHECKER_RIP(checker))
+                      , ntohs(CHECKER_RPORT(checker)));
 #endif
     /* check if server is currently alive */
-    if (thread_arg->svr->alive) {
-      smtp_alert(thread->master, thread_arg->root, thread_arg->svr, "DOWN", smtp_msg);
-      perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+    if (ISALIVE(checker->rs)) {
+      smtp_alert(thread->master, checker->rs
+                               , "DOWN"
+                               , smtp_msg);
+      perform_svr_state(DOWN, checker->vs, checker->rs);
     }
 
     return epilog(thread,1,0,0);
@@ -151,7 +282,7 @@ int timeout_epilog(thread *thread, char *smtp_msg, char *debug_msg)
 /* simple function returning a pointer to the html buffer begin */
 char *extract_html(char *buffer, int size_buffer)
 {
-  char *end = buffer+size_buffer;
+  char *end = buffer + size_buffer;
 
   while ( buffer < end &&
           !(*buffer++ == '\n' &&
@@ -162,57 +293,42 @@ char *extract_html(char *buffer, int size_buffer)
 }
 
 /* return the url pointer of the current url iterator  */
-urls *fetch_next_url(thread_arg *thread_arg)
+url *fetch_next_url(http_get_checker *http_get_check)
 {
-  http_thread_arg *checker_arg;
-  int i = 0;
+  http_arg *http_arg = HTTP_ARG(http_get_check);
 
-  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-
-  /* fetch the next url */
-  for (i=0; i<checker_arg->url_it; i++)
-    thread_arg->svr->method->u.http_get->check_urls=(urls *)thread_arg->svr->method->u.http_get->check_urls->next;
-
-  if (thread_arg->svr->method->u.http_get->check_urls != NULL)
-    return thread_arg->svr->method->u.http_get->check_urls;
-
-  return NULL;
+  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)
+int http_handle_response(thread *thread, unsigned char digest[16]
+                                       , int empty_buffer)
 {
-  thread_arg *thread_arg;
-  http_thread_arg *checker_arg;
-  REQ *req;
+  checker *checker                 = THREAD_ARG(thread);
+  http_get_checker *http_get_check = CHECKER_ARG(checker);
+  http_arg *http_arg               = HTTP_ARG(http_get_check);
   int r, di = 0;
   unsigned char *digest_tmp;
-  urls *fetched_url;
-  urls *pointerurls;
-
-  thread_arg  = THREAD_ARG(thread);
-  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-  req         = checker_arg->req;
-
+  url *fetched_url;
   if (empty_buffer) {
-    return timeout_epilog(thread,
-      "=> CHECK failed on service : empty buffer received <=\n\n",
-      "Read, no data received from ");
+    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]);
 
-    pointerurls = thread_arg->svr->method->u.http_get->check_urls;
-    fetched_url = fetch_next_url(thread_arg);
-    thread_arg->svr->method->u.http_get->check_urls = pointerurls;
+    fetched_url = fetch_next_url(http_get_check);
 
 #ifdef _DEBUG_
-    syslog(LOG_DEBUG, "MD5SUM to [%s:%d] url(%d) = [%s].",
-                      inet_ntoa(thread_arg->svr->addr_ip),
-                      ntohs(thread_arg->svr->addr_port),
-                      checker_arg->url_it+1, digest_tmp);
+    syslog(LOG_DEBUG, "MD5SUM to [%s:%d] url(%d) = [%s]."
+                    , ip_ntoa(CHECKER_RIP(checker))
+                    , ntohs(CHECKER_RPORT(checker))
+                    , http_arg->url_it + 1
+                    , digest_tmp);
 #endif
 
     r = strcmp(fetched_url->digest, digest_tmp);
@@ -220,25 +336,29 @@ int http_handle_response(thread *thread, unsigned char digest[16], int empty_buf
 
     if (r) {
 #ifdef _DEBUG_
-      syslog(LOG_DEBUG, "MD5 digest error to [%s:%d] url(%d), expecting MD5SUM [%s].",
-                        inet_ntoa(thread_arg->svr->addr_ip),
-                        ntohs(thread_arg->svr->addr_port),
-                        checker_arg->url_it+1, fetched_url->digest);
+      syslog(LOG_DEBUG, "MD5 digest error to [%s:%d] url(%d)"
+                        ", expecting MD5SUM [%s]."
+                      , ip_ntoa(CHECKER_RIP(checker))
+                      , ntohs(CHECKER_RPORT(checker))
+                      , http_arg->url_it + 1
+                      , fetched_url->digest);
 #endif
 
       /* check if server is currently alive */
-      if (thread_arg->svr->alive) {
-        smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                   "DOWN", "=> CHECK failed on service : MD5 digest mismatch <=\n\n");
-        perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+      if (ISALIVE(checker->rs)) {
+        smtp_alert(thread->master, checker->rs
+                                 , "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_ntoa(thread_arg->svr->addr_ip),
-                        ntohs(thread_arg->svr->addr_port),
-                        checker_arg->url_it+1);
+      syslog(LOG_DEBUG, "MD5 digest success to [%s:%d] url(%d)."
+                      , ip_ntoa(CHECKER_RIP(checker))
+                      , ntohs(CHECKER_RPORT(checker))
+                      , http_arg->url_it + 1);
 #endif
       return epilog(thread,2,1,0)+1;
     }
@@ -249,25 +369,22 @@ int http_handle_response(thread *thread, unsigned char digest[16], int empty_buf
 /* Asynchronous HTTP stream reader */
 int http_read_thread(thread *thread)
 {
-  thread_arg *thread_arg;
-  http_thread_arg *checker_arg;
+  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];
-  REQ *req;
   int r = 0;
 
-  thread_arg  = THREAD_ARG(thread);
-  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-  req         = checker_arg->req;
-
   /* Handle read timeout */
-  if (thread->type == THREAD_READ_TIMEOUT) {
-    return timeout_epilog(thread,
-      "=> HTTP CHECK failed on service : recevice data <=\n\n",
-      "HTTP read");
-  }
+  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);
+  r = read(thread->u.fd, req->buffer + req->len
+                       , MAX_BUFFER_LENGTH - req->len);
 
   if (r == -1 || r == 0) { /* -1:error , 0:EOF */
 
@@ -276,10 +393,12 @@ int http_read_thread(thread *thread)
 
     if (r == -1) {
       /* We have encourred a real read error */
-      if (thread_arg->svr->alive) {
-        smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                   "DOWN", "=> HTTP CHECK failed on service : cannot receive data <=\n\n");
-        perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+      if (ISALIVE(checker->rs)) {
+        smtp_alert(thread->master, checker->rs
+                                 , "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);
     }
@@ -317,8 +436,10 @@ int http_read_thread(thread *thread)
      * Register next http stream reader.
      * Register itself to not perturbe global I/O multiplexer.
      */
-    thread_add_read(thread->master, http_read_thread, thread_arg, thread->u.fd,
-                    thread_arg->svr->method->connection_to);
+    thread_add_read(thread->master, http_read_thread
+                                  , checker
+                                  , thread->u.fd
+                                  , http_get_check->connection_to);
   }
 
   return 0;
@@ -330,20 +451,16 @@ int http_read_thread(thread *thread)
  */
 int http_response_thread(thread *thread)
 {
-  thread_arg *thread_arg;
-  http_thread_arg *checker_arg;
-  REQ *req;
-
-  thread_arg  = THREAD_ARG(thread);
-  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-  req         = checker_arg->req;
+  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");
-  }
+  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);
@@ -353,58 +470,55 @@ int http_response_thread(thread *thread)
   MD5_Init(&req->context);
 
   /* Register asynchronous http/ssl read thread */
-  if (thread_arg->svr->method->type == SSL_GET_ID)
-    thread_add_read(thread->master, ssl_read_thread, thread_arg, thread->u.fd,
-                    thread_arg->svr->method->connection_to);
+  if (http_get_check->proto == PROTO_SSL)
+    thread_add_event(thread->master, ssl_read_thread
+                                   , checker
+                                   , 0);
   else
-    thread_add_read(thread->master, http_read_thread, thread_arg, thread->u.fd,
-                    thread_arg->svr->method->connection_to);
+    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)
 {
-  thread_arg *thread_arg;
-  http_thread_arg *checker_arg;
-  char    *str_request;
-  urls    *fetched_url;
-  urls    *pointerurls;
-  REQ     *req;
+  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);
+  char *str_request;
+  url *fetched_url;
   int ret = 0;
 
-  thread_arg  = THREAD_ARG(thread);
-  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-  req         = checker_arg->req;
-
   /* Handle read timeout */
-  if(thread->type == THREAD_WRITE_TIMEOUT) {
-    return timeout_epilog(thread,
-      "=> CHECK failed on service : read timeout <=\n\n",
-      "Web 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);
 
-  pointerurls = thread_arg->svr->method->u.http_get->check_urls;
-  fetched_url = fetch_next_url(thread_arg);
-  thread_arg->svr->method->u.http_get->check_urls = pointerurls;
+  fetched_url = fetch_next_url(http_get_check);
 
   snprintf(str_request, GET_REQUEST_BUFFER_LENGTH
-                      , REQUEST_TEMPLATE, fetched_url->url
-                      , inet_ntoa(thread_arg->svr->addr_ip)
-                      , ntohs(thread_arg->svr->addr_port));
+                      , REQUEST_TEMPLATE
+                      , fetched_url->path
+                      , ip_ntoa(CHECKER_RIP(checker))
+                      , ntohs(CHECKER_RPORT(checker)));
 
 #ifdef _DEBUG_
-  syslog(LOG_DEBUG, "Processing url(%d) of [%s:%d].",
-                    checker_arg->url_it+1,
-                    inet_ntoa(thread_arg->svr->addr_ip),
-                    ntohs(thread_arg->svr->addr_port));
+  syslog(LOG_DEBUG, "Processing url(%d) of [%s:%d]."
+                  , http_arg->url_it + 1
+                  , ip_ntoa(CHECKER_RIP(checker))
+                  , ntohs(CHECKER_RPORT(checker)));
 #endif
 
   /* Send the GET request to remote Web server */
-  if (thread_arg->svr->method->type == SSL_GET_ID)
+  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;
@@ -412,84 +526,90 @@ int http_request_thread(thread *thread)
   FREE(str_request);
 
   if (!ret) {
-    syslog(LOG_WARNING, "Cannot send get request to [%s:%d].",
-                        inet_ntoa(thread_arg->svr->addr_ip),
-                        ntohs(thread_arg->svr->addr_port));
+    syslog(LOG_INFO, "Cannot send get request to [%s:%d]."
+                   , ip_ntoa(CHECKER_RIP(checker))
+                   , ntohs(CHECKER_RPORT(checker)));
 
     /* check if server is currently alive */
-    if (thread_arg->svr->alive) {
-      smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                 "DOWN", "=> CHECK failed on service : cannot send data <=\n\n");
-      perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+    if (ISALIVE(checker->rs)) {
+      smtp_alert(thread->master, checker->rs
+                               , "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, thread_arg, thread->u.fd,
-                  thread_arg->svr->method->connection_to);
+  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)
 {
-  thread_arg *thread_arg;
-  http_thread_arg *checker_arg;
-  REQ *req;
+  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 ret = 1;
-
   int status;
 
-  thread_arg  = THREAD_ARG(thread);
-  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-  req         = checker_arg->req;
-
-  status = tcp_socket_state(thread->u.fd, thread, http_check_thread);
-
+  status = tcp_socket_state(thread->u.fd, thread
+                                        , CHECKER_RIP(checker)
+                                        , CHECKER_RPORT(checker)
+                                        , http_check_thread);
   switch (status) {
     case connect_error:
 #ifdef _DEBUG_
-      syslog(LOG_DEBUG,"Error connecting server [%s:%d].",
-                       inet_ntoa(thread_arg->svr->addr_ip),
-                       ntohs(thread_arg->svr->addr_port));
+      syslog(LOG_DEBUG, "Error connecting server [%s:%d]."
+                      , ip_ntoa(CHECKER_RIP(checker))
+                      , ntohs(CHECKER_RPORT(checker)));
 #endif
       /* check if server is currently alive */
-      if (thread_arg->svr->alive) {
-        smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                   "DOWN", "=> CHECK failed on service : connection error <=\n\n");
-        perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+      if (ISALIVE(checker->rs)) {
+        smtp_alert(thread->master, checker->rs
+                                 , "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");
+      return timeout_epilog(thread, "==> CHECK failed on service"
+                                    " : connection timeout <=\n\n"
+                                  , "connect, timeout");
       break;
 
     case connect_success: {
-      if (thread_arg->svr->method->type == SSL_GET_ID)
+      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_ntoa(thread_arg->svr->addr_ip),
-                          ntohs(thread_arg->svr->addr_port));
+        syslog(LOG_DEBUG, "Remote Web server [%s:%d] connected."
+                        , ip_ntoa(CHECKER_RIP(checker))
+                        , ntohs(CHECKER_RPORT(checker)));
 #endif
-        thread_add_write(thread->master, http_request_thread, thread_arg, thread->u.fd,
-                         thread_arg->svr->method->connection_to);
+        thread_add_write(thread->master, http_request_thread
+                                       , checker
+                                       , thread->u.fd
+                                       , http_get_check->connection_to);
       } else {
 #ifdef _DEBUG_
-        syslog(LOG_DEBUG, "Connection problem host: [%s:%d].",
-                          inet_ntoa(thread_arg->svr->addr_ip),
-                          ntohs(thread_arg->svr->addr_port));
-        if (thread_arg->svr->method->type == SSL_GET_ID)
+        syslog(LOG_DEBUG, "Connection trouble to: [%s:%d]."
+                        , ip_ntoa(CHECKER_RIP(checker))
+                        , ntohs(CHECKER_RPORT(checker)));
+        if (http_get_check->proto == PROTO_SSL)
           ssl_printerr(SSL_get_error(req->ssl, ret));
 #endif
         return epilog(thread,1,0,0);
@@ -503,41 +623,39 @@ int http_check_thread(thread *thread)
 
 int http_connect_thread(thread *thread)
 {
-  thread_arg *thread_arg;
-  http_thread_arg *checker_arg;
-  urls *fetched_url;
-  urls *pointerurls;
+  checker *checker                 = THREAD_ARG(thread);
+  http_get_checker *http_get_check = CHECKER_ARG(checker);
+  http_arg *http_arg               = HTTP_ARG(http_get_check);
+  url *fetched_url;
   enum connect_result status;
+  uint16_t addr_port;
   int fd;
 
-  thread_arg  = THREAD_ARG(thread);
-  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-
   /* Find eventual url end */
-  pointerurls = thread_arg->svr->method->u.http_get->check_urls;
-  fetched_url = fetch_next_url(thread_arg);
-  thread_arg->svr->method->u.http_get->check_urls = pointerurls;
-  if (fetched_url == NULL) {
+  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 (!thread_arg->svr->alive) {
-      smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                 "UP", "=> CHECK succeed on service <=\n\n");
-      perform_svr_state(UP, thread_arg->vs, thread_arg->svr);
+    if (!ISALIVE(checker->rs)) {
+      smtp_alert(thread->master, checker->rs
+                               , "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_ntoa(thread_arg->svr->addr_ip)
-                      , ntohs(thread_arg->svr->addr_port));
+                      , ip_ntoa(CHECKER_RIP(checker))
+                      , ntohs(CHECKER_RPORT(checker)));
 #endif
     }
-    checker_arg->req = NULL;
+    http_arg->req = NULL;
     return epilog(thread,1,0,0)+1;
   }
 
   /* Allocate & clean request struct */
-  checker_arg->req = (REQ *)MALLOC(sizeof(REQ));
+  http_arg->req = (REQ *)MALLOC(sizeof(REQ));
 
   if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
 #ifdef _DEBUG_
@@ -546,10 +664,21 @@ int http_connect_thread(thread *thread)
     return 0;
   }
 
-  status = tcp_connect(fd, thread_arg->svr->addr_ip.s_addr, thread_arg->svr->addr_port);
+  /*
+   *  Set the remote connection port.
+   *  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);
 
-  /* handle tcp connection status & register check worker thread */
-  tcp_connection_state(fd, status, thread, http_check_thread);
+  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;
 }
index 5ad27bc..34ae5c2 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_http.c include file.
  *
- * Version:     $Id: check_http.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: check_http.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Jan Holmberg, <jan@artech.net>
 #ifndef _HTTP_H
 #define _HTTP_H
 
+/* system includes */
+#include <stdio.h>
+#include <openssl/md5.h>
+#include <openssl/ssl.h>
+
 /* local includes */
-#include "cfreader.h"
+#include "data.h"
 #include "ipwrapper.h"
 #include "scheduler.h"
 #include "layer4.h"
+#include "list.h"
+
+/* 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;
+} 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 */
+} http_arg;
+
+typedef struct _url {
+  char *path;
+  char *digest;
+} url;
+typedef struct _http_get_checker {
+  int      proto;
+  int      connection_to;
+  int      nb_get_retry;
+  int      delay_before_retry;
+  list     url;
+  http_arg *arg;
+} http_get_checker;
 
 /* global defs */
 #define MD5_BUFFER_LENGTH 32
 #define GET_REQUEST_BUFFER_LENGTH 128
 #define GET_BUFFER_LENGTH 2048
 #define MAX_BUFFER_LENGTH 4096
+#define PROTO_HTTP     0x01
+#define PROTO_SSL      0x02
 
-/* http get processing command */
+/* GET processing command */
 #define REQUEST_TEMPLATE "GET %s HTTP/1.0\r\n" \
                          "User-Agent:KeepAliveClient\r\n" \
                          "Host: %s:%d\r\n\r\n"
 
+/* macro utility */
+#define HTTP_ARG(X) ((X)->arg)
+#define HTTP_REQ(X) ((X)->req)
+
 /* 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 char *extract_html(char *buffer, int size_buffer);
-extern urls *fetch_next_url(thread_arg *thread_arg);
+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 void smtp_alert(thread_master *
-                       , configuration_data *
-                       , realserver *
-                       , const char *
-                       , const char *);
-
 #endif
index d37d0c0..c13ca46 100644 (file)
@@ -6,7 +6,7 @@
  * Part:        MISC CHECK. Perform a system call to run an extra
  *              system prog or script.
  *
- * Version:     $Id: check_misc.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: check_misc.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
  */
 
 #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();
+}
 
-/* does this need to be threaded? */
 int misc_check_call(char* cmdline)
 {
   int retval;
@@ -33,10 +81,10 @@ int misc_check_call(char* cmdline)
 
   if (retval == 127) {
     /* couldn't exec command */
-    syslog(LOG_DEBUG,"Couldn't exec command: %s", cmdline);
+    syslog(LOG_DEBUG, "Couldn't exec command: %s", cmdline);
   } else if (retval == -1) {
     /* other error */
-    syslog(LOG_DEBUG,"Error exec-ing command: %s", cmdline);
+    syslog(LOG_DEBUG, "Error exec-ing command: %s", cmdline);
   } else {
     /* everything is good */
     syslog(LOG_DEBUG, "Successfully exec command: %s retval is %d"
@@ -48,27 +96,42 @@ int misc_check_call(char* cmdline)
 
 int misc_check_thread(thread *thread)
 {
-  thread_arg *thread_arg;
+  checker *checker;
+  misc_checker *misc_chk;
   int status;
 
-  thread_arg = THREAD_ARG(thread);
+  checker  = THREAD_ARG(thread);
+  misc_chk = CHECKER_ARG(checker);
 
-  status = misc_check_call(thread_arg->svr->method->u.misc_check_path);
+  /* Register next timer checker */
+  thread_add_timer(thread->master, misc_check_thread
+                                 , checker
+                                 , checker->vs->delay_loop);
 
-  if (status == 0) {
-    /* everything is good */
-    if (!thread_arg->svr->alive) {
-      perform_svr_state(UP, thread_arg->vs, thread_arg->svr);
+  /* 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
+                                 , "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
+                                 , "DOWN"
+                                 , "=> MISC CHECK failed on service <=\n\n");
+        perform_svr_state(DOWN, checker->vs, checker->rs);
+      }
     }
-  } else {
-   if (thread_arg->svr->alive) {
-     perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
-   }
   }
 
-  /* Register next timer checker */
-  thread_add_timer(thread->master, misc_check_thread, thread_arg,
-  thread_arg->vs->delay_loop);
-
-  return 0;
+  exit(0);
 }
index 076f60c..3ed9970 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_misc.c include file.
  *
- * Version:     $Id: check_misc.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: check_misc.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
 #include <stdlib.h>
 
 /* local includes */
-#include "cfreader.h"
-#include "ipwrapper.h"
 #include "scheduler.h"
-#include "smtp.h"
+
+/* Checker argument structure  */
+typedef struct _misc_checker {
+  char *path;
+} misc_checker;
 
 /* Prototypes defs */
-extern int misc_check_thread(thread *thread);
+extern void install_misc_check_keyword(void);
 
 #endif
index 7e2bba0..c0812c1 100644 (file)
@@ -7,7 +7,7 @@
  *              url, compute a MD5 over this result and match it to the
  *              expected value.
  *
- * Version:     $Id: check_ssl.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: check_ssl.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Jan Holmberg, <jan@artech.net>
 
 #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 */
@@ -50,71 +56,84 @@ static int password_cb(char *buf, int num, int rwflag, void *userdata)
 
 /* Inititalize global SSL context */
 static BIO *bio_err = 0;
-static SSL_DATA *build_ssl_ctx(SSL_DATA *ssl)
+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 (!ssl)
+  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 (strlen(ssl->keyfile) > 0)
-    if (!(SSL_CTX_use_certificate_chain_file(ssl->ctx, ssl->keyfile))) {
+  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 NULL;
+      return 0;
     }
 
   /* Handle password callback using userdata ssl */
-  if (strlen(ssl->password) > 0) {
-    SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, 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 (strlen(ssl->keyfile) > 0)
-    if (!(SSL_CTX_use_PrivateKey_file(ssl->ctx, ssl->keyfile, SSL_FILETYPE_PEM))) {
+  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 NULL;
+      return 0;
     }
 
   /* Load the CAs we trust */
-  if (strlen(ssl->cafile) > 0)
-    if (!(SSL_CTX_load_verify_locations(ssl->ctx, ssl->cafile, 0))) {
+  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 NULL;
+      return 0;
     }
 
+end:
 #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
-  SSL_CTX_set_verify_depth(ssl->ctx,1);
+  SSL_CTX_set_verify_depth(ssl->ctx, 1);
 #endif
 
-  return ssl;
+  return 1;
 }
 
 /*
  * Initialize the SSL context, with or without specific
  * configuration files.
  */
-SSL_DATA *init_ssl_ctx(SSL_DATA *ssl)
+int init_ssl_ctx(void)
 {
-  if (!(ssl = build_ssl_ctx(ssl))) {
+  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 NULL;
+    return 0;
   }
-
-  return ssl;
+  return 1;
 }
 
 /* Display SSL error to readable string */
@@ -157,15 +176,12 @@ int ssl_printerr(int err)
 
 int ssl_connect(thread *thread)
 {
-  thread_arg *thread_arg;
-  http_thread_arg *checker_arg;
-  REQ *req;
-
-  thread_arg  = THREAD_ARG(thread);
-  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-  req         = checker_arg->req;
+  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(thread_arg->root->ssldata->ctx);
+  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);
 
@@ -187,32 +203,30 @@ int ssl_send_request(SSL *ssl, char *str_request, int request_len)
     err++;
     break;
   }
+
   return (err == 3)?1:0;
 }
 
 /* Asynchronous SSL stream reader */
 int ssl_read_thread(thread *thread)
 {
-  thread_arg *thread_arg;
-  http_thread_arg *checker_arg;
+  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];
-  REQ *req;
   int r = 0;
 
-  thread_arg  = THREAD_ARG(thread);
-  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-  req         = checker_arg->req;
-
   /* Handle read timeout */
-  if (thread->type == THREAD_READ_TIMEOUT) {
-    return timeout_epilog(thread,
-      "=> SSL CHECK failed on service : recevice data <=\n\n",
-      "SSL read");
-  }
+  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);
+  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) {
@@ -223,12 +237,14 @@ int ssl_read_thread(thread *thread)
 
     r = (req->error == SSL_ERROR_ZERO_RETURN) ? SSL_shutdown(req->ssl) : 0;
 
-    if (r) {
+    if (r && !req->extracted) {
       /* check if server is currently alive */
-      if (thread_arg->svr->alive) {
-        smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                   "DOWN", "=> SSL CHECK failed on service : cannot receive data <=\n\n");
-        perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+      if (ISALIVE(checker->rs)) {
+        smtp_alert(thread->master, checker->rs
+                                 , "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);
     }
@@ -266,8 +282,10 @@ int ssl_read_thread(thread *thread)
      * Register next ssl stream reader.
      * Register itself to not perturbe global I/O multiplexer.
      */
-    thread_add_read(thread->master, ssl_read_thread, thread_arg, thread->u.fd,
-                    thread_arg->svr->method->connection_to);
+    thread_add_read(thread->master, ssl_read_thread
+                                  , checker
+                                  , thread->u.fd
+                                  , http_get_check->connection_to);
   }
 
   return 0;
index 45da9bf..d302fe3 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_http.c include file.
  *
- * Version:     $Id: check_http.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: check_http.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Jan Holmberg, <jan@artech.net>
@@ -28,7 +28,8 @@
 #include "check_http.h"
 
 /* Prototypes */
-extern SSL_DATA *init_ssl_ctx(SSL_DATA *ssl);
+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 int ssl_printerr(int err);
index 898b922..f97521a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        TCP checker.
  *
- * Version:     $Id: check_tcp.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: check_tcp.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
  */
 
 #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");
+  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_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_timeout", &connect_timeout_handler);
+  install_sublevel_end();
+}
 
 int tcp_check_thread(thread *thread)
 {
-  thread_arg *thread_arg;
+  checker *checker;
   int status;
 
-  thread_arg = THREAD_ARG(thread);
+  checker = THREAD_ARG(thread);
 
-  status = tcp_socket_state(thread->u.fd, thread, tcp_check_thread);
+  status = tcp_socket_state(thread->u.fd, thread
+                                        , CHECKER_RIP(checker)
+                                        , CHECKER_RPORT(checker)
+                                        , tcp_check_thread);
 
   /* If status = connect_success, TCP connection to remote host is established.
    * Otherwise we have a real connection error or connection timeout.
@@ -37,48 +87,52 @@ int tcp_check_thread(thread *thread)
   if (status == connect_success) {
 
 #ifdef _DEBUG_
-    syslog(LOG_DEBUG, "TCP connection to [%s:%d] success.",
-                      inet_ntoa(thread_arg->svr->addr_ip),
-                      ntohs(thread_arg->svr->addr_port));
+    syslog(LOG_DEBUG, "TCP connection to [%s:%d] success."
+                    ,  ip_ntoa(CHECKER_RIP(checker))
+                    ,  ntohs(CHECKER_RPORT(checker)));
 #endif
     close(thread->u.fd);
 
-    if (!thread_arg->svr->alive) {
-      smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                 "UP", "=> TCP CHECK succeed on service <=\n\n");
-      perform_svr_state(UP, thread_arg->vs, thread_arg->svr);
+    if (!ISALIVE(checker->rs)) {
+      smtp_alert(thread->master, checker->rs
+                               , "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_ntoa(thread_arg->svr->addr_ip),
-                      ntohs(thread_arg->svr->addr_port));
+    syslog(LOG_DEBUG, "TCP connection to [%s:%d] failed !!!"
+                    ,  ip_ntoa(CHECKER_RIP(checker))
+                    ,  ntohs(CHECKER_RPORT(checker)));
 #endif
 
-    if (thread_arg->svr->alive) {
-      smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                 "DOWN", "=> TCP CHECK failed on service <=\n\n");
-      perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+    if (ISALIVE(checker->rs)) {
+      smtp_alert(thread->master, checker->rs
+                               , "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, thread_arg,
-                     thread_arg->vs->delay_loop);
-
+    thread_add_timer(thread->master, tcp_connect_thread
+                                   , checker
+                                   , checker->vs->delay_loop);
   return 0;
 }
 
 int tcp_connect_thread(thread *thread)
 {
-  thread_arg *thread_arg;
+  checker *checker;
+  tcp_checker *tcp_check;
   int fd;
   int status;
 
-  thread_arg = THREAD_ARG(thread);
+  checker   = THREAD_ARG(thread);
+  tcp_check = CHECKER_ARG(checker);
 
   if ( (fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
 #ifdef _DEBUG_
@@ -87,10 +141,12 @@ int tcp_connect_thread(thread *thread)
     return 0;
   }
 
-  status = tcp_connect(fd, thread_arg->svr->addr_ip.s_addr, thread_arg->svr->addr_port);
+  status = tcp_connect(fd, CHECKER_RIP(checker)
+                         , CHECKER_RPORT(checker));
 
   /* handle tcp connection status & register check worker thread */
-  tcp_connection_state(fd, status, thread, tcp_check_thread);
-
+  tcp_connection_state(fd, status, thread
+                                 , tcp_check_thread
+                                 , tcp_check->connection_to);
   return 0;
 }
index a1d8ac5..2a251c0 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_tcp.c include file.
  *
- * Version:     $Id: check_tcp.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: check_tcp.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include <arpa/inet.h>
 
 /* local includes */
-#include "cfreader.h"
-#include "ipwrapper.h"
 #include "scheduler.h"
-#include "layer4.h"
-#include "smtp.h"
+
+/* Checker argument structure  */
+typedef struct _tcp_checker {
+  int connection_to;
+} tcp_checker;
+
 
 /* Prototypes defs */
-extern int tcp_connect_thread(thread *thread);
+extern void install_tcp_check_keyword(void);
 
 #endif
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..20b219e
--- /dev/null
+++ b/configure
@@ -0,0 +1,1844 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  case "$ac_option" in
+  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case "$ac_option" in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir="$ac_optarg" ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build="$ac_optarg" ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file="$ac_optarg" ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix="$ac_optarg" ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he)
+    # Omit some internal or obsolete options to make the list less imposing.
+    # This message is too long to be a string in the A/UX 3.1 sh.
+    cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --bindir=DIR            user executables in DIR [EPREFIX/bin]
+  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
+  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
+  --datadir=DIR           read-only architecture-independent data in DIR
+                          [PREFIX/share]
+  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
+                          [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
+  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
+  --includedir=DIR        C header files in DIR [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
+  --infodir=DIR           info documentation in DIR [PREFIX/info]
+  --mandir=DIR            man documentation in DIR [PREFIX/man]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --program-prefix=PREFIX prepend PREFIX to installed program names
+  --program-suffix=SUFFIX append SUFFIX to installed program names
+  --program-transform-name=PROGRAM
+                          run sed PROGRAM on installed program names
+EOF
+    cat << EOF
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+EOF
+    if test -n "$ac_help"; then
+      echo "--enable and --with options recognized:$ac_help"
+    fi
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$ac_optarg" ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir="$ac_optarg" ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir="$ac_optarg" ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir="$ac_optarg" ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir="$ac_optarg" ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir="$ac_optarg" ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir="$ac_optarg" ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir="$ac_optarg" ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix="$ac_optarg" ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix="$ac_optarg" ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix="$ac_optarg" ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name="$ac_optarg" ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir="$ac_optarg" ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir="$ac_optarg" ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site="$ac_optarg" ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir="$ac_optarg" ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir="$ac_optarg" ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.13"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval "with_${ac_package}=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes="$ac_optarg" ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries="$ac_optarg" ;;
+
+  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *)
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+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=parser.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    echo "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='       '
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+# 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:529: 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
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="gcc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+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:559: 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
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_prog_rejected=no
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+        ac_prog_rejected=yes
+       continue
+      fi
+      ac_cv_prog_CC="cc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# -gt 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    set dummy "$ac_dir/$ac_word" "$@"
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  if test -z "$CC"; then
+    case "`uname -s`" in
+    *win32* | *WIN32*)
+      # 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:610: 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
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="cl"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+ ;;
+    esac
+  fi
+  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:642: 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.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 653 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:658: \"$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
+    ac_cv_prog_cc_cross=no
+  else
+    ac_cv_prog_cc_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+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:684: 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:689: 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
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:698: \"$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
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+
+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:717: 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
+  echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+  ac_cv_prog_cc_g=yes
+else
+  ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# 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:779: 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
+else
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS=":"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+         if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         else
+           ac_cv_path_install="$ac_dir/$ac_prog -c"
+           break 2
+         fi
+       fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL="$ac_cv_path_install"
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL="$ac_install_sh"
+  fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+KERNEL_VERSION=`uname -r`
+modprobe ip_vs
+if test -f /proc/net/ip_vs; then
+  IPVS_VERSION=`cat /proc/net/ip_vs | head -1 | awk '{ print $5}'`
+else
+  echo
+  echo "!!!WARN!!! Your kernel need to be patched with LVS code !!!WARN!!!"
+  echo
+  exit 1
+fi
+VERSION=`cat VERSION`
+
+echo $ac_n "checking for main in -lcrypto""... $ac_c" 1>&6
+echo "configure:845: checking for main in -lcrypto" >&5
+ac_lib_var=`echo crypto'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lcrypto  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 853 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:860: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo crypto | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lcrypto $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for main in -lpopt""... $ac_c" 1>&6
+echo "configure:888: checking for main in -lpopt" >&5
+ac_lib_var=`echo popt'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lpopt  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 896 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:903: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo popt | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lpopt $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for main in -lssl""... $ac_c" 1>&6
+echo "configure:931: checking for main in -lssl" >&5
+ac_lib_var=`echo ssl'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lssl  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 939 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:946: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo ssl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lssl $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+KERNEL_CODE=`echo $KERNEL_VERSION | cut -d'.' -f2`
+if test "${KERNEL_CODE}" = "2"; then
+  LDFLAGS = ${LIBS} libipfwc/libipfwc.a
+  LIBOBJS = ${LIBOBJS} ipfwwrapper.o
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:981: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    # This must be in double quotes, not single quotes, because CPP may get
+  # substituted into the Makefile and "${CC-cc}" will confuse make.
+  CPP="${CC-cc} -E"
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp.
+  cat > conftest.$ac_ext <<EOF
+#line 996 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1002: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -E -traditional-cpp"
+  cat > conftest.$ac_ext <<EOF
+#line 1013 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1019: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -nologo -E"
+  cat > conftest.$ac_ext <<EOF
+#line 1030 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1036: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+  ac_cv_prog_CPP="$CPP"
+fi
+  CPP="$ac_cv_prog_CPP"
+else
+  ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1061: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1066 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1074: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  ac_cv_header_stdc=yes
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+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 1091 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+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 1109 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+  :
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1130 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1141: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  :
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+  cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
+echo "configure:1165: checking for sys/wait.h that is POSIX.1 compatible" >&5
+if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1170 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+int main() {
+int s;
+wait (&s);
+s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+; return 0; }
+EOF
+if { (eval echo configure:1186: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_header_sys_wait_h=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_sys_wait_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
+if test $ac_cv_header_sys_wait_h = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_SYS_WAIT_H 1
+EOF
+
+fi
+
+for ac_hdr in fcntl.h sys/ioctl.h sys/time.h syslog.h unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1210: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1215 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1220: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:1248: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1253 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this.  */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this.  */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this.  */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+   It does not let you subtract one const X* pointer from another in an arm
+   of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this.  */
+  char *t;
+  char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+  *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+  int x[] = {25, 17};
+  const int *foo = &x[0];
+  ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+  typedef const int *iptr;
+  iptr p = 0;
+  ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+     "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+  struct s { int j; const int *ap[3]; };
+  struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+  const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:1302: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_c_const=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+  cat >> confdefs.h <<\EOF
+#define const 
+EOF
+
+fi
+
+echo $ac_n "checking for pid_t""... $ac_c" 1>&6
+echo "configure:1323: checking for pid_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1328 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_pid_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_pid_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_pid_t" 1>&6
+if test $ac_cv_type_pid_t = no; then
+  cat >> confdefs.h <<\EOF
+#define pid_t int
+EOF
+
+fi
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:1356: checking whether time.h and sys/time.h may both be included" >&5
+if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1361 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:1370: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_header_time=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_time=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+  cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+
+if test $ac_cv_prog_gcc = yes; then
+    echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
+echo "configure:1393: checking whether ${CC-cc} needs -traditional" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    ac_pattern="Autoconf.*'x'"
+  cat > conftest.$ac_ext <<EOF
+#line 1399 "configure"
+#include "confdefs.h"
+#include <sgtty.h>
+Autoconf TIOCGETP
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "$ac_pattern" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_prog_gcc_traditional=yes
+else
+  rm -rf conftest*
+  ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+  if test $ac_cv_prog_gcc_traditional = no; then
+    cat > conftest.$ac_ext <<EOF
+#line 1417 "configure"
+#include "confdefs.h"
+#include <termio.h>
+Autoconf TCGETA
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "$ac_pattern" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+  fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6
+  if test $ac_cv_prog_gcc_traditional = yes; then
+    CC="$CC -traditional"
+  fi
+fi
+
+echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
+echo "configure:1439: checking for 8-bit clean memcmp" >&5
+if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_memcmp_clean=no
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1447 "configure"
+#include "confdefs.h"
+
+main()
+{
+  char c0 = 0x40, c1 = 0x80, c2 = 0x81;
+  exit(memcmp(&c0, &c2, 1) < 0 && memcmp(&c1, &c2, 1) < 0 ? 0 : 1);
+}
+
+EOF
+if { (eval echo configure:1457: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_func_memcmp_clean=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_func_memcmp_clean=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6
+test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
+
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:1475: checking return type of signal handlers" >&5
+if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1480 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int main() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:1497: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_type_signal=void
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_type_signal=int
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_type_signal" 1>&6
+cat >> confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+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:1518: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1523 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1546: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[        ]*VPATH[        ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[    `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version 2.13"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+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
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@CPP@%$CPP%g
+s%@LIBOBJS@%$LIBOBJS%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile genhash/Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+  case "$ac_given_INSTALL" in
+  [/$]*) INSTALL="$ac_given_INSTALL" ;;
+  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+  esac
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+
+cat <<EOF;
+
+Keepalived configuration
+------------------------
+Keepalived version   : ${VERSION}
+Linux Kernel release : ${KERNEL_VERSION}
+IPVS version code    : ${IPVS_VERSION}
+Compiler             : ${CC}
+Compiler flags       : ${CFLAGS}
+
+EOF
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..3cbcc73
--- /dev/null
@@ -0,0 +1,72 @@
+#
+# Keepalived OpenSource project.
+#
+# Configuration template file for keepalived.
+# autoconf will generate & check deps for proper compilation
+#
+# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
+
+dnl ----[ Process this file with autoconf to produce a configure script ]----
+AC_INIT(cfreader.c)
+
+dnl ----[ Checks for programs ]----
+AC_PROG_CC
+AC_PROG_INSTALL
+
+dnl ----[ Checks for kernel support ]----
+KERNEL_VERSION=`uname -r`
+modprobe ip_vs
+if test -f /proc/net/ip_vs; then
+  IPVS_VERSION=`cat /proc/net/ip_vs | head -1 | awk '{ print $5}'`
+else
+  echo
+  echo "!!!WARN!!! Your kernel need to be patched with LVS code !!!WARN!!!"
+  echo
+  exit 1
+fi
+VERSION=`cat VERSION`
+
+dnl ----[ Checks for libraries ]----
+dnl Replace `main' with a function in -lcrypto:
+AC_CHECK_LIB(crypto, main)
+dnl Replace `main' with a function in -lpopt:
+AC_CHECK_LIB(popt, main)
+dnl Replace `main' with a function in -lssl:
+AC_CHECK_LIB(ssl, main)
+
+dnl ----[ Create object list ]----
+KERNEL_CODE=`echo $KERNEL_VERSION | cut -d'.' -f2`
+if test "${KERNEL_CODE}" = "2"; then
+  LDFLAGS = ${LIBS} libipfwc/libipfwc.a
+  LIBOBJS = ${LIBOBJS} ipfwwrapper.o
+fi
+
+dnl ----[ Checks for header files ]----
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(fcntl.h sys/ioctl.h sys/time.h syslog.h unistd.h)
+
+dnl ----[ Checks for typedefs, structures, and compiler characteristics ]----
+AC_C_CONST
+AC_TYPE_PID_T
+AC_HEADER_TIME
+
+dnl ----[ Checks for library functions ]----
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_MEMCMP
+AC_TYPE_SIGNAL
+AC_CHECK_FUNCS(gettimeofday select socket strerror strtol uname)
+
+AC_OUTPUT(Makefile genhash/Makefile)
+
+cat <<EOF;
+
+Keepalived configuration
+------------------------
+Keepalived version   : ${VERSION}
+Linux Kernel release : ${KERNEL_VERSION}
+IPVS version code    : ${IPVS_VERSION}
+Compiler             : ${CC}
+Compiler flags       : ${CFLAGS}
+
+EOF
diff --git a/daemon.c b/daemon.c
new file mode 100644 (file)
index 0000000..f0a4b69
--- /dev/null
+++ b/daemon.c
@@ -0,0 +1,72 @@
+/*
+ * 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.5.3 2002/02/24 23:50:11 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 "daemon.h"
+
+/* Daemonization function coming from zebra source code */
+pid_t xdaemon(int nochdir, int noclose, int exitflag)
+{
+  pid_t pid;
+
+  /* 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;
+  }
+
+  /* Become session leader and get pid. */
+  pid = setsid();
+  if (pid < -1) {
+    perror ("setsid");
+    return -1;
+  }
+
+  /* Change directory to root. */
+  if (!nochdir)
+    chdir ("/");
+
+  /* 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);
+    }
+  }
+
+  umask (0);
+  return 0;
+}
diff --git a/daemon.h b/daemon.h
new file mode 100644 (file)
index 0000000..719c327
--- /dev/null
+++ b/daemon.h
@@ -0,0 +1,39 @@
+/*
+ * 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:        Daemon process handling.
+ *
+ * Version:     $Id: daemon.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ *
+ * Author:      Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _DAEMON_H
+#define _DAEMON_H
+
+/* System includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+/* prototype */
+extern pid_t xdaemon(int, int, int);
+
+#endif
diff --git a/data.c b/data.c
new file mode 100644 (file)
index 0000000..a01abb0
--- /dev/null
+++ b/data.c
@@ -0,0 +1,337 @@
+/*
+ * 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.5.3 2002/02/24 23:50:11 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"
+
+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_vrrp(void *data)
+{
+  vrrp_instance *vrrp = data;
+  vrrp_rt *ptr = vrrp->vsrv;
+
+  FREE(vrrp->iname);
+  FREE_PTR(vrrp->isync);
+  FREE_PTR(ptr->vaddr);
+  FREE(ptr->ipsecah_counter);
+  FREE(ptr->vif->ifname);
+  FREE(ptr->vif);
+  FREE(ptr);
+  FREE(vrrp);
+}
+static void dump_vrrp(void *data)
+{
+  vrrp_instance *vrrp = data;
+  vrrp_rt *ptr = vrrp->vsrv;
+  int i;
+
+  syslog(LOG_INFO, " VRRP Instance = %s", vrrp->iname);
+  if (vrrp->isync)
+    syslog(LOG_INFO, "   Sync with instance = %s", vrrp->isync);
+  if (ptr->init_state == VRRP_STATE_BACK)
+    syslog(LOG_INFO, "   Want State = BACKUP");
+  else
+    syslog(LOG_INFO, "   Want State = MASTER");
+  syslog(LOG_INFO, "   Runing on device = %s", ptr->vif->ifname);
+  syslog(LOG_INFO, "   Virtual Router ID = %d", ptr->vrid);
+  syslog(LOG_INFO, "   Priority = %d", ptr->priority);
+  syslog(LOG_INFO, "   Advert interval = %dsec", ptr->adver_int/TIMER_HZ);
+  if (ptr->preempt)
+    syslog(LOG_INFO, "   Preempt Active");
+  if (ptr->vif->auth_type) {
+    syslog(LOG_INFO, "   Authentication type = %s",
+               (ptr->vif->auth_type == VRRP_AUTH_AH)?"IPSEC_AH":"SIMPLE_PASSWORD" );
+    syslog(LOG_INFO, "   Password = %s", ptr->vif->auth_data);
+  }
+  syslog(LOG_INFO, "   VIP count = %d", ptr->naddr);
+  for (i = 0; i < ptr->naddr; i++)
+    syslog(LOG_INFO, "     VIP%d = %s", i+1, ip_ntoa(ptr->vaddr[i].addr));
+}
+void alloc_vrrp(char *iname)
+{
+  int size = strlen(iname);
+  vrrp_instance *new;
+  vrrp_rt *rt;
+  vrrp_if *vif;
+  seq_counter *counter;
+
+  /* Allocate new VRRP structure */
+  new     = (vrrp_instance *)MALLOC(sizeof(vrrp_instance));
+  rt      = (vrrp_rt *)      MALLOC(sizeof(vrrp_rt));
+  vif     = (vrrp_if *)      MALLOC(sizeof(vrrp_if));
+  counter = (seq_counter *)  MALLOC(sizeof(seq_counter));
+
+  /* Build the structure */
+  new->vsrv           = rt;
+  rt->vif             = vif;
+  rt->ipsecah_counter = counter;
+
+  /* Set default values */
+  rt->wantstate  = VRRP_STATE_BACK;
+  rt->init_state = VRRP_STATE_BACK;
+  rt->adver_int  = TIMER_HZ;
+  new->iname = (char *)MALLOC(size+1);
+  memcpy(new->iname, iname, size);
+
+  list_add(conf_data->vrrp, new);
+}
+void alloc_vrrp_vip(char *vip)
+{
+  vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+  uint32_t ipaddr = inet_addr(vip);
+  vrrp_rt *ptr = vrrp->vsrv;
+
+  ptr->naddr++;
+  if (ptr->vaddr)
+    ptr->vaddr = REALLOC(ptr->vaddr, ptr->naddr*sizeof(*ptr->vaddr));
+  else
+    ptr->vaddr = (vip_addr *)MALLOC(sizeof(*ptr->vaddr));
+  ptr->vaddr[ptr->naddr-1].addr = ipaddr;
+  ptr->vaddr[ptr->naddr-1].deletable = 0;
+}
+
+/* Virtual server facility functions */
+static void free_vs(void *data)
+{
+  virtual_server *vs = data;
+  FREE_PTR(vs->s_svr);
+  if (!LIST_ISEMPTY(vs->rs))
+    free_list(vs->rs);
+  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"
+                   , ip_ntoa(SVR_IP(vs))
+                   , ntohs(SVR_PORT(vs)));
+  syslog(LOG_INFO, "   delay_loop = %d, lb_algo = %s"
+                 , vs->delay_loop
+                 , vs->sched);
+  if (atoi(vs->timeout_persistence) > 0)
+    syslog(LOG_INFO, "   persistence = %s"
+                   , vs->timeout_persistence);
+  syslog(LOG_INFO, "   protocol = %s"
+                 , (vs->service_type == IPPROTO_TCP)?"TCP":"UDP");
+
+  switch (vs->loadbalancing_kind) {
+#ifdef _KRNL_2_2_
+    case 0:
+      syslog(LOG_INFO, "   lb_kind = NAT");
+      syslog(LOG_INFO, "   nat mask = %s", ip_ntoa(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
+  }
+
+  if (vs->s_svr) {
+    syslog(LOG_INFO, "   sorry server = %s:%d"
+                   , ip_ntoa(SVR_IP(vs->s_svr))
+                   , ntohs(SVR_PORT(vs->s_svr)));
+  }
+
+  dump_list(vs->rs);
+}
+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 {
+    new->addr_ip   = inet_addr(ip);
+    new->addr_port = htons(atoi(port));
+  }
+  new->delay_loop = KEEPALIVED_DEFAULT_DELAY;
+  strncpy(new->timeout_persistence, "0", 1);
+
+  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;
+  vs->s_svr->addr_ip   = inet_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"
+                 , ip_ntoa(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));
+
+  new->addr_ip   = inet_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);
+}
+
+/* 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->vs    = alloc_list(free_vs,    dump_vs);
+
+  return new;
+}
+void free_data(void)
+{
+  free_ssl();
+  free_list(conf_data->email);
+  free_list(conf_data->vrrp);
+  free_list(conf_data->vs);
+
+  FREE(conf_data->lvs_id);
+  FREE(conf_data->email_from);
+  FREE(conf_data);
+}
+void dump_data(void)
+{
+  syslog(LOG_INFO, "------< Global definitions >------");
+  syslog(LOG_INFO, " LVS ID = %s", conf_data->lvs_id);
+  syslog(LOG_INFO, " Smtp server = %s", ip_ntoa(conf_data->smtp_server));
+  syslog(LOG_INFO, " Smtp server connection timeout = %d", conf_data->smtp_connection_to);
+  syslog(LOG_INFO, " Email notification from = %s", conf_data->email_from);
+  dump_list(conf_data->email);
+
+  if (conf_data->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->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();
+}
diff --git a/data.h b/data.h
new file mode 100644 (file)
index 0000000..3d6b22d
--- /dev/null
+++ b/data.h
@@ -0,0 +1,129 @@
+/*
+ * 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.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ *
+ * Author:      Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _DATA_H
+#define _DATA_H
+
+/* system includes */
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <syslog.h>
+#include <arpa/inet.h>
+#include <openssl/ssl.h>
+
+#ifdef _KRNL_2_2_
+  #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
+#endif
+#include <net/ip_vs.h>
+
+/* local includes */
+#include "list.h"
+#include "vrrp.h"
+
+/* Daemon dynamic data structure definition */
+#define MAX_TIMEOUT_LENGTH     5
+#define KEEPALIVED_DEFAULT_DELAY 60
+
+/* 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;
+} ssl_data;
+
+/* Real Server definition */
+typedef struct _real_server {
+  uint32_t     addr_ip;
+  uint16_t     addr_port;
+  int          weight;
+  int          alive;
+} real_server;
+
+/* 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];
+  unsigned             loadbalancing_kind;
+  uint32_t             nat_mask;
+  char                 timeout_persistence[MAX_TIMEOUT_LENGTH];
+  real_server          *s_svr;
+  list                 rs;
+} virtual_server;
+
+/* VRRP instance definition */
+typedef struct _vrrp_instance {
+  char         *iname; /* Instance Name */
+  char         *isync; /* Instance Name to synchronize with */
+  vrrp_rt      *vsrv;  /* VRRP data */
+} vrrp_instance;
+
+/* email link list */
+typedef struct _email {
+  char *addr;
+} 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         vs;
+} data;
+
+/* macro utility */
+#define ISALIVE(R)   ((R)->alive)
+#define SVR_IP(H)    ((H)->addr_ip)
+#define SVR_PORT(H)  ((H)->addr_port)
+
+/* prototypes */
+extern void alloc_email(char *addr);
+extern SSL_DATA *alloc_ssl(void);
+extern void alloc_vrrp(char *iname);
+extern void alloc_vrrp_vip(char *vip);
+extern void alloc_vs(char *ip, char *port);
+extern void alloc_rs(char *ip, char *port);
+extern void alloc_ssvr(char *ip, char *port);
+
+extern data *alloc_data(void);
+extern void free_data(void);
+extern void dump_data(void);
+
+#endif
index 2d6b8e7..143a0de 100644 (file)
@@ -1,3 +1,6 @@
+2002-01-17  Alexandre Cassen  <acassen@linux-vs.org>
+       * Patched the dynamic GET request lenght allocation.
+
 2001-11-29  Alexandre Cassen  <acassen@linux-vs.org>
        * genhash 0.4.9 released.
        * Rewrite the whole previous code
diff --git a/genhash/Makefile b/genhash/Makefile
deleted file mode 100644 (file)
index addb953..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-# Makefile
-# Alexandre Cassen <acassen@linux-vs.org>
-
-EXEC = genhash
-
-CC = gcc
-CFLAGS = -Wall -Wunused -Wstrict-prototypes -g -O2
-#LD = -lssl -lcrypto -dynamic -lpopt
-LD = -lssl -lcrypto -lpopt
-
-OBJS = main.o client.o common.o
-
-all:   genhash
-       strip genhash
-       @echo ""
-       @echo "Make complete"
-$(EXEC): $(OBJS)
-       $(CC) $(OBJS) -o $(EXEC) $(LD)
-clean:
-       rm -f core *.o $(EXEC)
-install:       
-       install -m 755 genhash /usr/bin/
diff --git a/genhash/Makefile.in b/genhash/Makefile.in
new file mode 100644 (file)
index 0000000..e488656
--- /dev/null
@@ -0,0 +1,34 @@
+# Makefile
+#
+# Keepalived OpenSource project.
+#
+# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
+
+EXEC = genhash
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+
+CC = gcc
+CFLAGS = @CFLAGS@ -Wall -Wunused -Wstrict-prototypes
+LDFLAGS = @LIBS@ @LDFLAGS@
+
+OBJS = main.o client.o common.o
+
+all:   $(EXEC)
+       strip $(EXEC)
+       @echo ""
+       @echo "Make complete"
+
+$(EXEC): $(OBJS)
+       $(CC) $(OBJS) -o $(EXEC) $(LDFLAGS)
+
+clean:
+       rm -f core *.o $(EXEC)
+
+clean-dist:
+       rm -f $(bindir)/$(EXEC)
+
+install:       
+       install -m 755 $(EXEC) $(bindir)/
index e7bafc9..0ec297c 100644 (file)
@@ -95,7 +95,10 @@ static char *build_request(REQ* req)
   char *request;
   int request_len = 0;
 
-  request_len = strlen(REQUEST_TEMPLATE) + strlen(req->host) + 12;
+  request_len = strlen(REQUEST_TEMPLATE) +
+                strlen(req->host) +
+                strlen(req->url) +
+                sizeof(unsigned short int);
   request = xmalloc(request_len);
   if (!request) return NULL;
 
diff --git a/install-sh b/install-sh
new file mode 100755 (executable)
index 0000000..e9de238
--- /dev/null
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+               chmodcmd=""
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
index e9053af..ea77db9 100644 (file)
@@ -7,7 +7,7 @@
  *              library to add/remove server MASQ rules to the kernel 
  *              firewall framework.
  *
- * Version:     $Id: ipfwwrapper.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: ipfwwrapper.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -23,8 +23,9 @@
  */
 
 #include "ipfwwrapper.h"
+#include "utils.h"
 
-int ipfw_cmd(int cmd, virtualserver *vserver, realserver *rserver)
+int ipfw_cmd(int cmd, virtual_server *vs, real_server *rs)
 {
   struct ip_fwuser ctl;
   int ret = 1;
@@ -33,13 +34,13 @@ int ipfw_cmd(int cmd, virtualserver *vserver, realserver *rserver)
 
   /* Create the firewall MASQ rule */
   strncpy(ctl.label, IP_FW_LABEL_MASQUERADE, IP_FW_MAX_LABEL_LENGTH);
-  ctl.ipfw.fw_proto = vserver->service_type;
+  ctl.ipfw.fw_proto = vs->service_type;
  
   /* compute the source ip address */
-  ctl.ipfw.fw_src.s_addr = rserver->addr_ip.s_addr & vserver->nat_mask.s_addr;
-  ctl.ipfw.fw_smsk.s_addr = vserver->nat_mask.s_addr;
+  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] = ntohs(rserver->addr_port);
+  ctl.ipfw.fw_spts[0] = ctl.ipfw.fw_spts[1] = ntohs(rs->addr_port);
   ctl.ipfw.fw_dpts[0] = 0x0000;
   ctl.ipfw.fw_dpts[1] = 0xFFFF;
   ctl.ipfw.fw_tosand = 0xFF;
@@ -48,9 +49,10 @@ int ipfw_cmd(int cmd, virtualserver *vserver, realserver *rserver)
   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_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+#ifdef _DEBUG_
+      syslog(LOG_DEBUG, "ipfw_cmd : MASQ firewall rule [%s:%d] already exist."
+                      , ip_ntoa(SVR_IP(rs))
+                      , ntohs(SVR_PORT(rs)));
 #endif
     }
     ret &= ipfwc_insert_entry(IP_FW_LABEL_FORWARD, &ctl, 1);
@@ -60,10 +62,11 @@ int ipfw_cmd(int cmd, virtualserver *vserver, realserver *rserver)
     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_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+#ifdef _DEBUG_
+    syslog(LOG_DEBUG, "ipfw_cmd : firewall error (%s) processing [%s:%d] MASQ rule."
+                    , strerror(errno)
+                    , ip_ntoa(SVR_IP(rs))
+                    , ntohs(SVR_PORT(rs)));
 #endif
     return IPFW_ERROR;
   }
index f52923f..fbeb92d 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipfwwrapper.c include file.
  *
- * Version:     $Id: ipfwwrapper.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: ipfwwrapper.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -29,7 +29,7 @@
 
 /* locale includes */
 #include "libipfwc/libipfwc.h"
-#include "cfreader.h"
+#include "data.h"
 
 /* local defs */
 #define IPFW_ERROR   0
@@ -42,6 +42,6 @@
 #define IPFW_SRC_NETMASK 0xffffffff
 
 /* prototypes */
-extern int ipfw_cmd(int cmd, virtualserver *vserver, realserver *rserver);
+extern int ipfw_cmd(int cmd, virtual_server *vserver, real_server *rserver);
 
 #endif
index 2c03b62..6812848 100644 (file)
@@ -6,7 +6,7 @@
  * Part:        IPVS Kernel wrapper. Use setsockopt call to add/remove
  *              server to/from the loadbalanced server pool.
  *  
- * Version:     $Id: ipvswrapper.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: ipvswrapper.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
  */
 
 #include "ipvswrapper.h"
+#include "utils.h"
 
 #ifdef _KRNL_2_2_  /* KERNEL 2.2 LVS handling */
 
-int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver)
+int ipvs_cmd(int cmd, virtual_server *vs, real_server *rs)
 {
   struct ip_masq_ctl ctl;
   int result=0;
@@ -35,31 +36,32 @@ int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver)
 
   ctl.m_target = IP_MASQ_TARGET_VS;
   ctl.m_cmd = cmd;
-  strncpy(ctl.m_tname, vserver->sched, IP_MASQ_TNAME_MAX);
+  strncpy(ctl.m_tname, vs->sched, IP_MASQ_TNAME_MAX);
   ctl.u.vs_user.weight = -1;
-  ctl.u.vs_user.masq_flags = vserver->loadbalancing_kind;
+  ctl.u.vs_user.masq_flags = vs->loadbalancing_kind;
   ctl.u.vs_user.netmask = ((u_int32_t) 0xffffffff); /* f:f:f:f for default netmask */
-  ctl.u.vs_user.protocol = vserver->service_type;
+  ctl.u.vs_user.protocol = vs->service_type;
 
-  if(!parse_timeout(vserver->timeout_persistence, &ctl.u.vs_user.timeout)) {
-    syslog(LOG_INFO, "IPVS WRAPPER : Virtual service [%s:%d] illegal timeout.",
-                      inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
+  if(!parse_timeout(vs->timeout_persistence, &ctl.u.vs_user.timeout)) {
+    syslog(LOG_INFO, "IPVS WRAPPER : Virtual service [%s:%d] illegal timeout."
+                   , ip_ntoa(SVR_IP(vs))
+                   , ntohs(SVR_PORT(vs)));
   }
   ctl.u.vs_user.vs_flags = (ctl.u.vs_user.timeout!=0)?IP_VS_SVC_F_PERSISTENT:0;
   
   /* VS specific */
-  if (vserver->vfwmark) {
-    ctl.u.vs_user.vfwmark = vserver->vfwmark;
+  if (vs->vfwmark) {
+    ctl.u.vs_user.vfwmark = vs->vfwmark;
   } else {
-    ctl.u.vs_user.vaddr = vserver->addr_ip.s_addr;
-    ctl.u.vs_user.vport = vserver->addr_port;
+    ctl.u.vs_user.vaddr = SVR_IP(vs);
+    ctl.u.vs_user.vport = SVR_PORT(vs);
   }
 
   /* SVR specific */
   if (ctl.m_cmd == IP_MASQ_CMD_ADD_DEST || ctl.m_cmd == IP_MASQ_CMD_DEL_DEST) {
-    ctl.u.vs_user.weight = rserver->weight;
-    ctl.u.vs_user.daddr = rserver->addr_ip.s_addr;
-    ctl.u.vs_user.dport = rserver->addr_port;
+    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);
@@ -71,16 +73,19 @@ int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver)
   result = setsockopt(sockfd, IPPROTO_IP, IP_FW_MASQ_CTL, (char *)&ctl, sizeof(ctl));
 
   if (errno == ESRCH) {
-    syslog(LOG_INFO, "IPVS WRAPPER : Virtual service [%s:%d] not defined.",
-                      inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
+    syslog(LOG_INFO, "IPVS WRAPPER : Virtual service [%s:%d] not defined."
+                   , ip_ntoa(SVR_IP(vs))
+                   , ntohs(SVR_PORT(vs)));
     close(sockfd);
     return IPVS_ERROR;
   } else if (errno == EEXIST) {
-    syslog(LOG_INFO, "IPVS WRAPPER : Destination already exists [%s:%d].",
-                      inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+    syslog(LOG_INFO, "IPVS WRAPPER : Destination already exists [%s:%d]."
+                   , ip_ntoa(SVR_IP(rs))
+                   , ntohs(SVR_PORT(rs)));
   } else if (errno == ENOENT) {
-    syslog(LOG_INFO, "IPVS WRAPPER : No such destination [%s:%d].",
-                      inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+    syslog(LOG_INFO, "IPVS WRAPPER : No such destination [%s:%d]."
+                   , ip_ntoa(SVR_IP(rs))
+                   , ntohs(SVR_PORT(rs)));
   }
 
   close(sockfd);
@@ -89,7 +94,7 @@ int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver)
 
 #else /* KERNEL 2.4 LVS handling */
 
-int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver)
+int ipvs_cmd(int cmd, virtual_server *vs, real_server *rs)
 {
   struct ip_vs_rule_user urule;
   int result=0;
@@ -97,30 +102,30 @@ int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver)
 
   memset(&urule, 0, sizeof(struct ip_vs_rule_user));
 
-  strncpy(urule.sched_name, vserver->sched, IP_VS_SCHEDNAME_MAXLEN);
+  strncpy(urule.sched_name, vs->sched, IP_VS_SCHEDNAME_MAXLEN);
   urule.weight = 1;
-  urule.conn_flags = vserver->loadbalancing_kind;
+  urule.conn_flags = vs->loadbalancing_kind;
   urule.netmask    = ((u_int32_t) 0xffffffff);
-  urule.protocol   = vserver->service_type;
+  urule.protocol   = vs->service_type;
   
-  if (!parse_timeout(vserver->timeout_persistence, &urule.timeout)) {
-    syslog(LOG_INFO, "IPVS WRAPPER : Virtual service [%s:%d] illegal timeout.",
-                      inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
-  }
+  if (!parse_timeout(vs->timeout_persistence, &urule.timeout))
+    syslog(LOG_INFO, "IPVS WRAPPER : Virtual service [%s:%d] illegal timeout."
+                   , ip_ntoa(SVR_IP(vs))
+                   , ntohs(SVR_PORT(vs)));
   urule.vs_flags = (urule.timeout != 0)?IP_VS_SVC_F_PERSISTENT:0;
 
   /* VS specific */
-  if (vserver->vfwmark) {
-    urule.vfwmark = vserver->vfwmark;
+  if (vs->vfwmark) {
+    urule.vfwmark = vs->vfwmark;
   } else {
-    urule.vaddr = vserver->addr_ip.s_addr;
-    urule.vport = vserver->addr_port;
+    urule.vaddr = SVR_IP(vs);
+    urule.vport = SVR_PORT(vs);
   }
   /* SVR specific */
   if (cmd == IP_VS_SO_SET_ADDDEST || cmd == IP_VS_SO_SET_DELDEST) {
-    urule.weight = rserver->weight;
-    urule.daddr  = rserver->addr_ip.s_addr;
-    urule.dport  = rserver->addr_port;
+    urule.weight = rs->weight;
+    urule.daddr  = SVR_IP(rs);
+    urule.dport  = SVR_PORT(rs);
   }
 
   sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
@@ -139,11 +144,12 @@ int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver)
     switch (cmd) {
       case IP_VS_SO_SET_ADD:
         if (errno == EEXIST)
-          syslog(LOG_INFO, "IPVS WRAPPER : Destination already exists [%s:%d].",
-                           inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
+          syslog(LOG_INFO, "IPVS WRAPPER : Destination already exists [%s:%d]."
+                         , ip_ntoa(SVR_IP(vs))
+                         , ntohs(SVR_PORT(vs)));
         else if (errno == ENOENT) {
-          syslog(LOG_INFO, "IPVS WRAPPER : Scheduler not found: ip_vs_%s.o !!!",
-                           urule.sched_name);
+          syslog(LOG_INFO, "IPVS WRAPPER : Scheduler not found: ip_vs_%s.o !!!"
+                         , urule.sched_name);
           close(sockfd);
           return IPVS_ERROR;
         }
@@ -151,28 +157,33 @@ int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver)
 
       case IP_VS_SO_SET_DEL:
         if (errno == ESRCH)
-          syslog(LOG_INFO, "IPVS WRAPPER : No such service [%s:%d].",
-                           inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
+          syslog(LOG_INFO, "IPVS WRAPPER : No such service [%s:%d]."
+                         , ip_ntoa(SVR_IP(vs))
+                         , ntohs(SVR_PORT(vs)));
         close(sockfd);
         return IPVS_ERROR;
         break;
 
       case IP_VS_SO_SET_ADDDEST:
         if (errno == ESRCH)
-          syslog(LOG_INFO, "IPVS WRAPPER : Service not defined [%s:%d].",
-                           inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+          syslog(LOG_INFO, "IPVS WRAPPER : Service not defined [%s:%d]."
+                         , ip_ntoa(SVR_IP(rs))
+                         , ntohs(SVR_PORT(rs)));
         else if (errno == EEXIST)
-          syslog(LOG_INFO, "IPVS WRAPPER : Destination already exists [%s:%d].",
-                           inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+          syslog(LOG_INFO, "IPVS WRAPPER : Destination already exists [%s:%d]."
+                         , ip_ntoa(SVR_IP(rs))
+                         , ntohs(SVR_PORT(rs)));
         break;
 
       case IP_VS_SO_SET_DELDEST:
         if (errno == ESRCH)
-          syslog(LOG_INFO, "IPVS WRAPPER : Service not defined [%s:%d].",
-                           inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+          syslog(LOG_INFO, "IPVS WRAPPER : Service not defined [%s:%d]."
+                         , ip_ntoa(SVR_IP(rs))
+                         , ntohs(SVR_PORT(rs)));
         else if (errno == ENOENT)
-          syslog(LOG_INFO, "IPVS WRAPPER : No such destination [%s:%d].",
-                           inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+          syslog(LOG_INFO, "IPVS WRAPPER : No such destination [%s:%d]."
+                         , ip_ntoa(SVR_IP(rs))
+                         , ntohs(SVR_PORT(rs)));
         break;
     }
   }
@@ -196,7 +207,7 @@ int parse_timeout(char *buf, unsigned *timeout)
     return 1;
   }
 
-  if ((i=string_to_number(buf, 1, 86400*31)) == -1)
+  if ((i=string_to_number(buf, 0, 86400*31)) == -1)
     return 0;
 
   *timeout = i * HZ;
index 9c43bd7..c1ef762 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipvswrapper.c include file.
  *
- * Version:     $Id: ipvswrapper.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: ipvswrapper.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
   #include <linux/ip_fw.h>
   #include <net/ip_masq.h>
 #endif
-
 #include <net/ip_vs.h>
 
 /* locale includes */
-#include "cfreader.h"
+#include "data.h"
 
 #define IPVS_ERROR   0
 #define IPVS_SUCCESS 1
@@ -52,6 +51,6 @@
 /* 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, virtualserver *vserver, realserver *rserver);
+extern int ipvs_cmd(int cmd, virtual_server *vserver, real_server *rserver);
 
 #endif
index c4995d6..14c2be1 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Manipulation functions for IPVS & IPFW wrappers.
  *
- * Version:     $id: ipwrapper.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $id: ipwrapper.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
  */
 
 #include "ipwrapper.h"
+#include "utils.h"
 
-int clear_service_vs(virtualserver *vserver)
+extern data *conf_data;
+
+int clear_service_vs(virtual_server *vs)
 {
-  realserver *pointersvr;
+  element e;
 
-  pointersvr = vserver->svr;
-  while (vserver->svr) {
+  for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) {
     /* IPVS cleaning server entry */
-    if (!ipvs_cmd(LVS_CMD_DEL_DEST, vserver, vserver->svr)) {
-      vserver->svr = pointersvr;
+    if (!ipvs_cmd(LVS_CMD_DEL_DEST, vs, e->data))
       return 0;
-    }
 
 #ifdef _KRNL_2_2_
     /* IPFW cleaning server entry if granularity = /32 */
-    if (vserver->nat_mask.s_addr == HOST_NETMASK)
-      if (!ipfw_cmd(IP_FW_CMD_DEL, vserver, vserver->svr))
+    if (vserver->nat_mask == HOST_NETMASK)
+      if (!ipfw_cmd(IP_FW_CMD_DEL, vs, e->data))
         return 0;
 #endif
-
-    vserver->svr = (realserver *)vserver->svr->next;
   }
-  vserver->svr = pointersvr;
 
-  if (!ipvs_cmd(LVS_CMD_DEL, vserver, vserver->svr))
+  if (!ipvs_cmd(LVS_CMD_DEL, vs, NULL))
     return 0;
-
   return 1;
 }
 
-int clear_services(virtualserver *vserver)
+/* IPVS cleaner processing */
+int clear_services(void)
 {
-  while (vserver) {
-    /* IPVS cleaner processing */
-    if (!clear_service_vs(vserver))
+  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 = (real_server *)LIST_HEAD(vsvr->rs);
+    if (!clear_service_vs(vsvr))
       return 0;
 
 #ifdef _KRNL_2_2_
-    /* IPFW cleaner processing */
-    if (vserver->nat_mask.s_addr != HOST_NETMASK)
-      if (!ipfw_cmd(IP_FW_CMD_DEL, vserver, vserver->svr))
+    if (vsvr->nat_mask != HOST_NETMASK)
+      if (!ipfw_cmd(IP_FW_CMD_DEL, vsvr, rsvr))
         return 0;
 #endif
-
-    vserver = (virtualserver *)vserver->next;
   }
   return 1;
 }
 
-int all_realservers_down(virtualserver *vserver)
+int all_realservers_down(virtual_server *vs)
 {
-  realserver *pointersvr;
+  element e;
+  real_server *svr;
 
-  pointersvr = vserver->svr;
-  while (vserver->svr) {
-    if (vserver->svr->alive) return 0;
-
-    vserver->svr = (realserver *)vserver->svr->next;
+  for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) {
+    svr = ELEMENT_DATA(e);
+    if (svr->alive) return 0;
   }
-  vserver->svr = pointersvr;
   return 1;
 }
 
-void perform_svr_state(int alive, virtualserver *vserver, realserver *rserver)
+void perform_svr_state(int alive, virtual_server *vs, real_server *rs)
 {
-  if (!rserver->alive && alive) {
+  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 (vserver->s_svr) {
-      if (vserver->s_svr->alive) {
-        syslog(LOG_INFO, "Removing sorry server [%s:%d] from VS [%s:%d]",
-               inet_ntoa(vserver->s_svr->addr_ip), ntohs(vserver->s_svr->addr_port),
-               inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
-
-        vserver->s_svr->alive = 0;
-        ipvs_cmd(LVS_CMD_DEL_DEST, vserver, vserver->s_svr);
+    if (vs->s_svr) {
+      if (vs->s_svr->alive) {
+        syslog(LOG_INFO, "Removing sorry server [%s:%d] from VS [%s:%d]"
+                       , ip_ntoa(SVR_IP(vs->s_svr))
+                       , ntohs(SVR_PORT(vs->s_svr))
+                       , ip_ntoa(SVR_IP(vs))
+                       , 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, vserver, vserver->s_svr);
+        ipfw_cmd(IP_FW_CMD_DEL, vs, vs->s_svr);
 #endif
       }
     }
 
-    rserver->alive = alive;
-    syslog(LOG_INFO, "Adding service [%s:%d] to VS [%s:%d]",
-           inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port),
-           inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
-    ipvs_cmd(LVS_CMD_ADD_DEST, vserver, rserver);
+    rs->alive = alive;
+    syslog(LOG_INFO, "Adding service [%s:%d] to VS [%s:%d]"
+                   , ip_ntoa(SVR_IP(rs))
+                   , ntohs(SVR_PORT(rs))
+                   , ip_ntoa(SVR_IP(vs))
+                   , ntohs(SVR_PORT(vs)));
+    ipvs_cmd(LVS_CMD_ADD_DEST, vs, rs);
 
 #ifdef _KRNL_2_2_
-    if (vserver->nat_mask.s_addr == HOST_NETMASK)
-      ipfw_cmd(IP_FW_CMD_ADD, vserver, rserver);
+    if (vs->nat_mask == HOST_NETMASK)
+      ipfw_cmd(IP_FW_CMD_ADD, vs, rs);
 #endif
 
   } else {
 
-    rserver->alive = alive;
-    syslog(LOG_INFO, "Removing service [%s:%d] from VS [%s:%d]",
-           inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port),
-           inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
+    rs->alive = alive;
+    syslog(LOG_INFO, "Removing service [%s:%d] from VS [%s:%d]"
+                   , ip_ntoa(SVR_IP(rs))
+                   , ntohs(SVR_PORT(rs))
+                   , ip_ntoa(SVR_IP(vs))
+                   , ntohs(SVR_PORT(vs)));
 
     /* server is down, it is removed from the LVS realserver pool */
-    ipvs_cmd(LVS_CMD_DEL_DEST, vserver, rserver);
+    ipvs_cmd(LVS_CMD_DEL_DEST, vs, rs);
 
 #ifdef _KRNL_2_2_
-    if (vserver->nat_mask.s_addr == HOST_NETMASK)
-      ipfw_cmd(IP_FW_CMD_DEL, vserver, rserver);
+    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 (vserver->s_svr && all_realservers_down(vserver)) {
-      syslog(LOG_INFO, "Adding sorry server [%s:%d] to VS [%s:%d]",
-             inet_ntoa(vserver->s_svr->addr_ip), ntohs(vserver->s_svr->addr_port),
-             inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
+    if (vs->s_svr && all_realservers_down(vs)) {
+      syslog(LOG_INFO, "Adding sorry server [%s:%d] to VS [%s:%d]"
+                     , ip_ntoa(SVR_IP(vs->s_svr))
+                     , ntohs(SVR_PORT(vs->s_svr))
+                     , ip_ntoa(SVR_IP(vs))
+                     , ntohs(SVR_PORT(vs)));
 
       /* the sorry server is now up in the pool, we flag it alive */
-      vserver->s_svr->alive = 1;
-      ipvs_cmd(LVS_CMD_ADD_DEST, vserver, vserver->s_svr);
+      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, vserver, vserver->s_svr);
+      ipfw_cmd(IP_FW_CMD_ADD, vs, vs->s_svr);
 #endif
     }
 
   }
 }
 
-int init_service_vs(virtualserver *vserver)
+int init_service_vs(virtual_server *vs)
 {
-  realserver *pointersvr;
+  element e;
+
+  /* Init the IPVS root */
+  if (!ipvs_cmd(LVS_CMD_ADD, vs, NULL))
+    return 0;
 
-  pointersvr = vserver->svr;
-  while (vserver->svr) {
-    if (!ipvs_cmd(LVS_CMD_ADD_DEST, vserver, vserver->svr)) {
-      vserver->svr = pointersvr;
+  for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) {
+    if (!ipvs_cmd(LVS_CMD_ADD_DEST, vs, e->data))
       return 0;
-    }
 
 #ifdef _KRNL_2_2_
     /* if we have a /32 mask, we create one nat rules per
      * realserver.
      */
-    if (vserver->nat_mask.s_addr == HOST_NETMASK)
-      if(!ipfw_cmd(IP_FW_CMD_ADD, vserver, vserver->svr)) {
-        vserver->svr = pointersvr;
+    if (vs->nat_mask == HOST_NETMASK)
+      if(!ipfw_cmd(IP_FW_CMD_ADD, vs, e->data))
         return 0;
-      }
 #endif
-
-    vserver->svr = (realserver *)vserver->svr->next;
   }
-  vserver->svr = pointersvr;
-
   return 1;
 }
 
-int init_services(virtualserver *vserver)
+int init_services(void)
 {
-  virtualserver *pointervs;
-
-  pointervs = vserver;
-  while (vserver) {
-    if (!ipvs_cmd(LVS_CMD_ADD, vserver, vserver->svr))
+  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 = (real_server *)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 (vserver->nat_mask.s_addr != HOST_NETMASK)
-      if (!ipfw_cmd(IP_FW_CMD_ADD, vserver, vserver->svr))
+    if (vsvr->nat_mask != HOST_NETMASK)
+      if (!ipfw_cmd(IP_FW_CMD_ADD, vsvr, rsvr))
         return 0;
 #endif
-
-    if (!init_service_vs(vserver))
-      return 0;
-
-    vserver = (virtualserver *)vserver->next;
   }
-  vserver = pointervs;
-
   return 1;
 }
index 698ff45..62fb58a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipwrapper.c include file.
  *
- * Version:     $Id: ipwrapper.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: ipwrapper.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -27,7 +27,7 @@
 #include <syslog.h>
 
 /* locale includes */
-#include "cfreader.h"
+#include "data.h"
 #include "smtp.h"
 
 /* NAT netmask */
 #endif
 
 /* prototypes */
-extern void perform_svr_state(int alive, virtualserver *vserver, realserver *rserver);
-extern int init_services(virtualserver *vserver);
-extern int clear_services(virtualserver *vserver);
+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, virtualserver *vserver, realserver *rserver);
-extern int ipfw_cmd(int cmd, virtualserver *vserver, realserver *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
index 3c28cc8..830ec9d 100644 (file)
--- a/layer4.c
+++ b/layer4.c
@@ -6,7 +6,7 @@
  * Part:        Layer4 checkers handling. Register worker threads &
  *              upper layer checkers.
  *
- * Version:     $Id: layer4.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: layer4.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
  */
 
 #include "layer4.h"
+#include "check_api.h"
 
 enum connect_result
-tcp_connect (int fd, uint32_t IP_DST, uint16_t PORT_DST)
+tcp_connect (int fd, uint32_t addr_ip, uint16_t addr_port)
 {
   struct linger li = { 0 };
   int long_inet;
@@ -35,13 +36,13 @@ tcp_connect (int fd, uint32_t IP_DST, uint16_t PORT_DST)
   /* 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));
+  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 = PORT_DST;
-  adr_serv.sin_addr.s_addr = IP_DST;
+  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);
@@ -68,24 +69,21 @@ tcp_connect (int fd, uint32_t IP_DST, uint16_t PORT_DST)
 }
 
 enum connect_result tcp_socket_state(int fd, thread *thread
-                                    , int (*func) (struct _thread *))
+                                           , uint32_t addr_ip
+                                           , uint16_t addr_port
+                                           , int (*func) (struct _thread *))
 {
-  thread_arg *thread_arg;
   int status;
   int slen;
   int ret = 0;
-  TIMEVAL timer_now;
   TIMEVAL timer_min;
 
-  thread_arg = THREAD_ARG(thread);
-
   /* Handle connection timeout */
   if(thread->type == THREAD_WRITE_TIMEOUT) {
 #ifdef _DEBUG_
-    if (thread_arg->svr)
-      syslog(LOG_DEBUG, "TCP connection timeout to [%s:%d].",
-                          inet_ntoa(thread_arg->svr->addr_ip),
-                          ntohs(thread_arg->svr->addr_port));
+    syslog(LOG_DEBUG, "TCP connection timeout to [%s:%d]."
+                    , ip_ntoa(addr_ip)
+                    , ntohs(addr_port));
 #endif
     close(thread->u.fd);
     return connect_timeout;
@@ -99,10 +97,9 @@ enum connect_result tcp_socket_state(int fd, thread *thread
   /* Connection failed !!! */
   if (ret) {
 #ifdef _DEBUG_
-    if (thread_arg->svr)
-      syslog(LOG_DEBUG, "TCP connection failed to [%s:%d].",
-                          inet_ntoa(thread_arg->svr->addr_ip), 
-                          ntohs(thread_arg->svr->addr_port));
+    syslog(LOG_DEBUG, "TCP connection failed to [%s:%d]."
+                    , ip_ntoa(addr_ip)
+                    , ntohs(addr_port));
 #endif
     close(thread->u.fd);
     return connect_error;
@@ -115,22 +112,23 @@ enum connect_result tcp_socket_state(int fd, thread *thread
    */
   if (status != 0) {
 #ifdef _DEBUG_
-    if (thread_arg->svr)
-      syslog(LOG_DEBUG, "TCP connection to [%s:%d] still IN_PROGRESS.",
-                        inet_ntoa(thread_arg->svr->addr_ip),
-                        ntohs(thread_arg->svr->addr_port));
+    syslog(LOG_DEBUG, "TCP connection to [%s:%d] still IN_PROGRESS."
+                    , ip_ntoa(addr_ip)
+                    , ntohs(addr_port));
 #endif
 
-    gettimeofday(&timer_now,NULL);
-    timer_min = thread_timer_sub(thread->sands,timer_now);
+    timer_min = timer_sub_now(thread->sands);
 
-    if (timer_min.tv_sec <= 0)
-      thread_add_write(thread->master, func,
-                       thread_arg, thread->u.fd, 0);
+    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->u.fd, timer_min.tv_sec);
-
+      thread_add_write(thread->master, func
+                                     , THREAD_ARG(thread)
+                                     , thread->u.fd
+                                     , TIMER_SEC(timer_min));
     return connect_in_progress;
   }
 
@@ -139,41 +137,40 @@ enum connect_result tcp_socket_state(int fd, thread *thread
 
 void tcp_connection_state(int fd, enum connect_result status
                          , thread *thread
-                         , int (*func) (struct _thread *))
+                         , int (*func) (struct _thread *)
+                          , int timeout)
 {
-  thread_arg *thread_arg;
+  checker *checker;
 
-  thread_arg = THREAD_ARG(thread);
+  checker = THREAD_ARG(thread);
 
   switch (status) {
     case connect_error:
 #ifdef _DEBUG_
-      syslog(LOG_DEBUG,"TCP connection ERROR to [%s:%d].",
-                       inet_ntoa(thread_arg->svr->addr_ip),
-                       ntohs(thread_arg->svr->addr_port));
+      syslog(LOG_DEBUG, "TCP connection ERROR to [%s:%d]."
+                      , ip_ntoa(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_ntoa(thread_arg->svr->addr_ip),
-                       ntohs(thread_arg->svr->addr_port));
+      syslog(LOG_DEBUG, "TCP connection SUCCESS to [%s:%d]."
+                      , ip_ntoa(SVR_IP(checker->rs))
+                      , ntohs(SVR_PORT(checker->rs)));
 #endif
-      thread_add_write(thread->master, func, thread_arg, fd,
-                       thread_arg->svr->method->connection_to);
+      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_ntoa(thread_arg->svr->addr_ip),
-                       ntohs(thread_arg->svr->addr_port));
+      syslog(LOG_DEBUG, "TCP connection to [%s:%d] now IN_PROGRESS."
+                      , ip_ntoa(SVR_IP(checker->rs))
+                      , ntohs(SVR_PORT(checker->rs)));
 #endif
-      thread_add_write(thread->master, func, thread_arg, fd,
-                       thread_arg->svr->method->connection_to);
+      thread_add_write(thread->master, func, checker, fd, timeout);
       break;
 
     default:
index 074452f..3d79e39 100644 (file)
--- a/layer4.h
+++ b/layer4.h
@@ -5,7 +5,7 @@
  *
  * Part:        layer4.c include file.
  *
- * Version:     $Id: layer4.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: layer4.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 
 /* system includes */
 #include <unistd.h>
+#include <string.h>
 #include <stdint.h>
 #include <netdb.h>
 #include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
 
 /* local includes */
-#include "cfreader.h"
 #include "scheduler.h"
-#include "check_http.h"
 
 enum connect_result {
   connect_error,
@@ -43,15 +44,17 @@ enum connect_result {
 
 /* Prototypes defs */
 extern enum connect_result
-tcp_connect(int fd, uint32_t IP_DST, uint16_t PORT_DST);
+tcp_connect(int fd, uint32_t, uint16_t);
 
 extern enum connect_result
-tcp_socket_state(int fd, thread *thread,
-                         int (*func) (struct _thread *));
+tcp_socket_state(int, thread *
+                    , uint32_t
+                    , uint16_t
+                    , int (*func) (struct _thread *));
 
 extern void
-tcp_connection_state(int fd, enum connect_result status,
-                             thread *thread,
-                             int (*func) (struct _thread *));
-
+tcp_connection_state(int, enum connect_result
+                        , thread *
+                        , int (*func) (struct _thread *)
+                        , int);
 #endif
index bfa78f5..e69de29 100644 (file)
@@ -1,12 +0,0 @@
-# Makefile to make libipfwc.
-
-CC     = gcc
-COPTS   = -g -O
-CFLAGS = -Wall -Wunused $(COPTS)
-
-libipfwc.a: libipfwc.a(libipfwc.o)
-
-libipfwc.o: libipfwc.h ipfwc_kernel_headers.h
-
-clean:
-       rm -f *.a *.o *~
diff --git a/list.c b/list.c
new file mode 100644 (file)
index 0000000..995a33a
--- /dev/null
+++ b/list.c
@@ -0,0 +1,93 @@
+/* 
+ * 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.5.3 2002/02/24 23:50:11 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/list.h b/list.h
new file mode 100644 (file)
index 0000000..4895536
--- /dev/null
+++ b/list.h
@@ -0,0 +1,60 @@
+/* 
+ * 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.c include file.
+ *  
+ * Version:     $Id: list.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ *
+ * Author:      Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+
+#ifndef _LIST_H
+#define _LIST_H
+
+/* list definition */
+typedef struct _element        *element;
+typedef struct _list   *list;
+
+struct _element {
+  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 *);
+};
+
+/* utility macro */
+#define ELEMENT_NEXT(E)                ((E) = (E)->next)
+#define ELEMENT_DATA(E)                ((E)->data)
+#define LIST_HEAD(L)           ((L)->head)
+#define LIST_TAIL_DATA(L)      ((L)->tail->data)
+#define LIST_ISEMPTY(L)                ((L) == NULL || ((L)->head == NULL && (L)->tail == NULL))
+#define LIST_SIZE(V)           ((V)->count)
+
+/* Prototypes */
+extern list alloc_list(void (*free_func) (void *), void (*dump_func) (void *));
+extern void free_list(list l);
+extern void *list_element(list l, int num);
+extern void dump_list(list l);
+extern void list_add(list l, void *data);
+
+#endif
diff --git a/main.c b/main.c
index 24ef4a4..50a02f9 100644 (file)
--- a/main.c
+++ b/main.c
@@ -5,7 +5,7 @@
  *
  * Part:        Main program structure.
  *
- * Version:     $Id: main.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: main.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -21,7 +21,9 @@
  */
 
 #include "main.h"
+#include "daemon.h"
 #include "memory.h"
+#include "parser.h"
 
 /* SIGHUP handler */
 void sighup(int sig)
@@ -36,13 +38,7 @@ void sighup(int sig)
 void sigchld(int sig)
 {
   int child;
-
   wait(&child);
-/*  child >>= 9;
- *  if (child)
- *    syslog(LOG_INFO, "Error from notify program, code:%d, %s"
- *                   , child, strerror(child));
- */
 }
 
 /* Signal wrapper */
@@ -77,57 +73,12 @@ void signal_init(void)
   signal_set (SIGCHLD, sigchld);
 }
 
-/* Daemonization function coming from zebra source code */
-int daemon(int nochdir, int noclose)
-{
-  pid_t pid;
-
-  /* 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)
-    exit (0);
-
-  /* Become session leader and get pid. */
-  pid = setsid();
-  if (pid < -1) {
-    perror ("setsid");
-    return -1;
-  }
-
-  /* Change directory to root. */
-  if (!nochdir)
-    chdir ("/");
-
-  /* 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);
-    }
-  }
-
-  umask (0);
-  return 0;
-}
-
 /* Usage function */
 static void usage(const char *prog)
 {
-  fprintf(stderr, "%s Version %s\n", PROG, VERSION);
+  fprintf(stderr, VERSION_STRING);
   fprintf(stderr,
-    "Usage:\n"
+    "\nUsage:\n"
     "  %s\n"
     "  %s -n\n"
     "  %s -f keepalived.conf\n"
@@ -175,7 +126,7 @@ static char *parse_cmdline(int argc, char **argv)
   /* The first option car */
   switch (c) {
     case 'v':
-      fprintf(stderr, "%s Version %s\n", PROG, VERSION);
+      fprintf(stderr, VERSION_STRING);
       exit(0);
       break;
     case 'h':
@@ -229,7 +180,6 @@ static char *parse_cmdline(int argc, char **argv)
 /* Entry point */
 int main(int argc, char **argv)
 {
-  configuration_data *conf_data;
   char *conf_file = NULL;
   thread thread;
 
@@ -244,58 +194,66 @@ int main(int argc, char **argv)
 
   openlog(PROG, LOG_PID | (debug & 1)?LOG_CONS:0
               , LOG_DAEMON);
-  syslog(LOG_INFO, "Starting "PROG" v"VERSION);
+  syslog(LOG_INFO, "Starting "VERSION_STRING);
 
   /* Check if keepalived is already running */
   if (keepalived_running()) {
-    syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
+    syslog(LOG_INFO, "Stopping "VERSION_STRING);
     closelog();
     exit(0);
   }
 
   /* daemonize process */
-  if (!(debug & 2)) {
-    daemon(0, 0);
-  }
+  if (!(debug & 2))
+    xdaemon(0, 0, 0);
 
   /* write the pidfile */
   if (!pidfile_write(getpid())) {
-    syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
+    syslog(LOG_INFO, "Stopping "VERSION_STRING);
     closelog();
     exit(0);
   }
 
+  /* Signal handling initialization  */
+  signal_init();
+
+  /* Create the master thread */
+  master = thread_make_master();
+
   /* Parse the configuration file */
-  if (!(conf_data = (configuration_data *)conf_reader(conf_file))) {
-    syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
+  init_checkers_queue();
+  init_keywords();
+  init_data(conf_file);
+  if (!conf_data) {
+    syslog(LOG_INFO, "Stopping "VERSION_STRING);
     closelog();
+    thread_destroy_master(master);
+    keepalived_free_final();
     exit(0);
   }
 
   /* SSL load static data & initialize common ctx context */
-  if (!(conf_data->ssldata = init_ssl_ctx(conf_data->ssldata))) {
+  if (!init_ssl_ctx()) {
     closelog();
+    thread_destroy_master(master);
+    keepalived_free_final();
     exit(0);
   }
 
   if (debug & 4) 
-    dump_conf(conf_data);
+    dump_data();
 
-  if (!init_services(conf_data->lvstopology)) {
-    syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
+  if (!init_services()) {
+    syslog(LOG_INFO, "Stopping "VERSION_STRING);
     closelog();
-    clear_conf(conf_data);
+    free_data();
     exit(0);
   }
 
-  /* Signal handling initialization  */
-  signal_init();
-
-  /* Create the master thread */
-  master = thread_make_master();
-
-  /* registering worker threads */
-  register_worker_thread(master, conf_data);
+  /* register workers threads */
+  register_checkers_thread();
+  vrrp_complete_init();
+  register_vrrp_thread();
 
   /* processing the master thread queues, return and execute one ready thread */
   while(thread_fetch(master, &thread)) {
@@ -311,14 +269,14 @@ int main(int argc, char **argv)
   }
 
   /* Reached when terminate signal catched */
-  syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
+  syslog(LOG_INFO, "Stopping "VERSION_STRING);
 
   /* Just cleanup memory & exit */
+  free_checkers_queue();
   thread_destroy_master(master);
-  clear_services(conf_data->lvstopology);
-  clear_vrrp_instance(conf_data->vrrp);
-  clear_ssl(conf_data->ssldata);
-  clear_conf(conf_data);
+  clear_services();
+  shutdown_vrrp_instances();
+  free_data();
 
   pidfile_rm();
 
diff --git a/main.h b/main.h
index ca47bf4..e615b0b 100644 (file)
--- a/main.h
+++ b/main.h
@@ -5,7 +5,7 @@
  *
  * Part:        Main program include file.
  *
- * Version:     $Id: main.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: main.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 /* local includes */
 #include "utils.h"
 #include "pidfile.h"
-#include "cfreader.h"
+#include "data.h"
 #include "scheduler.h"
 #include "ipwrapper.h"
 #include "smtp.h"
 #include "vrrp.h"
-#include "check_ssl.h"
+#include "check_api.h"
+//#include "check_ssl.h"
 
 /* global var */
 thread_master *master;
 unsigned int debug;
+data *conf_data;
 
-/* SSL support */
+/* extern prototypes */
 extern void clear_ssl(SSL_DATA *ssl);
-extern SSL_DATA *init_ssl_ctx(SSL_DATA *ssl);
+extern int init_ssl_ctx(void);
+extern void register_vrrp_thread(void);
 
 /* Build version */
-#define PROG    "keepalived"
-#define VERSION "0.4.9a (20/12, 2001)"
+#define PROG    "Keepalived"
 
+#define VERSION_CODE 0x000503
+#define DATE_CODE    0x160202
+
+#define KEEPALIVED_VERSION(version)    \
+       (version >> 16) & 0xFF,         \
+       (version >> 8) & 0xFF,          \
+       version & 0xFF
+
+#define VERSION_STRING PROG" v%d.%d.%d (%.2d/%.2d, 20%.2d)", \
+               KEEPALIVED_VERSION(VERSION_CODE), \
+               KEEPALIVED_VERSION(DATE_CODE)
 #endif
index bfe4adb..3a9440d 100644 (file)
--- a/memory.c
+++ b/memory.c
@@ -6,7 +6,7 @@
  * Part:        Memory management framework. This framework is used to
  *              find any memory leak.
  *
- * Version:     $Id: memory.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: memory.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Jan Holmberg, <jan@artech.net>
index bc614b3..a11cee0 100644 (file)
--- a/memory.h
+++ b/memory.h
@@ -5,7 +5,7 @@
  *
  * Part:        memory.c include file.
  *
- * Version:     $Id: memory.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: memory.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
  *              Jan Holmberg, <jan@artech.net>
@@ -57,4 +57,7 @@ extern void keepalived_free_final(void);
 
 #endif
 
+/* Common defines */
+#define FREE_PTR(P) if((P)) FREE((P));
+
 #endif
diff --git a/parser.c b/parser.c
new file mode 100644 (file)
index 0000000..e54ee8e
--- /dev/null
+++ b/parser.c
@@ -0,0 +1,624 @@
+/* 
+ * 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.5.3 2002/02/24 23:50:11 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 "check_api.h"
+
+/* global defs */
+static vector keywords;
+static int sublevel = 0;
+static FILE *stream;
+extern data *conf_data;
+
+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)
+{
+  int i;
+  struct keyword *keyword;
+
+  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 void dump_strvec(vector strvec)
+{
+  int i;
+  char *str;
+
+  if (!strvec)
+    return;
+
+  printf("String Vector : ");
+
+  for (i = 0; i < VECTOR_SIZE(strvec); i++) {
+    str = VECTOR_SLOT(strvec, i);
+    printf("[%i]=%s ", i, str);
+  }
+  printf("\n");
+}
+*/
+
+static void free_strvec(vector strvec)
+{
+  int i;
+  char *str;
+
+  if (!strvec)
+    return;
+
+  for (i=0; i < VECTOR_SIZE(strvec); i++)
+    if ((str = VECTOR_SLOT(strvec, i)) != NULL)
+      FREE(str);
+
+  vector_free(strvec);
+}
+
+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 == '\r' || *cp == '\n') &&
+         *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;
+    while (!(isspace((int) *cp) || *cp == '\r' || *cp == '\n') &&
+           *cp != '\0')
+      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 == '\n' || *cp == '\r') &&
+           *cp != '\0')
+      cp++;
+    if (*cp == '\0' || *cp == '!' || *cp == '#')
+      return strvec;
+  }
+}
+
+static char *read_line(char *buf, int size)
+{
+  return(fgets(buf, size, stream));
+}
+
+vector read_value_block(void)
+{
+  char buf[BUFSIZ];
+  int i;
+  char *str = NULL;
+  char *dup;
+  vector vec = NULL;
+  vector elements = vector_alloc();
+
+  while (read_line(buf, BUFSIZ)) {
+    vec = alloc_strvec(buf);
+    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);
+  }
+
+  return elements;
+}
+
+void *set_value(vector strvec)
+{
+  char *str = VECTOR_SLOT(strvec, 1);
+  int size = strlen(str);
+  void *alloc;
+
+  alloc = MALLOC(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)
+{
+  conf_data->smtp_server = inet_addr(VECTOR_SLOT(strvec, 1));
+}
+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_handler(vector strvec)
+{
+  alloc_vrrp(VECTOR_SLOT(strvec, 1));
+}
+static void vrrp_isync_handler(vector strvec)
+{
+  vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+  vrrp->isync = set_value(strvec);
+}
+static void vrrp_state_handler(vector strvec)
+{
+  char *str = VECTOR_SLOT(strvec, 1);
+  vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+  vrrp_rt *rt = vrrp->vsrv;
+
+  if (!strcmp(str, "MASTER")) {
+    rt->wantstate  = VRRP_STATE_MAST;
+    rt->init_state = VRRP_STATE_MAST;
+  } else {
+    rt->wantstate  = VRRP_STATE_BACK;
+    rt->init_state = VRRP_STATE_BACK;
+  }
+}
+static void vrrp_int_handler(vector strvec)
+{
+  vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+  vrrp->vsrv->vif->ifname = set_value(strvec);
+}
+static void vrrp_vrid_handler(vector strvec)
+{
+  vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+  vrrp->vsrv->vrid = atoi(VECTOR_SLOT(strvec, 1));
+
+  if (VRRP_IS_BAD_VID(vrrp->vsrv->vrid)) {
+    syslog(LOG_INFO, "VRRP Error : VRID not valid !\n");
+    syslog(LOG_INFO, "             must be between 1 & 255. reconfigure !\n");
+  }
+}
+static void vrrp_prio_handler(vector strvec)
+{
+  vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+  vrrp->vsrv->priority = atoi(VECTOR_SLOT(strvec, 1));
+
+  if (VRRP_IS_BAD_PRIORITY(vrrp->vsrv->priority)) {
+    syslog(LOG_INFO, "VRRP Error : Priority not valid !\n");
+    syslog(LOG_INFO, "             must be between 1 & 255. reconfigure !\n");
+    syslog(LOG_INFO, "             Using default value : 100\n");
+    vrrp->vsrv->priority = 100;
+  }
+}
+static void vrrp_adv_handler(vector strvec)
+{
+  vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+  vrrp->vsrv->adver_int = atoi(VECTOR_SLOT(strvec, 1));
+
+  if (VRRP_IS_BAD_ADVERT_INT(vrrp->vsrv->adver_int)) {
+    syslog(LOG_INFO, "VRRP Error : Advert intervall not valid !\n");
+    syslog(LOG_INFO, "             must be between less than 1sec.\n");
+    syslog(LOG_INFO, "             Using default value : 1sec\n");
+    vrrp->vsrv->adver_int = 1;
+  }
+  vrrp->vsrv->adver_int *= TIMER_HZ;
+}
+static void vrrp_debug_handler(vector strvec)
+{
+  vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+  vrrp->vsrv->debug = atoi(VECTOR_SLOT(strvec, 1));
+
+  if (VRRP_IS_BAD_DEBUG_INT(vrrp->vsrv->debug)) {
+    syslog(LOG_INFO, "VRRP Error : Debug intervall not valid !\n");
+    syslog(LOG_INFO, "             must be between 0-4\n");
+    vrrp->vsrv->debug = 0;
+  }
+}
+static void vrrp_preempt_handler(vector strvec)
+{
+  vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+  vrrp->vsrv->preempt = !vrrp->vsrv->preempt;
+}
+static void vrrp_notify_handler(vector strvec)
+{
+  vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+  char *str = VECTOR_SLOT(strvec, 1);
+  int size = sizeof(vrrp->vsrv->notify_file);
+
+  memcpy(vrrp->vsrv->notify_file, str, size);
+  vrrp->vsrv->notify_exec = 1;
+}
+static void vrrp_auth_type_handler(vector strvec)
+{
+  vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+  char *str = VECTOR_SLOT(strvec, 1);
+
+  if (!strcmp(str, "AH"))
+    vrrp->vsrv->vif->auth_type = VRRP_AUTH_AH;
+  else
+    vrrp->vsrv->vif->auth_type = VRRP_AUTH_PASS;
+}
+static void vrrp_auth_pass_handler(vector strvec)
+{
+  vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+  char *str = VECTOR_SLOT(strvec, 1);
+  int size = sizeof(vrrp->vsrv->vif->auth_data);
+
+  memcpy(vrrp->vsrv->vif->auth_data, str, size);
+}
+static void vrrp_vip_handler(vector strvec)
+{
+  vector vips = read_value_block();
+  int i;
+  char *str;
+
+  for (i = 0; i < VECTOR_SIZE(vips); i++) {
+    str = VECTOR_SLOT(vips, i);
+    alloc_vrrp_vip(str);
+  }
+
+  free_strvec(vips);
+}
+
+/* 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);
+  vs->nat_mask = inet_addr(VECTOR_SLOT(strvec, 1));
+}
+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 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;
+}
+
+/* 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));
+}
+
+/* recursive configuration stream handler */
+static void process_stream(vector keywords)
+{
+  int i;
+  struct keyword *keyword;
+  char *str;
+  char buf[BUFSIZ];
+  vector strvec;
+
+  if (!read_line(buf, BUFSIZ))
+    return;
+
+  strvec = alloc_strvec(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);
+}
+
+void 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_instance",                &vrrp_handler);
+  install_keyword("state",                     &vrrp_state_handler);
+  install_keyword("interface",                 &vrrp_int_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("sync_instance",             &vrrp_isync_handler);
+  install_keyword("preempt",                   &vrrp_preempt_handler);
+  install_keyword("debug",                     &vrrp_debug_handler);
+  install_keyword("notify",                    &vrrp_notify_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();
+
+  /* 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("protocol",                  &proto_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();
+}
+
+void init_data(char *conf_file)
+{
+  conf_data = NULL;
+  stream = fopen((conf_file)?conf_file:CONF, "r");
+  if (!stream) {
+    syslog(LOG_INFO, "Configuration file open problem...\n");
+    return;
+  }
+
+  /* Init data structure */
+  conf_data = alloc_data();
+
+  /* Stream handling */
+  process_stream(keywords);
+
+/* Dump configuration *
+
+  vector_dump(keywords);
+  dump_keywords(keywords, 0);
+  free_keywords(keywords);
+*/
+
+  fclose(stream);
+  free_keywords(keywords);
+}
diff --git a/parser.h b/parser.h
new file mode 100644 (file)
index 0000000..b531b15
--- /dev/null
+++ b/parser.h
@@ -0,0 +1,57 @@
+/* 
+ * 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:        cfreader.c include file.
+ *  
+ * Version:     $Id: parser.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ *
+ * Author:      Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _PARSER_H
+#define _PARSER_H
+
+/* system includes */
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <syslog.h>
+#include <ctype.h>
+
+/* local includes */
+#include "data.h"
+#include "vector.h"
+
+/* Global definitions */
+#define CONF "/etc/keepalived/keepalived.conf"
+#define EOB  "}"
+
+/* ketword definition */
+struct keyword {
+  char *string;
+  void (*handler) (vector);
+  vector sub;
+};
+
+
+/* Prototypes */
+extern void init_keywords(void);
+extern void init_data(char *conf_file);
+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);
+
+#endif
index 3b3a8b1..c3efb9f 100644 (file)
--- a/pidfile.c
+++ b/pidfile.c
@@ -5,7 +5,7 @@
  *
  * Part:        pidfile utility.
  *
- * Version:     $Id: pidfile.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: pidfile.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index c396642..13c020f 100644 (file)
--- a/pidfile.h
+++ b/pidfile.h
@@ -5,7 +5,7 @@
  *
  * Part:        pidfile.c include file.
  *
- * Version:     $Id: pidfile.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: pidfile.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 6644fde..a8aa270 100644 (file)
@@ -7,7 +7,7 @@
  *              the thread management routine (thread.c) present in the 
  *              very nice zebra project (http://www.zebra.org).
  *
- * Version:     $Id: scheduler.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: scheduler.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -31,37 +31,6 @@ thread_master *thread_make_master(void)
   thread_master *new;
 
   new = (thread_master *)MALLOC(sizeof(thread_master));
-
-  return new;
-}
-
-/* Make a new http thread arg */
-http_thread_arg *thread_http_checker_arg_new(void)
-{
-  http_thread_arg *new;
-
-  /* Allocate & prepare the thread argument structure */
-  new = (http_thread_arg *)MALLOC(sizeof(http_thread_arg));
-
-  return new;
-}
-
-/* Make a new global thread arg */
-thread_arg *thread_arg_new(configuration_data *root
-                          , virtualserver *vserver
-                          , realserver *rserver)
-{
-  thread_arg *new;
-
-  /* Allocate & prepare the thread argument structure */
-  new = (thread_arg *)MALLOC(sizeof(thread_arg));
-
-  /* Assign structure elements */
-  new->root = root;
-  new->vs = vserver;
-  new->svr = rserver;
-  new->checker_arg = NULL;
-
   return new;
 }
 
@@ -93,27 +62,13 @@ void thread_list_add_before(thread_list *list
   list->count++;
 }
 
-/* timer compare */
-int thread_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;
-}
-
 /* 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 (thread_timer_cmp (thread->sands, tt->sands) <= 0)
+    if (timer_cmp (thread->sands, tt->sands) <= 0)
       break;
 
   if (tt)
@@ -146,22 +101,11 @@ static void thread_clean_unuse(thread_master *m)
   thread = m->unuse.head;
   while (thread) {
     struct _thread *t;
-    thread_arg *ta;
 
     t = thread;
     thread = t->next;
 
     thread_list_delete(&m->unuse, t);
-    ta = t->arg;
-
-    /* thread_arg memory cleanup */
-    if (ta) {
-      if (ta->checker_arg)
-        FREE(ta->checker_arg);
-      /* Free the arg if it is a thread_arg entry. */
-      if (ta->vs)
-        FREE(ta);
-    }
 
     /* free the thread */
     FREE(t);
@@ -244,7 +188,7 @@ thread *thread_add_read(thread_master *m
                        , long timer)
 {
   thread *thread;
-  TIMEVAL timer_now;
+  TIMEVAL time_now;
 
   assert(m != NULL);
 
@@ -263,14 +207,14 @@ thread *thread_add_read(thread_master *m
   thread->u.fd = fd;
 
   /* Compute read timeout value */
-  gettimeofday(&timer_now, NULL);
+  time_now = timer_now();
   if (timer >= TIMER_MAX_SEC) {
-    timer_now.tv_sec  += timer / TIMER_SEC_MICRO;
-    timer_now.tv_usec += timer % TIMER_SEC_MICRO;
+    time_now.tv_sec  += timer / TIMER_HZ;
+    time_now.tv_usec += timer % TIMER_HZ;
   } else
-    timer_now.tv_sec += timer;
+    time_now.tv_sec += timer;
 
-  thread->sands = timer_now;
+  thread->sands = time_now;
 
   /* Sort the thread. */
   thread_list_add_timeval(&m->read, thread); 
@@ -286,7 +230,7 @@ thread *thread_add_write(thread_master *m
                         , long timer)
 {
   thread *thread;
-  TIMEVAL timer_now;
+  TIMEVAL time_now;
 
   assert(m != NULL);
 
@@ -305,14 +249,14 @@ thread *thread_add_write(thread_master *m
   thread->u.fd = fd;
 
   /* Compute write timeout value */
-  gettimeofday(&timer_now,NULL);
+  time_now = timer_now();
   if (timer >= TIMER_MAX_SEC) {
-    timer_now.tv_sec  += timer / TIMER_SEC_MICRO;
-    timer_now.tv_usec += timer % TIMER_SEC_MICRO;
+    time_now.tv_sec  += timer / TIMER_HZ;
+    time_now.tv_usec += timer % TIMER_HZ;
   } else
-    timer_now.tv_sec += timer;
+    time_now.tv_sec += timer;
 
-  thread->sands = timer_now;
+  thread->sands = time_now;
 
   /* Sort the thread. */
   thread_list_add_timeval(&m->write, thread); 
@@ -327,7 +271,7 @@ thread *thread_add_timer (thread_master *m
                          , long timer)
 {
   thread *thread;
-  TIMEVAL timer_now;
+  TIMEVAL time_now;
 
   assert(m != NULL);
 
@@ -339,14 +283,14 @@ thread *thread_add_timer (thread_master *m
   thread->arg = arg;
 
   /* Do we need jitter here? */
-  gettimeofday (&timer_now, NULL);
+  time_now = timer_now();
   if (timer >= TIMER_MAX_SEC) {
-    timer_now.tv_sec  += timer / TIMER_SEC_MICRO;
-    timer_now.tv_usec += timer % TIMER_SEC_MICRO;
+    time_now.tv_sec  += timer / TIMER_HZ;
+    time_now.tv_usec += timer % TIMER_HZ;
   } else
-    timer_now.tv_sec += timer;
+    time_now.tv_sec += timer;
 
-  thread->sands = timer_now;
+  thread->sands = time_now;
 
   /* Sort by timeval. */
   thread_list_add_timeval(&m->timer, thread); 
@@ -446,61 +390,36 @@ void thread_cancel_event(thread_master *m, void *arg)
   }
 }
 
-/* timer sub */
-TIMEVAL thread_timer_sub(TIMEVAL a, TIMEVAL b)
-{
-  TIMEVAL 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_SEC_MICRO;
-    ret.tv_sec--;
-  }
-
-  return ret;
-}
-
-static int thread_timer_null(TIMEVAL timer)
-{
-  if (timer.tv_sec == 0 && timer.tv_usec == 0)
-    return 1;
-  else
-    return 0;
-}
-
 /* Compute the wait timer. Take care of timeouted fd */
 TIMEVAL *thread_compute_timer(thread_master *m, TIMEVAL *timer_wait)
 {
-  TIMEVAL timer_now;
+  TIMEVAL time_now;
   TIMEVAL timer_min;
 
-  timer_min.tv_sec = 0;
-  timer_min.tv_usec = 0;
-  gettimeofday (&timer_now, NULL);
+  TIMER_RESET(timer_min);
+  time_now = timer_now();
 
   if (m->timer.head)
     timer_min = m->timer.head->sands;
 
   if (m->write.head) {
-    if (!thread_timer_null(timer_min)) {
-      if (thread_timer_cmp(m->write.head->sands, timer_min) <= 0)
+    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 (!thread_timer_null(timer_min)) {
-      if (thread_timer_cmp(m->read.head->sands, timer_min) <= 0)
+    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 (!thread_timer_null(timer_min)) {
-    timer_min = thread_timer_sub (timer_min, timer_now);
+  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;
@@ -521,7 +440,7 @@ thread *thread_fetch(thread_master *m, thread *fetch)
   fd_set readfd;
   fd_set writefd;
   fd_set exceptfd;
-  TIMEVAL timer_now;
+  TIMEVAL time_now;
   TIMEVAL *timer_wait;
 
   assert(m != NULL);
@@ -560,8 +479,8 @@ retry:  /* When thread can't fetch try to find next thread again. */
   timer_wait = thread_compute_timer(m, timer_wait);
 
   /* Call select function. */
-  readfd = m->readfd;
-  writefd = m->writefd;
+  readfd   = m->readfd;
+  writefd  = m->writefd;
   exceptfd = m->exceptfd;
 
   ret = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
@@ -578,7 +497,7 @@ retry:  /* When thread can't fetch try to find next thread again. */
   }
 
   /* Read thead. */
-  gettimeofday (&timer_now, NULL);
+  time_now = timer_now();
   thread = m->read.head;
 
   while (thread) {
@@ -594,7 +513,7 @@ retry:  /* When thread can't fetch try to find next thread again. */
       thread_list_add (&m->ready, t);
       t->type = THREAD_READY;
     } else {
-      if (thread_timer_cmp(timer_now, t->sands) >= 0) {
+      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);
@@ -604,7 +523,7 @@ retry:  /* When thread can't fetch try to find next thread again. */
   }
 
   /* Write thead. */
-  gettimeofday (&timer_now, NULL);
+  time_now = timer_now();
   thread = m->write.head;
 
   while (thread) {
@@ -620,7 +539,7 @@ retry:  /* When thread can't fetch try to find next thread again. */
       thread_list_add (&m->ready, t);
       t->type = THREAD_READY;
     } else {
-      if (thread_timer_cmp(timer_now, t->sands) >= 0) {
+      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);
@@ -632,7 +551,7 @@ retry:  /* When thread can't fetch try to find next thread again. */
   /*...*/
 
   /* Timer update. */
-  gettimeofday (&timer_now, NULL);
+  time_now = timer_now();
 
   thread = m->timer.head;
   while (thread) {
@@ -641,7 +560,7 @@ retry:  /* When thread can't fetch try to find next thread again. */
     t = thread;
     thread = t->next;
 
-    if (thread_timer_cmp (timer_now, t->sands) >= 0) {
+    if (timer_cmp (time_now, t->sands) >= 0) {
       thread_list_delete (&m->timer, t);
       thread_list_add (&m->ready, t);
       t->type = THREAD_READY;
@@ -674,77 +593,5 @@ unsigned long int thread_get_id(void)
 void thread_call(thread *thread)
 {
   thread->id = thread_get_id ();
-  (*thread->func)(thread);
-}
-
-/* Register worker thread. One per realserver of each virtualserver */
-void register_vs_worker_thread(thread_master *master
-                              , configuration_data *root
-                              , virtualserver *lstptr)
-{
-  realserver *pointersvr;
-  thread_arg *thread_arg;
-
-  pointersvr = lstptr->svr;
-
-  while (lstptr->svr) {
-
-    switch (lstptr->svr->method->type) {
-      /* Implemented section */
-      case TCP_CHECK_ID:
-      case HTTP_GET_ID:
-      case SSL_GET_ID:
-      case MISC_CHECK_ID:
-        thread_arg = thread_arg_new(root, lstptr, lstptr->svr);
-
-        switch (lstptr->svr->method->type ) {
-          case TCP_CHECK_ID:
-            thread_add_timer(master, tcp_connect_thread, thread_arg
-                                   , BOOTSTRAP_DELAY);
-            break;
-          case HTTP_GET_ID:
-          case SSL_GET_ID:
-            thread_arg->checker_arg = (http_thread_arg *)thread_http_checker_arg_new();
-            thread_add_timer(master, http_connect_thread, thread_arg
-                                   , BOOTSTRAP_DELAY);
-            break;
-          case MISC_CHECK_ID:
-            thread_add_timer(master, misc_check_thread, thread_arg
-                                   , BOOTSTRAP_DELAY);
-            break;
-        }
-
-        break;
-
-      /* Not yet implemented section */
-      case LDAP_GET_ID:
-        break;
-      default:
-        break;
-    }
-
-    lstptr->svr = (realserver *)lstptr->svr->next;
-  }
-
-  lstptr->svr = pointersvr;
-}
-
-/* Register each virtualserver realservers worker thread */
-void register_worker_thread(thread_master *master, configuration_data *lstptr)
-{
-  virtualserver *pointervs;
-
-  /* register VRRP instances dispatcher */
-  if (lstptr->vrrp)
-    thread_add_event(master, vrrp_dispatcher_init_thread,
-                     lstptr->vrrp, VRRP_DISPATCHER);
-
-  /* register VS specifics threads */
-  pointervs = lstptr->lvstopology;
-  while (lstptr->lvstopology) {
-    register_vs_worker_thread(master, lstptr, lstptr->lvstopology);
-
-    lstptr->lvstopology = (virtualserver *)lstptr->lvstopology->next;
-  }
-  lstptr->lvstopology = pointervs;
+  (*thread->func) (thread);
 }
index c661449..9838e91 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        scheduler.c include file.
  *
- * Version:     $Id: scheduler.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: scheduler.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include <assert.h>
 #include <fcntl.h>
 #include <errno.h>
-
-/* local includes */
-#include "cfreader.h"
-#include "check.h"
+#include <syslog.h>
+#include "timer.h"
 
 /* Thread itself. */
-typedef struct timeval TIMEVAL;
 typedef struct _thread {
   unsigned long id;
   unsigned char type;                  /* thread type */
@@ -83,69 +80,38 @@ typedef struct _thread_master {
 #define THREAD_TERMINATE      8
 
 /* MICRO SEC def */
-#define TIMER_SEC_MICRO 1000000
-#define TIMER_MAX_SEC   1000
 #define BOOTSTRAP_DELAY 1
 
 /* Macros. */
 #define THREAD_ARG(X) ((X)->arg)
-#define THREAD_ARG_CHECKER_ARG(X) ((X)->checker_arg)
 #define THREAD_FD(X)  ((X)->u.fd)
 #define THREAD_VAL(X) ((X)->u.val)
 
 /* Prototypes. */
 thread_master *thread_make_master(void);
-
 thread *thread_add_terminate_event(thread_master *m);
-
 void thread_destroy_master(thread_master *m);
-
-thread_arg *thread_arg_new(configuration_data *root
-                          , virtualserver *vserver
-                          , realserver *rserver);
-
 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);
 
-int thread_timer_cmp(TIMEVAL a, TIMEVAL b);
-
-TIMEVAL thread_timer_sub(TIMEVAL a, TIMEVAL b);
-
-void register_worker_thread(thread_master *master
-                           , configuration_data *lstptr);
-
-/* extern prototypes */
-extern int tcp_connect_thread(thread *thread);
-extern int http_connect_thread(thread *thread);
-extern int ssl_connect_thread(thread *thread);
-extern int misc_check_thread(thread *thread);
-extern int vrrp_dispatcher_init_thread(thread *thread);
-
 #endif
diff --git a/smtp.c b/smtp.c
index c859cf1..b3c6d80 100644 (file)
--- a/smtp.c
+++ b/smtp.c
@@ -7,7 +7,7 @@
  *              using the smtp protocol according to the RFC 821. A non blocking
  *              timeouted connection is used to handle smtp protocol.
  *
- * Version:     $Id: smtp.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: smtp.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 
 #include "smtp.h"
 #include "memory.h"
+#include "list.h"
+
+extern data *conf_data;
 
 /* static prototype */
-static int smtp_send_cmd_thread(thread *thread);
+static int smtp_send_cmd_thread(thread *);
 
-static void free_smtp_arg(smtp_thread_arg *smtp_arg)
+static void free_smtp_all(smtp_thread_arg *smtp_arg)
 {
   FREE(smtp_arg->subject);
   FREE(smtp_arg->body);
   FREE(smtp_arg);
 }
 
-static void free_smtp_all(thread_arg *thread_arg)
+static char *fetch_next_email(smtp_thread_arg *smtp_arg)
 {
-  free_smtp_arg(THREAD_ARG_CHECKER_ARG(thread_arg));
-  FREE(thread_arg);
-}
-
-static char *fetch_next_email(thread_arg *thread_arg)
-{
-  smtp_thread_arg *smtp_arg;
-  int i = 0;
-
-  smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-
-  for (i=0; i<smtp_arg->email_it; i++)
-    thread_arg->root->email = (notification_email *)thread_arg->root->email->next;
-
-  if (thread_arg->root->email)
-    return thread_arg->root->email->addr;
-
-  return NULL;
+  return list_element(conf_data->email, smtp_arg->email_it);
 }
 
 static int smtp_read_cmd_thread(thread *thread)
 {
-  thread_arg *thread_arg;
   smtp_thread_arg *smtp_arg;
-  notification_email *pointeremail;
   char *fetched_email;
   long total_length = 0;
   int rcv_buffer_size = 0;
   char *buffer;
   char *buffer_tmp;
 
-  thread_arg = THREAD_ARG(thread);
-  smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+  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_ntoa(thread_arg->root->smtp_server),
+                      ip_ntoa(conf_data->smtp_server),
                       SMTP_PORT);
 #endif
-    free_smtp_all(thread_arg);
-    thread_arg->checker_arg = NULL;
+    free_smtp_all(smtp_arg);
     close(thread->u.fd);
     return 0;
   }
 
   /* Allocate the get buffers */
-  buffer = (char *)MALLOC(SMTP_BUFFER_MAX);
+  buffer     = (char *)MALLOC(SMTP_BUFFER_MAX);
   buffer_tmp = (char *)MALLOC(SMTP_BUFFER_LENGTH);
 
   /* Cleanup the room */
@@ -95,12 +77,11 @@ static int smtp_read_cmd_thread(thread *thread)
     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_ntoa(thread_arg->root->smtp_server),
-                        SMTP_PORT);
+      syslog(LOG_DEBUG, "Error reading data to remote SMTP server [%s:%d]."
+                      , ip_ntoa(conf_data->smtp_server)
+                      , SMTP_PORT);
 #endif
-      free_smtp_all(thread_arg);
-      thread_arg->checker_arg = NULL;
+      free_smtp_all(smtp_arg);
       close(thread->u.fd);
       FREE(buffer);
       FREE(buffer_tmp);
@@ -111,12 +92,11 @@ static int smtp_read_cmd_thread(thread *thread)
     if (total_length >= SMTP_BUFFER_MAX) {
 #ifdef _DEBUG_
       syslog(LOG_DEBUG, "Received buffer from remote SMTP server [%s:%d]"
-                        " overflow our get read buffer length.",
-                        inet_ntoa(thread_arg->root->smtp_server),
-                        SMTP_PORT);
+                        " overflow our get read buffer length."
+                      , ip_ntoa(conf_data->smtp_server)
+                      , SMTP_PORT);
 #endif
-      free_smtp_all(thread_arg);
-      thread_arg->checker_arg = NULL;
+      free_smtp_all(smtp_arg);
       close(thread->u.fd);
       FREE(buffer);
       FREE(buffer_tmp);
@@ -135,85 +115,84 @@ end:
 
   /* setting the next stage */
   switch (smtp_arg->stage) {
-    case connection:
+    case CONNECTION:
       if (memcmp(buffer, SMTP_CONNECT, 3) == 0) {
-        smtp_arg->stage = helo;
+        smtp_arg->stage = HELO;
       } else {
         syslog(LOG_DEBUG, "Error connecting smtp server : [%s]", buffer);
-        smtp_arg->stage = error;
+        smtp_arg->stage = ERROR;
       }
       break;
 
-    case helo:
+    case HELO:
       if (memcmp(buffer, SMTP_HELO, 3) == 0) {
-        smtp_arg->stage = mail;
+        smtp_arg->stage = MAIL;
       } else {
         syslog(LOG_DEBUG, "Error processing HELO cmd : [%s]", buffer);
-        smtp_arg->stage = error;
+        smtp_arg->stage = ERROR;
       }
       break;
 
-    case mail:
+    case MAIL:
       if (memcmp(buffer, SMTP_MAIL_FROM, 3) == 0) {
-        smtp_arg->stage = rcpt;
+        smtp_arg->stage = RCPT;
       } else {
         syslog(LOG_DEBUG, "Error processing MAIL FROM cmd : [%s]", buffer);
-        smtp_arg->stage = error;
+        smtp_arg->stage = ERROR;
       }
       break;
 
-    case rcpt:
+    case RCPT:
       if (memcmp(buffer, SMTP_RCPT_TO, 3) == 0) {
         smtp_arg->email_it++;
 
-        pointeremail = thread_arg->root->email;
-        fetched_email = fetch_next_email(thread_arg);
-        thread_arg->root->email = pointeremail;
+        fetched_email = fetch_next_email(smtp_arg);
 
         if (!fetched_email)
-          smtp_arg->stage = data;
+          smtp_arg->stage = DATA;
       } else {
         syslog(LOG_DEBUG, "Error processing RCPT TO cmd : [%s]", buffer);
-        smtp_arg->stage = error;
+        smtp_arg->stage = ERROR;
       }
       break;
 
-    case data:
+    case DATA:
       if (memcmp(buffer, SMTP_DATA, 3) == 0) {
-        smtp_arg->stage = body;
+        smtp_arg->stage = BODY;
       } else {
         syslog(LOG_DEBUG, "Error processing DATA cmd : [%s]", buffer);
-        smtp_arg->stage = error;
+        smtp_arg->stage = ERROR;
       }
       break;
 
-    case body:
+    case BODY:
       if (memcmp(buffer, SMTP_DOT, 3) == 0) {
-        smtp_arg->stage = quit;
+        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;
+        smtp_arg->stage = ERROR;
       }
       break;
 
-    case quit:
+    case QUIT:
       /* final state, we are disconnected from the remote host */
-      free_smtp_all(thread_arg);
-      thread_arg->checker_arg = NULL;
+      free_smtp_all(smtp_arg);
       close(thread->u.fd);
       FREE(buffer);
       FREE(buffer_tmp);
       return 0;
       break;
 
-    case error:
+    case ERROR:
       break;
   }
 
   /* Registering next smtp command processing thread */
-  thread_add_write(thread->master, smtp_send_cmd_thread, thread_arg, thread->u.fd,
-                   thread_arg->root->smtp_connection_to);
+  thread_add_write(thread->master, smtp_send_cmd_thread
+                                 , smtp_arg
+                                 , thread->u.fd
+                                 , conf_data->smtp_connection_to);
 
   FREE(buffer);
   FREE(buffer_tmp);
@@ -237,23 +216,19 @@ static char *get_local_name(void)
 
 static int smtp_send_cmd_thread(thread *thread)
 {
-  thread_arg *thread_arg;
   smtp_thread_arg *smtp_arg;
-  notification_email *pointeremail;
   char *fetched_email;
   char *buffer;
 
-  thread_arg = THREAD_ARG(thread);
-  smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+  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_ntoa(thread_arg->root->smtp_server),
-                      SMTP_PORT);
+    syslog(LOG_DEBUG, "Timeout sending data to remote SMTP server [%s:%d]."
+                    , ip_ntoa(conf_data->smtp_server)
+                    , SMTP_PORT);
 #endif
-    free_smtp_all(thread_arg);
-    thread_arg->checker_arg = NULL;
+    free_smtp_all(smtp_arg);
     close(thread->u.fd);
     return 0;
   }
@@ -262,70 +237,69 @@ static int smtp_send_cmd_thread(thread *thread)
   buffer = (char *)MALLOC(SMTP_BUFFER_MAX);
 
   switch (smtp_arg->stage) {
-    case connection:
+    case CONNECTION:
       break;
 
-    case helo:
-      snprintf(buffer, TEMP_BUFFER_LENGTH, SMTP_HELO_CMD, get_local_name());
+    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;
+        smtp_arg->stage = ERROR;
       break;
 
-    case mail:
-      snprintf(buffer, TEMP_BUFFER_LENGTH, SMTP_MAIL_CMD, thread_arg->root->email_from);
+    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;
+        smtp_arg->stage = ERROR;
       break;
 
-    case rcpt:
+    case RCPT:
       /* We send RCPT TO command multiple time to add all our email receivers.
        * --rfc821.3.1
        */
-      pointeremail = thread_arg->root->email;
-      fetched_email = fetch_next_email(thread_arg);
-      thread_arg->root->email = pointeremail;
+      fetched_email = fetch_next_email(smtp_arg);
 
-      snprintf(buffer, TEMP_BUFFER_LENGTH, SMTP_RCPT_CMD, fetched_email);
+      snprintf(buffer, SMTP_BUFFER_MAX, SMTP_RCPT_CMD, fetched_email);
       if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
-        smtp_arg->stage = error;
+        smtp_arg->stage = ERROR;
       break;
 
-    case data:
+    case DATA:
       if (send(thread->u.fd, SMTP_DATA_CMD, strlen(SMTP_DATA_CMD), 0) == -1)
-        smtp_arg->stage = error;
+        smtp_arg->stage = ERROR;
       break;
 
-    case body:
-      snprintf(buffer, TEMP_BUFFER_LENGTH, SMTP_SUBJECT_CMD, smtp_arg->subject);
+    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;
+        smtp_arg->stage = ERROR;
 
       memset(buffer, 0, SMTP_BUFFER_MAX);
-      snprintf(buffer, TEMP_BUFFER_LENGTH, SMTP_BODY_CMD, smtp_arg->body);
+      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;
+        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;
+        smtp_arg->stage = ERROR;
       break;
 
-    case quit:
+    case QUIT:
       if (send(thread->u.fd, SMTP_QUIT_CMD, strlen(SMTP_QUIT_CMD), 0) == -1)
-        smtp_arg->stage = error;
+        smtp_arg->stage = ERROR;
       break;
 
-    case error:
+    case ERROR:
 #ifdef _DEBUG_
-      syslog(LOG_DEBUG, "Can not send data to remote SMTP server [%s:%d].",
-                        inet_ntoa(thread_arg->root->smtp_server),
-                        SMTP_PORT);
+      syslog(LOG_DEBUG, "Can not send data to remote SMTP server [%s:%d]."
+                      , ip_ntoa(conf_data->smtp_server)
+                      , SMTP_PORT);
 #endif
       /* we just cleanup the room */
-      free_smtp_all(thread_arg);
-      thread_arg->checker_arg = NULL;
+      free_smtp_all(smtp_arg);
       close(thread->u.fd);
       FREE(buffer);
       return 0;
@@ -335,8 +309,10 @@ static int smtp_send_cmd_thread(thread *thread)
 //printf("Sending : %s", buffer);
 
   /* Registering next smtp command processing thread */
-  thread_add_read(thread->master, smtp_read_cmd_thread, thread_arg, thread->u.fd,
-                  thread_arg->root->smtp_connection_to);
+  thread_add_read(thread->master, smtp_read_cmd_thread
+                                , smtp_arg
+                                , thread->u.fd
+                                , conf_data->smtp_connection_to);
 
   FREE(buffer);
   return 0;
@@ -345,34 +321,33 @@ static int smtp_send_cmd_thread(thread *thread)
 /* SMTP checkers threads */
 static int smtp_check_thread(thread *thread)
 {
-  thread_arg *thread_arg;
   smtp_thread_arg *smtp_arg;
   int status;
 
-  thread_arg = THREAD_ARG(thread);
-  smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+  smtp_arg = THREAD_ARG(thread);
 
-  status = tcp_socket_state(thread->u.fd, thread, smtp_check_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_ntoa(thread_arg->root->smtp_server),
-                        SMTP_PORT);
+      syslog(LOG_DEBUG, "Error connecting SMTP server [%s:%d]."
+                      , ip_ntoa(conf_data->smtp_server)
+                      , SMTP_PORT);
 #endif
-      free_smtp_all(thread_arg);
-      thread_arg->checker_arg = NULL;
+      free_smtp_all(smtp_arg);
       break;
 
     case connect_timeout:
 #ifdef _DEBUG_
-      syslog(LOG_DEBUG, "Timeout writing data to SMTP server [%s:%d].",
-                        inet_ntoa(thread_arg->root->smtp_server),
-                        SMTP_PORT);
+      syslog(LOG_DEBUG, "Timeout writing data to SMTP server [%s:%d]."
+                      , ip_ntoa(conf_data->smtp_server)
+                      , SMTP_PORT);
 #endif
-      free_smtp_all(thread_arg);
-      thread_arg->checker_arg = NULL;
+      free_smtp_all(smtp_arg);
       break;
 
     case connect_success:
@@ -380,13 +355,14 @@ static int smtp_check_thread(thread *thread)
        * Register the next step thread smtp_cmd_thread.
        */
 #ifdef _DEBUG_
-      syslog(LOG_DEBUG, "Remote SMTP server [%s:%d] connected.",
-                        inet_ntoa(thread_arg->root->smtp_server),
-                        SMTP_PORT);
+      syslog(LOG_DEBUG, "Remote SMTP server [%s:%d] connected."
+                      , ip_ntoa(conf_data->smtp_server)
+                      , SMTP_PORT);
 #endif
-
-      thread_add_write(thread->master, smtp_send_cmd_thread, thread_arg, thread->u.fd,
-                       thread_arg->root->smtp_connection_to);
+      thread_add_write(thread->master, smtp_send_cmd_thread
+                                     , smtp_arg
+                                     , thread->u.fd
+                                     , conf_data->smtp_connection_to);
       break;
   }
 
@@ -395,13 +371,11 @@ static int smtp_check_thread(thread *thread)
 
 static int smtp_connect_thread(thread *thread)
 {
-  thread_arg *thread_arg;
   smtp_thread_arg *smtp_arg;
   enum connect_result status;
   int fd;
 
-  thread_arg = THREAD_ARG(thread);
-  smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+  smtp_arg = THREAD_ARG(thread);
 
   if ( (fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
 #ifdef _DEBUG_
@@ -410,90 +384,87 @@ static int smtp_connect_thread(thread *thread)
     return 0;
   }
 
-  status = tcp_connect(fd, thread_arg->root->smtp_server.s_addr, htons(SMTP_PORT));
+  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_ntoa(thread_arg->root->smtp_server),
-                        SMTP_PORT);
+      syslog(LOG_DEBUG, "SMTP connection ERROR to [%s:%d]."
+                      , ip_ntoa(conf_data->smtp_server)
+                      , SMTP_PORT);
 #endif
-      free_smtp_all(thread_arg);
-      thread_arg->checker_arg = NULL;
+      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_ntoa(thread_arg->root->smtp_server),
-                        SMTP_PORT);
+      syslog(LOG_DEBUG, "Timeout connecting SMTP server [%s:%d]."
+                      , ip_ntoa(conf_data->smtp_server)
+                      , SMTP_PORT);
 #endif
-      free_smtp_all(thread_arg);
-      thread_arg->checker_arg = NULL;
+      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_ntoa(thread_arg->root->smtp_server),
-                        SMTP_PORT);
+      syslog(LOG_DEBUG, "SMTP connection SUCCESS to [%s:%d]."
+                      , ip_ntoa(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_ntoa(thread_arg->root->smtp_server),
-                        SMTP_PORT);
+      syslog(LOG_DEBUG, "SMTP connection to [%s:%d] now IN_PROGRESS."
+                      , ip_ntoa(conf_data->smtp_server)
+                      , SMTP_PORT);
 #endif
       break;
   }
 
   /* connection have succeeded or still in progress */
-  thread_add_write(thread->master, smtp_check_thread, thread_arg, fd,
-                   thread_arg->root->smtp_connection_to);
-
+  thread_add_write(thread->master, smtp_check_thread
+                                 , smtp_arg
+                                 , fd
+                                 , conf_data->smtp_connection_to);
   return 1;
 }
 
 void smtp_alert(thread_master *master
-                , configuration_data *root
-                , realserver *rserver
+                , real_server *rs
                 , const char *subject
                 , const char *body)
 {
-  thread_arg *thread_arg;
   smtp_thread_arg *smtp_arg;
 
   /* Only send mail if email specified */
-  if (root->email) {
-    /* allocate a new thread_arg */
-    thread_arg = thread_arg_new(root, NULL, NULL);
-
+  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_SUBJECT_LENGTH);
-    smtp_arg->body = (char *)MALLOC(MAX_BODY_LENGTH);
+    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->stage = connection; /* first smtp command set to HELO */
+    smtp_arg->stage = CONNECTION; /* first smtp command set to HELO */
 
     /* format subject if rserver is specified */
-    if (rserver)
-      snprintf(smtp_arg->subject, MAX_SUBJECT_LENGTH, "[%s] %s:%d - %s",
-               root->lvs_id, inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port), subject);
+    if (rs)
+      snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH, "[%s] %s:%d - %s"
+               , conf_data->lvs_id
+               , ip_ntoa(SVR_IP(rs))
+               , ntohs(SVR_PORT(rs))
+               , subject);
     else
-      snprintf(smtp_arg->subject, MAX_SUBJECT_LENGTH, "[%s] %s", root->lvs_id, subject);
+      snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH, "[%s] %s"
+                                , conf_data->lvs_id
+                                , subject);
 
     strncpy(smtp_arg->body, body, MAX_BODY_LENGTH);
 
-    thread_arg->checker_arg = smtp_arg;
-
-    thread_add_event(master, smtp_connect_thread, thread_arg, 0);
+    thread_add_event(master, smtp_connect_thread, smtp_arg, 0);
   }
 }
diff --git a/smtp.h b/smtp.h
index 771a07b..f77f73f 100644 (file)
--- a/smtp.h
+++ b/smtp.h
@@ -5,7 +5,7 @@
  *
  * Part:        smtp.c include file.
  *
- * Version:     $Id: smtp.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: smtp.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -20,8 +20,8 @@
  *              2 of the License, or (at your option) any later version.
  */
 
-#ifndef _HTTP_H
-#define _HTTP_H
+#ifndef _SMTP_H
+#define _SMTP_H
 
 /* globales includes */
 #include <netdb.h>
@@ -29,7 +29,7 @@
 #include <sys/utsname.h>
 
 /* local includes */
-#include "cfreader.h"
+#include "data.h"
 #include "scheduler.h"
 #include "layer4.h"
 
 
 /* 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 */
-#define MAX_SUBJECT_LENGTH 256
+#define MAX_HEADERS_LENGTH 256
 #define MAX_BODY_LENGTH    512
 
 typedef struct _smtp_thread_arg {
@@ -71,19 +71,17 @@ typedef struct _smtp_thread_arg {
 
 /* Smtp command string processing */
 #define SMTP_HELO_CMD    "HELO %s\n"
-#define SMTP_MAIL_CMD    "MAIL FROM:%s\n"
-#define SMTP_RCPT_CMD    "RCPT TO:%s\n"
+#define SMTP_MAIL_CMD    "MAIL FROM:<%s>\n"
+#define SMTP_RCPT_CMD    "RCPT TO:<%s>\n"
 #define SMTP_DATA_CMD    "DATA\n"
-#define SMTP_SUBJECT_CMD "Subject: %s\nX-Mailer: Keepalived\n\n"
+#define SMTP_HEADERS_CMD "From: %s\nSubject: %s\nX-Mailer: Keepalived\n\n"
 #define SMTP_BODY_CMD    "\n\n%s\n\n"
 #define SMTP_SEND_CMD    "\n.\n"
 #define SMTP_QUIT_CMD    "QUIT\n"
 
 /* Prototypes defs */
 extern void smtp_alert(thread_master *
-                       , configuration_data *
-                       , realserver *
+                       , real_server *
                        , const char *
                        , const char *);
-
 #endif
diff --git a/timer.c b/timer.c
new file mode 100644 (file)
index 0000000..bd839c2
--- /dev/null
+++ b/timer.c
@@ -0,0 +1,84 @@
+/* 
+ * 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:        Timer manipulations.
+ *  
+ * Version:     $Id: timer.c,v 0.5.3 2002/02/24 23:50:11 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 <string.h>
+#include "timer.h"
+
+/* set a timer to a specific value */
+TIMEVAL timer_dup(TIMEVAL b)
+{
+  TIMEVAL 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)
+{
+  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 ret;
+
+  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--;
+  }
+
+  return ret;
+}
+
+/* current time */
+TIMEVAL timer_now(void)
+{
+  TIMEVAL timer_now;
+
+  /* init timer */
+  TIMER_RESET(timer_now);
+  gettimeofday(&timer_now, NULL);
+
+  return timer_now;
+}
+
+/* timer sub from current time */
+TIMEVAL timer_sub_now(TIMEVAL a)
+{
+  return timer_sub(timer_now(), a);
+}
diff --git a/timer.h b/timer.h
new file mode 100644 (file)
index 0000000..ec8922c
--- /dev/null
+++ b/timer.h
@@ -0,0 +1,44 @@
+/* 
+ * 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:        timer.c include file.
+ *  
+ * Version:     $Id: timer.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ *
+ * Author:      Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _TIMER_H
+#define _TIMER_H
+
+#include <sys/time.h>
+
+typedef struct timeval TIMEVAL;
+
+/* macro utilities */
+#define TIMER_HZ      1000000
+#define TIMER_MAX_SEC 1000
+#define TIMER_SEC(T) ((T).tv_sec)
+#define TIMER_ISNULL(T) ((T).tv_sec == 0 && (T).tv_usec == 0)
+#define TIMER_RESET(T) (memset(&(T), 0, sizeof(struct timeval)))
+
+/* prototypes */
+extern TIMEVAL timer_now(void);
+extern TIMEVAL timer_dup(TIMEVAL b);
+extern int timer_cmp(TIMEVAL a, TIMEVAL b);
+extern TIMEVAL timer_sub(TIMEVAL a, TIMEVAL b);
+extern TIMEVAL timer_sub_now(TIMEVAL a);
+
+#endif
diff --git a/utils.c b/utils.c
index 10c7311..959f09d 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -5,7 +5,7 @@
  *
  * Part:        General program utils.
  *
- * Version:     $Id: utils.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: utils.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
diff --git a/utils.h b/utils.h
index 11dbbc8..1eb3d78 100644 (file)
--- a/utils.h
+++ b/utils.h
@@ -5,7 +5,7 @@
  *
  * Part:        utils.h include file.
  *
- * Version:     $Id: utils.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: utils.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
diff --git a/vector.c b/vector.c
new file mode 100644 (file)
index 0000000..0c16aaf
--- /dev/null
+++ b/vector.c
@@ -0,0 +1,71 @@
+/* 
+ * 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:        Vector structure manipulation.
+ *  
+ * Version:     $Id: vector.c,v 0.5.3 2002/02/24 23:50:11 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 "vector.h"
+#include "memory.h"
+
+/* 
+ * Initialize vector struct.
+ * allocalted 'size' slot elements then return vector.
+ */
+vector vector_alloc(void)
+{
+  vector v = (vector)MALLOC(sizeof(struct _vector));
+  return v;
+}
+
+/* allocated one slot */
+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);
+}
+
+/* Free memory vector allocation */
+void vector_free(vector v)
+{
+  FREE(v->slot);
+  FREE(v);
+}
+
+/* Set a vector slot value */
+void vector_set_slot(vector v, void *value)
+{
+  unsigned int i = v->allocated-1;
+
+  v->slot[i] = value;
+}
+
+/* dump vector slots */
+void vector_dump(vector v)
+{
+  int i;
+
+  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));
+}
diff --git a/vector.h b/vector.h
new file mode 100644 (file)
index 0000000..047287d
--- /dev/null
+++ b/vector.h
@@ -0,0 +1,45 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ * 
+ * Part:        vector.c include file.
+ *  
+ * Version:     $Id: vector.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
+ *
+ * Author:      Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+
+#ifndef _VECTOR_H
+#define _VECTOR_H
+
+/* vector definition */
+struct _vector {
+  unsigned int allocated;
+  void **slot;
+};
+typedef struct _vector *vector;
+
+#define VECTOR_DEFAULT_SIZE 1
+#define VECTOR_SLOT(V,E) ((V)->slot[(E)])
+#define VECTOR_SIZE(V)   ((V)->allocated)
+
+/* Prototypes */
+extern vector vector_alloc(void);
+extern void vector_alloc_slot(vector v);
+extern void vector_free(vector v);
+extern void vector_set_slot(vector v, void *value);
+extern void vector_dump(vector v);
+
+#endif
diff --git a/vrrp.c b/vrrp.c
index a9da7b5..83d00bf 100644 (file)
--- a/vrrp.c
+++ b/vrrp.c
@@ -8,7 +8,7 @@
  *              master fails, a backup server takes over.
  *              The original implementation has been made by jerome etienne.
  *
- * Version:     $Id: vrrp.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: vrrp.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -27,6 +27,7 @@
 #include "vrrp_scheduler.h"
 #include "vrrp.h"
 #include "memory.h"
+#include "list.h"
 
 /* Close all FDs >= a specified value */
 void closeall(int fd)
@@ -120,7 +121,6 @@ static int notify_exec( vrrp_rt *vsrv , char *cmd)
   exit(0);
 }
 
-
 /* compute checksum */
 static u_short in_csum( u_short *addr, int len, u_short csum)
 {
@@ -237,24 +237,22 @@ static int vrrp_handle_ipaddress(vrrp_rt *vsrv, int cmd)
   int i, err = 0;
   int retry;
   int ifidx = ifname_to_idx(vsrv->vif->ifname);
-  struct in_addr in;
 
   for(i = 0; i < vsrv->naddr; i++ ) {
     vip_addr *vadd = &vsrv->vaddr[i];
     retry ^= retry;
     if(!cmd && !vadd->deletable) continue;
 retry:
-    if (netlink_address_ipv4(ifidx , vadd->addr, cmd) < 0) {
+    if (netlink_address_ipv4(ifidx , ntohl(vadd->addr), cmd) < 0) {
       err = 1;
       vadd->deletable = 0;
-      in.s_addr = htonl(vadd->addr);
       syslog(LOG_INFO, "cant %s the address %s to %s\n"
                      , cmd ? "set" : "remove"
-                     , inet_ntoa(in)
+                     , ip_ntoa(vadd->addr)
                      , vsrv->vif->ifname);
       if (cmd == VRRP_IPADDRESS_ADD) {
         syslog(LOG_INFO, "try to delete eventual stalled ip");
-        netlink_address_ipv4(ifidx, vadd->addr, VRRP_IPADDRESS_DEL);
+        netlink_address_ipv4(ifidx, ntohl(vadd->addr), VRRP_IPADDRESS_DEL);
         if (!retry) {
           retry++;
           goto retry;
@@ -474,7 +472,7 @@ static int vrrp_in_chk(vrrp_rt *vsrv, char *buffer)
    * MUST verify that the Adver Interval in the packet is the same as
    * the locally configured for this virtual router
    */
-  if (vsrv->adver_int/VRRP_TIMER_HZ != hd->adver_int) {
+  if (vsrv->adver_int/TIMER_HZ != hd->adver_int) {
     syslog(LOG_INFO, "advertissement interval mismatch mine=%d rcved=%d"
                    , vsrv->adver_int, hd->adver_int);
     /* to prevent concurent VRID running => multiple master in 1 VRID */
@@ -631,7 +629,7 @@ static int vrrp_build_vrrp(vrrp_rt *vsrv, int prio, char *buffer, int buflen)
   hd->priority  = prio;
   hd->naddr  = vsrv->naddr;
   hd->auth_type  = vsrv->vif->auth_type;
-  hd->adver_int  = vsrv->adver_int/VRRP_TIMER_HZ;
+  hd->adver_int  = vsrv->adver_int/TIMER_HZ;
 
   /* copy the ip addresses */
   for( i = 0; i < vsrv->naddr; i++ ){
@@ -698,6 +696,8 @@ static int vrrp_send_pkt(vrrp_rt *vsrv, char *buffer, int buflen)
   memset(&from, 0 , sizeof(from));
   strcpy(from.sa_data, vsrv->vif->ifname);
 
+//print_buffer(buflen, buffer);
+
   /* send the data */
   len = sendto(fd, buffer, buflen, 0, &from, sizeof(from));
 
@@ -973,40 +973,6 @@ static int chk_min_cfg(vrrp_rt *vsrv)
   return 1;
 }
 
-/* compute vrrp structure */
-int complete_vrrp_init(vrrp_rt *vsrv)
-{
-  vrrp_if *vif = vsrv->vif;
-
-  /* complete the VMAC address */
-  vsrv->hwaddr[0] = 0x00;
-  vsrv->hwaddr[1] = 0x00;
-  vsrv->hwaddr[2] = 0x5E;
-  vsrv->hwaddr[3] = 0x00;
-  vsrv->hwaddr[4] = 0x01;
-  vsrv->hwaddr[5] = vsrv->vrid;
-
-  /* get the ip address */
-  vif->ipaddr = ifname_to_ip(vif->ifname);
-  if (!vif->ipaddr) {
-    syslog(LOG_INFO, "VRRP Error : no interface found : %s !\n", vif->ifname);
-    return 0;
-  }
-  /* get the hwaddr */
-  if (hwaddr_get(vif->ifname, vif->hwaddr, sizeof(vif->hwaddr))) {
-    syslog(LOG_INFO, "VRRP Error : Unreadable MAC"
-                     "address for interface : %s !\n", vif->ifname);
-    return 0;
-  }
-
-  vsrv->state = VRRP_STATE_INIT;
-  if (!vsrv->adver_int) vsrv->adver_int = VRRP_ADVER_DFL * VRRP_TIMER_HZ;
-  if (!vsrv->priority) vsrv->priority = VRRP_PRIO_DFL;
-  if (!vsrv->preempt) vsrv->preempt = VRRP_PREEMPT_DFL;
-
-  return(chk_min_cfg(vsrv));
-}
-
 /* open the socket and join the multicast group. */
 int open_vrrp_socket(const int proto, const int index)
 {
@@ -1066,10 +1032,67 @@ int open_vrrp_socket(const int proto, const int index)
   return fd;
 }
 
+
+extern data *conf_data;
+
 /* handle terminate state */
-void vrrp_state_stop_instance(vrrp_rt *vsrv)
+void shutdown_vrrp_instances(void)
+{
+  list l = conf_data->vrrp;
+  element e;
+  vrrp_instance *vrrp;
+
+  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+    vrrp = ELEMENT_DATA(e);
+
+    /* remove VIPs */
+    if (vrrp->vsrv->state == VRRP_STATE_MAST)
+      vrrp_restore_interface(vrrp->vsrv, 1);
+  }
+}
+
+/* complete vrrp structure */
+static int vrrp_complete_instance(vrrp_rt *vsrv)
 {
-  /* restore MAC, routing table & remove VIPs */
-  if (vsrv->state == VRRP_STATE_MAST)
-    vrrp_restore_interface(vsrv, 1);
+  vrrp_if *vif = vsrv->vif;
+
+  /* complete the VMAC address */
+  vsrv->hwaddr[0] = 0x00;
+  vsrv->hwaddr[1] = 0x00;
+  vsrv->hwaddr[2] = 0x5E;
+  vsrv->hwaddr[3] = 0x00;
+  vsrv->hwaddr[4] = 0x01;
+  vsrv->hwaddr[5] = vsrv->vrid;
+
+  /* get the ip address */
+  vif->ipaddr = ifname_to_ip(vif->ifname);
+  if (!vif->ipaddr) {
+    syslog(LOG_INFO, "VRRP Error : no interface found : %s !\n", vif->ifname);
+    return 0;
+  }
+  /* get the hwaddr */
+  if (hwaddr_get(vif->ifname, vif->hwaddr, sizeof(vif->hwaddr))) {
+    syslog(LOG_INFO, "VRRP Error : Unreadable MAC"
+                     "address for interface : %s !\n", vif->ifname);
+    return 0;
+  }
+
+  vsrv->state = VRRP_STATE_INIT;
+  if (!vsrv->adver_int) vsrv->adver_int = VRRP_ADVER_DFL * TIMER_HZ;
+  if (!vsrv->priority) vsrv->priority = VRRP_PRIO_DFL;
+  if (!vsrv->preempt) vsrv->preempt = VRRP_PREEMPT_DFL;
+
+  return(chk_min_cfg(vsrv));
+}
+
+void vrrp_complete_init(void)
+{
+  list l = conf_data->vrrp;
+  element e;
+  vrrp_instance *vrrp;
+
+  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+    vrrp = ELEMENT_DATA(e);
+    vrrp_complete_instance(vrrp->vsrv);
+  }
 }
diff --git a/vrrp.h b/vrrp.h
index 6ffd07b..5de4bce 100644 (file)
--- a/vrrp.h
+++ b/vrrp.h
@@ -6,7 +6,7 @@
  *
  * Part:        vrrp.c program include file.
  *
- * Version:     $Id: vrrp.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: vrrp.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              Based on the Jerome Etienne, <jetienne@arobas.net> code.
@@ -35,9 +35,9 @@
 #include <unistd.h>
 
 /* local include */
-#include "cfreader.h"
 #include "vrrp_ipaddress.h"
 #include "vrrp_ipsecah.h"
+#include "timer.h"
 #include "utils.h"
 
 
@@ -81,7 +81,7 @@ typedef struct {
 
        uint32_t        ipaddr;         /* the address of the interface */
        char            hwaddr[6];      /* hardcoded for ethernet */
-       char            ifname[10];     /* the device name for this ipaddr */
+       char            *ifname;        /* the device name for this ipaddr */
        /*
         * To have my own ip_id creates collision with kernel ip->id
         * but it should be ok because the packets are unlikely to be
@@ -113,8 +113,7 @@ typedef struct {
 
         int     debug;          /* Debug level 0-4 */
         int     notify_exec;
-        char    notify_file[FILENAME_MAX ];
-
+        char    notify_file[FILENAME_MAX];
 
        /* rfc2336.6.2 */
        uint32_t        ms_down_timer;
@@ -153,15 +152,14 @@ typedef struct {
 #define VRRP_IS_BAD_DEBUG_INT(d)       ((d)<0 || (d)>4)
 
 
-#define VRRP_TIMER_HZ          1000000
-#define VRRP_TIMER_SKEW(srv)   ((256-(srv)->priority)*VRRP_TIMER_HZ/256) 
+#define VRRP_TIMER_SKEW(srv)   ((256-(srv)->priority)*TIMER_HZ/256) 
 
 #define VRRP_MIN(a, b) ((a) < (b)?(a):(b))
 #define VRRP_MAX(a, b) ((a) > (b)?(a):(b))
 
 /* prototypes */
 extern int vrrp_ipsecah_len(void);
-extern int complete_vrrp_init(vrrp_rt *vsrv);
-extern void vrrp_state_stop_instance(vrrp_rt *vsrv);
+extern void vrrp_complete_init(void);
+extern void shutdown_vrrp_instances(void);
 
 #endif
index 0b688f1..fa8700a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        NETLINK IPv4 address manipulation.
  *
- * Version:     $Id: vrrp_ipaddress.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: vrrp_ipaddress.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 3fb0bd7..b48fa0a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_ipaddress.c include file.
  *
- * Version:     $Id: vrrp_ipaddress.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: vrrp_ipaddress.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index d2f0212..dbe6855 100644 (file)
@@ -7,7 +7,7 @@
  *              authentication data encryption using HMAC MD5 according to
  *              RFCs 2085 & 2104.
  *
- * Version:     $Id: vrrp_ipsecah.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: vrrp_ipsecah.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index b98fdde..82a5a92 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_ipsecah.c include file.
  * 
- * Version:     $Id: vrrp_ipsecah.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: vrrp_ipsecah.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
index 671df7f..f8803d1 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        NETLINK kernel command channel.
  *
- * Version:     $Id: vrrp_netlink.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: vrrp_netlink.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 39a7f4c..ecc053a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_netlink.c include file.
  *
- * Version:     $Id: vrrp_netlink.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: vrrp_netlink.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 102b527..79ea6b2 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Sheduling framework for vrrp code.
  *
- * Version:     $Id: vrrp_scheduler.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: vrrp_scheduler.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include "vrrp_ipsecah.h"
 #include "vrrp.h"
 #include "memory.h"
+#include "list.h"
+
+extern thread_master *master;
+extern data *conf_data;
 
 /*
  * Initialize state handling
  * --rfc2338.6.4.1
  */
-static void vrrp_init_state(vrrp_instance *instance)
+static void vrrp_init_state(list l)
 {
-  vrrp_instance *vrrpptr = instance;
+  vrrp_instance *vrrp;
+  element e;
+
+  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+    vrrp = ELEMENT_DATA(e);
 
-  while (instance) {
-    if (instance->vsrv->priority == VRRP_PRIO_OWNER ||
-        instance->vsrv->wantstate == VRRP_STATE_MAST) {
-      instance->vsrv->state = VRRP_STATE_GOTO_MASTER;
+    if (vrrp->vsrv->priority == VRRP_PRIO_OWNER ||
+        vrrp->vsrv->wantstate == VRRP_STATE_MAST) {
+      vrrp->vsrv->state = VRRP_STATE_GOTO_MASTER;
     } else {
-      instance->vsrv->ms_down_timer = 3 * instance->vsrv->adver_int
-                                      + VRRP_TIMER_SKEW(instance->vsrv);
-      instance->vsrv->state = VRRP_STATE_BACK;
+      vrrp->vsrv->ms_down_timer = 3 * vrrp->vsrv->adver_int
+                                      + VRRP_TIMER_SKEW(vrrp->vsrv);
+      vrrp->vsrv->state = VRRP_STATE_BACK;
     }
-
-    instance = (vrrp_instance *)instance->next;
   }
-  instance = vrrpptr;
 }
 
-static void vrrp_init_instance_sands(vrrp_instance *instance)
+static void vrrp_init_instance_sands(vrrp_instance *vrrp)
 {
-  struct timeval timer_now;
+  TIMEVAL timer;
 
-  gettimeofday(&timer_now, NULL);
+  timer = timer_now();
 
-  if (instance->vsrv->state == VRRP_STATE_BACK) {
-    instance->vsrv->sands.tv_sec = timer_now.tv_sec +
-                                   instance->vsrv->ms_down_timer / VRRP_TIMER_HZ;
-    instance->vsrv->sands.tv_usec = timer_now.tv_usec +
-                                    instance->vsrv->ms_down_timer % VRRP_TIMER_HZ;
+  if (vrrp->vsrv->state == VRRP_STATE_BACK) {
+    vrrp->vsrv->sands.tv_sec = timer.tv_sec +
+                               vrrp->vsrv->ms_down_timer / TIMER_HZ;
+    vrrp->vsrv->sands.tv_usec = timer.tv_usec +
+                                vrrp->vsrv->ms_down_timer % TIMER_HZ;
   }
-  if (instance->vsrv->state == VRRP_STATE_GOTO_MASTER ||
-      instance->vsrv->state == VRRP_STATE_MAST) {
-    instance->vsrv->sands.tv_sec = timer_now.tv_sec +
-                                   instance->vsrv->adver_int / VRRP_TIMER_HZ;
-    instance->vsrv->sands.tv_usec = timer_now.tv_usec;
+  if (vrrp->vsrv->state == VRRP_STATE_GOTO_MASTER ||
+      vrrp->vsrv->state == VRRP_STATE_MAST) {
+    vrrp->vsrv->sands.tv_sec = timer.tv_sec +
+                               vrrp->vsrv->adver_int / TIMER_HZ;
+    vrrp->vsrv->sands.tv_usec = timer.tv_usec;
   }
 }
 
-static void vrrp_init_sands(vrrp_instance *instance)
+static void vrrp_init_sands(list l)
 {
-  vrrp_instance *vrrpptr = instance;
+  vrrp_instance *vrrp;
+  element e;
 
-  while (instance) {
-    vrrp_init_instance_sands(instance);
-
-    instance = (vrrp_instance *)instance->next;
+  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+    vrrp = ELEMENT_DATA(e);
+    vrrp_init_instance_sands(vrrp);
   }
-  instance = vrrpptr;
 }
 
 /* Timer functions */
-static TIMEVAL vrrp_compute_timer(const int fd, vrrp_instance *vrrp)
+static TIMEVAL vrrp_compute_timer(const int fd)
 {
-  vrrp_instance *ptr = vrrp;
+  vrrp_instance *vrrp;
   TIMEVAL timer;
+  element e;
+  list l = conf_data->vrrp;
 
   /* clean the memory */
-  memset(&timer, 0, sizeof(struct timeval));
+  TIMER_RESET(timer);
 
-  while (vrrp) {
+  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+    vrrp = ELEMENT_DATA(e);
     if (vrrp->vsrv->fd == fd) {
-      if (thread_timer_cmp(vrrp->vsrv->sands, timer) < 0 ||
-          (timer.tv_sec == 0 && timer.tv_usec == 0)) {
-        timer.tv_sec = vrrp->vsrv->sands.tv_sec;
-        timer.tv_usec = vrrp->vsrv->sands.tv_usec;
-      }
+      if (timer_cmp(vrrp->vsrv->sands, timer) < 0 ||
+          TIMER_ISNULL(timer))
+        timer = timer_dup(vrrp->vsrv->sands);
     }
-
-    vrrp = (vrrp_instance *)vrrp->next;
   }
-  vrrp = ptr;
 
   return timer;
 }
 
-static TIMEVAL vrrp_timer_delta(TIMEVAL timer)
-{
-  TIMEVAL timer_now;
-
-  /* init timer */
-  memset(&timer_now, 0, sizeof(struct timeval));
-  gettimeofday(&timer_now, NULL);
-
-  return(thread_timer_sub(timer, timer_now));
-}
-
-static long vrrp_timer_fd(const int fd, vrrp_instance *instance)
+static long vrrp_timer_fd(const int fd)
 {
-  TIMEVAL timer;
-  long vrrp_timer = 0;
+  TIMEVAL timer, vrrp_timer, now;
 
-  timer = vrrp_compute_timer(fd, instance);
-  timer = vrrp_timer_delta(timer);
-  vrrp_timer = timer.tv_sec * VRRP_TIMER_HZ + timer.tv_usec;
+  timer = vrrp_compute_timer(fd);
+  now = timer_now();
+  vrrp_timer = timer_sub(timer, now);
+//  vrrp_timer = timer_sub_now(timer);
 
-  return vrrp_timer;
+  return (vrrp_timer.tv_sec*TIMER_HZ + vrrp_timer.tv_usec);
 }
 
-static int vrrp_timer_vrid_timeout(const int fd, vrrp_instance *vrrp)
+static int vrrp_timer_vrid_timeout(const int fd)
 {
-  vrrp_instance *ptr = vrrp;
+  vrrp_instance *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, vrrp);
+  vrrp_timer = vrrp_compute_timer(fd);
 
-  while (vrrp) {
-    if (thread_timer_cmp(vrrp->vsrv->sands, vrrp_timer) == 0)
+  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+    vrrp = ELEMENT_DATA(e);
+    if (timer_cmp(vrrp->vsrv->sands, vrrp_timer) == 0)
       vrid = vrrp->vsrv->vrid;
-
-    vrrp = (vrrp_instance *)vrrp->next;
   }
-  vrrp = ptr;
-
   return vrid;
 }
 
@@ -158,12 +147,10 @@ static void vrrp_timer_dump(vrrp_instance *vrrp)
   long vrrp_timer = 0;
 
   memset(&timer, 0, sizeof(struct timeval));
-  memset(&timer_now, 0, sizeof(struct timeval));
-  gettimeofday(&timer_now, NULL);
 
   while (vrrp) {
-    timer = thread_timer_sub(vrrp->vsrv->sands, timer_now);
-    vrrp_timer = timer.tv_sec * VRRP_TIMER_HZ + timer.tv_usec;
+    timer = timer_sub_now(vrrp->vsrv->sands);
+    vrrp_timer = timer.tv_sec * TIMER_HZ + timer.tv_usec;
     syslog(LOG_DEBUG, "Timer(vrid,value) : (%d,%d)", vrrp->vsrv->vrid, vrrp_timer);
 
     vrrp = (vrrp_instance *)vrrp->next;
@@ -173,147 +160,128 @@ static void vrrp_timer_dump(vrrp_instance *vrrp)
 */
 
 /* Thread functions */
-static void vrrp_register_workers(thread_master *master
-                                  , vrrp_instance *instance
-                                  , sockpool *pool)
+static void vrrp_register_workers(list l)
 {
-  sockpool *poolptr = pool;
+  sock *sock;
   TIMEVAL timer;
   long vrrp_timer = 0;
+  element e;
 
-  /* init compute timer */
+  /* Init compute timer */
   memset(&timer, 0, sizeof(struct timeval));
 
   /* Init the VRRP instances state */
-  vrrp_init_state(instance);
+  vrrp_init_state(conf_data->vrrp);
 
   /* Init VRRP instances sands */
-  vrrp_init_sands(instance);
+  vrrp_init_sands(conf_data->vrrp);
 
-  while (pool) {
+  /* 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(pool->fd, instance);
-    thread_add_read(master, vrrp_read_dispatcher_thread,
-                    instance, pool->fd, vrrp_timer);
-
-    pool = (sockpool *)pool->next;
+    vrrp_timer = vrrp_timer_fd(sock->fd);
+    thread_add_read(master, vrrp_read_dispatcher_thread
+                          , NULL
+                          , sock->fd
+                          , vrrp_timer);
   }
-  pool = poolptr;
 }
 
 /* VRRP dispatcher functions */
-static int already_exist_sock(sockpool *lstptr, int ifindex, int proto)
+static int already_exist_sock(list l, int ifindex, int proto)
 {
-  sockpool *ptrpool = lstptr;
+  sock *sock;
+  element e;
 
-  while (lstptr) {
-    if ((lstptr->ifindex == ifindex) && (lstptr->proto == proto)) {
-      lstptr = ptrpool;
+  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+    sock = ELEMENT_DATA(e);
+    if ((sock->ifindex == ifindex) && (sock->proto == proto))
       return 1;
-    }
-    lstptr = (sockpool *)lstptr->next;
   }
-  lstptr = ptrpool;
   return 0;
 }
 
-static sockpool *add_sock(sockpool *lstsock, sockpool *sock)
+/* sockpool list primitives */
+void free_sock(void *data)
 {
-  sockpool *ptrpool = lstsock;
-
-  if (lstsock) {
-    while (lstsock->next) lstsock = (sockpool *)lstsock->next;
-    lstsock->next = (struct sockpool *)sock;
-    return ptrpool;
-  } else {
-    lstsock = sock;
-    return lstsock;
-  }
+  FREE(data);
 }
-
-static sockpool *remove_sock(sockpool *pool)
+void dump_sock(void *data)
 {
-  sockpool *t;
-
-  t = (sockpool *)pool->next;
-  FREE(pool);
-  return t;
+  sock *sock = data;
+  syslog(LOG_DEBUG, "sockpool -> ifindex(%d), proto(%d), fd(%d)"
+                  , sock->ifindex
+                  , sock->proto
+                  , sock->fd);
 }
-
-static void clear_sockpool(sockpool *pool)
+void alloc_sock(list l, int ifindex, int proto)
 {
-  while (pool)
-    pool = remove_sock(pool);
+  sock *new;
+
+  new = (sock *)MALLOC(sizeof(sock));
+  new->ifindex = ifindex;
+  new->proto   = proto;
+
+  list_add(l, new);
 }
 
-static sockpool *vrrp_create_sockpool(vrrp_instance *instance, sockpool *pool)
+static void vrrp_create_sockpool(list l)
 {
-  vrrp_instance *ptr = instance;
-  sockpool *sock;
+  vrrp_instance *vrrp;
+  list p = conf_data->vrrp;
+  element e;
   int ifindex;
   int proto;
 
-  while (instance) {
-    ifindex = ifname_to_idx(instance->vsrv->vif->ifname);
-    if (instance->vsrv->vif->auth_type == VRRP_AUTH_AH)
+  for (e = LIST_HEAD(p); e; ELEMENT_NEXT(e)) {
+    vrrp = ELEMENT_DATA(e);
+    ifindex = ifname_to_idx(vrrp->vsrv->vif->ifname);
+    if (vrrp->vsrv->vif->auth_type == VRRP_AUTH_AH)
       proto = IPPROTO_IPSEC_AH;
     else
       proto = IPPROTO_VRRP;
 
-    if (!already_exist_sock(pool, ifindex, proto)) {
-      /* allocate & clean the new struct */
-      sock = (sockpool *)MALLOC(sizeof(sockpool));
-
-      /* fill in the new sock structure */
-      sock->ifindex = ifindex;
-      sock->proto = proto;
-      pool = add_sock(pool, sock);
-    }
-
-    instance = (vrrp_instance *)instance->next;
+    /* add the vrrp element if not exist */
+    if (!already_exist_sock(l, ifindex, proto))
+      alloc_sock(l, ifindex, proto);
   }
-
-  instance = ptr;
-  return pool;
 }
 
-static void vrrp_open_sockpool(sockpool *pool)
+static void vrrp_open_sockpool(list l)
 {
-  sockpool *ptr = pool;
+  sock *sock;
+  element e;
 
-  while (pool) {
-    pool->fd = open_vrrp_socket(pool->proto, pool->ifindex);
-    syslog(LOG_DEBUG, "sockpool -> ifindex %d, proto %d, fd %d",
-                      pool->ifindex, pool->proto, pool->fd);
-    pool = (sockpool *)pool->next;
+  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+    sock = ELEMENT_DATA(e);
+    sock->fd = open_vrrp_socket(sock->proto, sock->ifindex);
   }
-  pool = ptr;
 }
 
-static void vrrp_set_fds(vrrp_instance *instance, sockpool *pool)
+static void vrrp_set_fds(list l)
 {
-  sockpool *ptr = pool;
-  vrrp_instance *ptrvrrp = instance;
+  sock *sock;
+  vrrp_instance *vrrp;
+  list p = conf_data->vrrp;
+  element e_sock;
+  element e_vrrp;
   int proto;
 
-  while (pool) {
-    while (instance) {
-      if (instance->vsrv->vif->auth_type == VRRP_AUTH_AH)
+  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->vsrv->vif->auth_type == VRRP_AUTH_AH)
         proto = IPPROTO_IPSEC_AH;
       else
         proto = IPPROTO_VRRP;
 
-      if ((pool->ifindex == ifname_to_idx(instance->vsrv->vif->ifname)) &&
-          (pool->proto == proto))
-        instance->vsrv->fd = pool->fd;
-
-      instance = (vrrp_instance *)instance->next;
+      if ((sock->ifindex == ifname_to_idx(vrrp->vsrv->vif->ifname)) &&
+          (sock->proto == proto))
+        vrrp->vsrv->fd = sock->fd;
     }
-    instance = ptrvrrp;
-
-    pool = (sockpool *)pool->next;
   }
-  pool = ptr;
 }
 
 /*
@@ -330,51 +298,57 @@ static void vrrp_set_fds(vrrp_instance *instance, sockpool *pool)
  * are multiplexed through this fds. So our design can handle 2*n
  * multiplexing points.
  */
-int vrrp_dispatcher_init_thread(thread *thread)
+int vrrp_dispatcher_init(thread *thread)
 {
-  vrrp_instance *instance = THREAD_ARG(thread);
-  sockpool *pool;
+  list pool;
 
-  /* init */
-  pool = NULL;
+  /* allocate the sockpool */
+  pool = alloc_list(free_sock, dump_sock);
 
   /* create the VRRP socket pool list */
-  pool = vrrp_create_sockpool(instance, pool);
+  vrrp_create_sockpool(pool);
 
   /* open the VRRP socket pool */
   vrrp_open_sockpool(pool);
 
   /* set VRRP instance fds to sockpool */
-  vrrp_set_fds(instance, pool);
+  vrrp_set_fds(pool);
 
   /* register read dispatcher worker thread */
-  vrrp_register_workers(thread->master, instance, pool);
+  vrrp_register_workers(pool);
 
   /* cleanup the temp socket pool */
-  clear_sockpool(pool);
+  dump_list(pool);
+  free_list(pool);
 
   return 0;
 }
 
-static vrrp_instance *vrrp_search_instance_isync(char *isync, vrrp_instance *instance)
+static vrrp_instance *vrrp_search_instance_isync(char *isync)
 {
-  while (instance) {
-    if (strcmp(instance->iname, isync) == 0) /* FIXME: handle buffer overflow */
-      return instance;
-    instance = (vrrp_instance *)instance->next;
+  vrrp_instance *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, isync) == 0)
+      return vrrp;
   }
-
   return NULL;
 }
 
-static vrrp_instance *vrrp_search_instance(const int vrid, vrrp_instance *instance)
+static vrrp_instance *vrrp_search_instance(const int vrid)
 {
-  while (instance) {
-    if (instance->vsrv->vrid == vrid)
-      return instance;
-    instance = (vrrp_instance *)instance->next;
+  vrrp_instance *vrrp;
+  list l = conf_data->vrrp;
+  element e;
+
+  for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+    vrrp = ELEMENT_DATA(e);
+    if (vrrp->vsrv->vrid == vrid)
+      return vrrp;
   }
-
   return NULL;
 }
 
@@ -410,7 +384,7 @@ static void vrrp_handle_leave_master(vrrp_instance *instance
 {
   if (vrrp_state_master_rx(instance, vrrp_buffer, len)) {
     syslog(LOG_INFO, "VRRP_Instance(%s) Received higher prio advert"
-                    , instance->iname);
+                   , instance->iname);
     vrrp_state_leave_master(instance);
   }
 }
@@ -502,8 +476,6 @@ static int vrrp_handle_state_timeout(vrrp_instance *instance)
 /* Our read packet dispatcher */
 int vrrp_read_dispatcher_thread(thread *thread)
 {
-  vrrp_instance *instance = THREAD_ARG(thread);
-  vrrp_instance *ptr = instance;
   vrrp_instance *vrrp_isync;
   vrrp_instance *vrrp_instance;
   long vrrp_timer = 0;
@@ -517,19 +489,14 @@ int vrrp_read_dispatcher_thread(thread *thread)
   if (thread->type == THREAD_READ_TIMEOUT) {
 
     /* Searching for matching instance */
-    vrid = vrrp_timer_vrid_timeout(thread->u.fd, instance);
-    vrrp_instance = vrrp_search_instance(vrid, instance);
-    instance = ptr;
-
-// syslog(LOG_DEBUG, "Dispatcher timeout on (fd,vrid) : (%d,%d)", thread->u.fd, vrid);
+    vrid = vrrp_timer_vrid_timeout(thread->u.fd);
+    vrrp_instance = vrrp_search_instance(vrid);
 
     previous_state = vrrp_handle_state_timeout(vrrp_instance);
 
     /* handle master instance synchronization */
-    if (previous_state == VRRP_STATE_BACK && 
-        strlen(vrrp_instance->isync) > 0) {
-      vrrp_isync = vrrp_search_instance_isync(vrrp_instance->isync, instance);
-      instance = ptr;
+    if (previous_state == VRRP_STATE_BACK && vrrp_instance->isync) {
+      vrrp_isync = vrrp_search_instance_isync(vrrp_instance->isync);
 
       if (vrrp_isync->vsrv->state == VRRP_STATE_BACK) {
         syslog(LOG_INFO, "VRRP_Instance(%s) must be sync with %s"
@@ -566,27 +533,23 @@ int vrrp_read_dispatcher_thread(thread *thread)
     iph = (struct iphdr *)vrrp_buffer;
 
     /* GCC bug : Workaround */
-    hd = (vrrp_pkt *) ((char *)iph + (iph->ihl<<2));
+    hd = (vrrp_pkt *) ((char *)iph + (iph->ihl << 2));
     if (iph->protocol == IPPROTO_IPSEC_AH)
       hd = (vrrp_pkt *) ((char *)hd + vrrp_ipsecah_len());
     /* GCC bug : end */
 
     /* Searching for matching instance */
-    vrrp_instance = vrrp_search_instance(hd->vrid, instance);
-    instance = ptr;
+    vrrp_instance = vrrp_search_instance(hd->vrid);
 
     if (vrrp_instance) {
 
-//syslog(LOG_DEBUG, "VRRP packet received: on fd:%d", thread->u.fd);
-
       previous_state = vrrp_handle_state(vrrp_instance, vrrp_buffer, len);
 
       /* handle backup instance synchronization */
       if (previous_state == VRRP_STATE_MAST && 
           vrrp_instance->vsrv->state == VRRP_STATE_BACK &&
-          strlen(vrrp_instance->isync) > 0) {
-        vrrp_isync = vrrp_search_instance_isync(vrrp_instance->isync, instance);
-        instance = ptr;
+          vrrp_instance->isync) {
+        vrrp_isync = vrrp_search_instance_isync(vrrp_instance->isync);
 
         /* synchronized instance probably failed */
         if (vrrp_isync->vsrv->state == VRRP_STATE_MAST &&
@@ -620,11 +583,19 @@ int vrrp_read_dispatcher_thread(thread *thread)
   }
 
   /* register next dispatcher thread */
-  vrrp_timer = vrrp_timer_fd(thread->u.fd, instance);
-  thread_add_read(thread->master, vrrp_read_dispatcher_thread,
-                  instance, thread->u.fd, vrrp_timer);
-
-//syslog(LOG_DEBUG, "VRRP new timer: %lu on fd:%d", vrrp_timer, thread->u.fd);
-
+  vrrp_timer = vrrp_timer_fd(thread->u.fd);
+  thread_add_read(thread->master, vrrp_read_dispatcher_thread
+                                , NULL
+                                , thread->u.fd
+                                , vrrp_timer);
   return 0;
 }
+
+/* Register VRRP thread */
+void register_vrrp_thread(void)
+{
+  if (!LIST_ISEMPTY(conf_data->vrrp))
+    thread_add_event(master, vrrp_dispatcher_init
+                           , NULL
+                           , VRRP_DISPATCHER);
+}
index b06878c..7418a89 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_scheduler.c include file.
  * 
- * Version:     $Id: vrrp_scheduler.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version:     $Id: vrrp_scheduler.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
@@ -32,6 +32,7 @@
 
 /* local include */
 #include "scheduler.h"
+#include "data.h"
 
 /*
  * Our instance dispatcher use a socket pool.
@@ -42,9 +43,7 @@ typedef struct {
   int ifindex;
   int proto;
   int fd;
-
-  struct sockpool *next;
-} sockpool;
+} sock;
 
 /* extern prototypes */
 extern int open_vrrp_socket(const int proto, const int index);