keepalived-0.4.8 v0.4.8
authorAlexandre Cassen <acassen@freebox.fr>
Wed, 21 Nov 2001 14:52:21 +0000 (15:52 +0100)
committerAlexandre Cassen <acassen@freebox.fr>
Mon, 28 Sep 2009 08:58:54 +0000 (10:58 +0200)
* keepalived-0.4.8 released.
* Rewrite the whole VRRP previous code.
* VRRP : Created a hierarchic scheduling framework.
  Handle VRRP instances multiplexing on the same I/O fd.
  VRRP I/O events are handled by our global scheduling
  framework. Then the global sheduling framework call a VRRP
  I/O instance dispatcher to manage VRRP instances.
* VRRP : Created a temporary socket pool to handle register
         our VRRP thread instances.
  We create & allocate a socket pool here. The soft design
  can be sum up by the following sketch :

         fd1  fd2    fd3  fd4          fdi  fdi+1
      -----\__/--------\__/---........---\__/---
         | ETH0 |    | ETH1 |          | ETHn |
         +------+    +------+          +------+

    Here we have n physical NIC. Each NIC own a maximum of 2 fds.
  (one for VRRP the other for IPSEC_AH). All our VRRP instances
  are multiplexed through this fds. So our design can handle 2*n
  multiplexing points.
* VRRP : Review the multicast socket creating. We bind the socket
  to a specific NIC. inbound & outbound traffic are bound to the
  NIC.
  => why IP_ADD_MEMBERSHIP & IP_MULTICAST_IF doesnt set
     sk->bound_dev_if themself ??? !!!
     Needed for filter multicasted advert per interface.
  => For inbound binding we use SO_BINDTODEVICE kernel option.
* VRRP : Created a read dispatcher thread to deal with our sockpool.
  Handle VRRP states & transition states.
* VRRP : Created a VRRP synchronization instance circuit. This
  functionnality gave you the ability to monitor VRRP instance
  each other. This mean that if 2 VRRP instances are monitoring
  themself and if one of this instance change state, the other
  follow the same state. ex.: With 2 VRRP instances (VI_1 & VI_2)
  if VI_1 become backup then VI_2 become backup too. (symetricly
  with master VRRP state).
* VRRP : Rewrite the netlink interface to use non blocking socket.
* VRRP : Rewrite the ipaddress handling to use the new netlink
  interface.
* VRRP : Remove the VRPP VMAC handling since linux kernel only
  permit to use one MAC address on a specific NIC. We use gratuitous
  arp when setting up VRRP VIP, to uptade remote host arp caches.
  => In certain case this can cause a TCP session renegociation
     which can cause a permature session end.
  => To be fully compliant with the VRRP RFC, need to patch the
     kernel to gave it the possibility to deal with more than one
     MAC address at a time. Give me clue on it please ! to same me
     a little time :)
* Starting VRRP documentation.
* Patch a pidfile handling bug when forking the keepalived daemon.
  Thanks goes to Gianni D'Aprile for pointing it to me.
* Patch a timer race condition into the scheduling framework.
  This bug caused tcpcheck to respawn quickly...
  Thanks goes to Gianni D'Aprile for pointing it to me.
* keepalived-0.3.8 released.
* Added support to native IPTABLE LVS CODE
  => using NAT on 2.4 kernel ipchains kernel support
     has been removed.
* Added support to Direct Routing & Tunneling.
* Review the keepalived.init script to be much more generic.

52 files changed:
ChangeLog
INSTALL
Makefile
TODO
cfreader.c
cfreader.h
check.h
check_http.c
check_http.h
check_misc.c [new file with mode: 0644]
check_misc.h [new file with mode: 0644]
check_tcp.c
check_tcp.h
etc/rc.d/init.d/keepalived.init
ipfwwrapper.c
ipfwwrapper.h
ipvswrapper.c
ipvswrapper.h
ipwrapper.c
ipwrapper.h
layer4.c
layer4.h
libnetlink/Makefile [deleted file]
libnetlink/libnetlink.c [deleted file]
libnetlink/libnetlink.h [deleted file]
libnetlink/ll_map.c [deleted file]
libnetlink/ll_map.h [deleted file]
main.c
main.h
pidfile.c
pidfile.h
samples/keepalived.conf.misc_check [new file with mode: 0644]
samples/keepalived.conf.sample [moved from keepalived.conf.sample with 100% similarity]
samples/keepalived.conf.vrrp [moved from keepalived.conf.vrrp with 52% similarity]
samples/keepalived.conf.vrrp.sync [new file with mode: 0644]
samples/sample.misccheck.smbcheck.sh [new file with mode: 0644]
scheduler.c
scheduler.h
smtp.c
smtp.h
utils.c
vrrp.c
vrrp.h
vrrp_ipaddress.c
vrrp_ipaddress.h
vrrp_iproute.c [deleted file]
vrrp_ipsecah.c
vrrp_ipsecah.h
vrrp_netlink.c [new file with mode: 0644]
vrrp_netlink.h [moved from vrrp_iproute.h with 53% similarity]
vrrp_scheduler.c [new file with mode: 0644]
vrrp_scheduler.h [new file with mode: 0644]

index 5a1d6c3..433b6cb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,73 @@
-2001-09-14  Alexandre Cassen  <acassen@linux-vs.org>
+2001-11-20  Alexandre Cassen  <acassen@linux-vs.org>
+        * keepalived-0.4.8 released.
+       * Rewrite the whole VRRP previous code.
+       * VRRP : Created a hierarchic scheduling framework.
+         Handle VRRP instances multiplexing on the same I/O fd.
+         VRRP I/O events are handled by our global scheduling 
+         framework. Then the global sheduling framework call a VRRP
+         I/O instance dispatcher to manage VRRP instances.
+       * VRRP : Created a temporary socket pool to handle register
+                our VRRP thread instances.
+         We create & allocate a socket pool here. The soft design
+         can be sum up by the following sketch :
+                fd1  fd2    fd3  fd4          fdi  fdi+1
+             -----\__/--------\__/---........---\__/---
+                | ETH0 |    | ETH1 |          | ETHn |
+                +------+    +------+          +------+
+         Here we have n physical NIC. Each NIC own a maximum of 2 fds.
+         (one for VRRP the other for IPSEC_AH). All our VRRP instances
+         are multiplexed through this fds. So our design can handle 2*n
+         multiplexing points.
+       * VRRP : Review the multicast socket creating. We bind the socket
+         to a specific NIC. inbound & outbound traffic are bound to the
+         NIC.
+         => why IP_ADD_MEMBERSHIP & IP_MULTICAST_IF doesnt set
+            sk->bound_dev_if themself ??? !!!
+            Needed for filter multicasted advert per interface.
+         => For inbound binding we use SO_BINDTODEVICE kernel option.
+       * VRRP : Created a read dispatcher thread to deal with our sockpool.
+         Handle VRRP states & transition states.
+       * VRRP : Created a VRRP synchronization instance circuit. This
+         functionnality gave you the ability to monitor VRRP instance
+         each other. This mean that if 2 VRRP instances are monitoring 
+         themself and if one of this instance change state, the other
+         follow the same state. ex.: With 2 VRRP instances (VI_1 & VI_2)
+         if VI_1 become backup then VI_2 become backup too. (symetricly
+         with master VRRP state).
+       * VRRP : Rewrite the netlink interface to use non blocking socket.
+       * VRRP : Rewrite the ipaddress handling to use the new netlink
+         interface.
+       * VRRP : Remove the VRPP VMAC handling since linux kernel only
+         permit to use one MAC address on a specific NIC. We use gratuitous
+         arp when setting up VRRP VIP, to uptade remote host arp caches.
+         => In certain case this can cause a TCP session renegociation
+            which can cause a permature session end.
+         => To be fully compliant with the VRRP RFC, need to patch the
+            kernel to gave it the possibility to deal with more than one
+            MAC address at a time. Give me clue on it please ! to same me
+            a little time :)
+       * Starting VRRP documentation.
+       * Patch a pidfile handling bug when forking the keepalived daemon.
+         Thanks goes to Gianni D'Aprile for pointing it to me.
+       * Patch a timer race condition into the scheduling framework.
+         This bug caused tcpcheck to respawn quickly...
+         Thanks goes to Gianni D'Aprile for pointing it to me.
+
+2001-11-04  Alexandre Cassen  <acassen@linux-vs.org>
+        * keepalived-0.3.8 released.
+        * Added support to native IPTABLE LVS CODE
+          => using NAT on 2.4 kernel ipchains kernel support
+             has been removed.
+        * Added support to Direct Routing & Tunneling.
+        * Review the keepalived.init script to be much more generic.
 
+2001-09-14  Alexandre Cassen  <acassen@linux-vs.org>
        * keepalived-0.4.1 released.
        * Added support to LVS kernel 2.4 code
 
-
 2001-08-23  Alexandre Cassen  <acassen@linux-vs.org>
-
        * keepalived-0.4.0 released.
        * Patch a race condition into the scheduler timer computation.
        * Patch a race condition into the tcp checker thread. Only
@@ -27,9 +89,7 @@
          or set by kernel. Only UNICAST route are stored.
        * Added dropping packet support.
 
-
 2001-07-15  Alexandre Cassen  <acassen@linux-vs.org>
-
        * keepalived-0.3.5 released.
         * Rewrite the whole signal handling, registering a terminating
           thread on signal.
diff --git a/INSTALL b/INSTALL
index 0e66309..69ab723 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -3,19 +3,11 @@ Kernel needing
 
   Compile a kernel with the following options :
 
-  IP aliasing
   Kernel/User netlink socket
-  Network firewalls
+  Network firewalls (for Kernel 2.2)
   Routing messages
   LinuxVirtualServer
 
-  If you use KERNEL 2.4 build your kernel with ipchains support :
-  => Network options
-       IP: Netfilter Configuration
-        <M> ipchains (2.2-style) support
-
-  => Patch your 2.4 kernel with the LVS code
-
 Installation
 ============
 
index 46282f3..503f9ed 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -7,29 +7,49 @@ CC= gcc
 KERNEL := KERNEL_2_$(shell uname -r | cut -d'.' -f2)
 
 # To compile with debug messages uncomment the following line
-CFLAGS= -g -Wall -DDEBUG -D$(KERNEL)
+CFLAGS= -g -Wall -Wunused -DDEBUG -D$(KERNEL)
 #CFLAGS= -g -Wall -D$(KERNEL)
 DEFS=
 
-LIB=   libipfwc/libipfwc.a \
-       libnetlink/libnetlink.a
+ifeq ($(KERNEL),KERNEL_2_2)
+  LIB := $(LIB) libipfwc/libipfwc.a
+endif
 
-#DEFS= main.h scheduler.h cfreader.h layer4.h check_tcp.h check_http.h md5.h smtp.h
-OBJECTS= main.o \
+DEFS= main.h \
+        scheduler.h \
+        cfreader.h \
+        layer4.h \
+        check_tcp.h \
+        check_http.h \
+        check_misc.h \
+        md5.h \
+       vrrp.h \
+       vrrp_scheduler.h \
+       vrrp_netlink.h \
+       vrrp_ipaddress.h \
+       vrrp_ipsecah.h \
+        smtp.h
+
+OBJECTS := main.o \
        utils.o \
        scheduler.o \
        cfreader.o \
        layer4.o \
        check_tcp.o \
        check_http.o \
+       check_misc.o \
        md5.o \
        ipwrapper.o \
-       ipvswrapper.o \
-       ipfwwrapper.o \
+       ipvswrapper.o
+ifeq ($(KERNEL),KERNEL_2_2)
+  OBJECTS := $(OBJECTS) ipfwwrapper.o
+endif
+OBJECTS := $(OBJECTS) \
        pidfile.o \
        smtp.o \
        vrrp.o \
-       vrrp_iproute.o \
+       vrrp_scheduler.o \
+       vrrp_netlink.o \
        vrrp_ipaddress.o \
        vrrp_ipsecah.o
 
@@ -46,15 +66,15 @@ all:        $(EXEC)
 $(EXEC):       $(OBJECTS) $(DEFS) $(LIB)
        $(CC) -o $(EXEC) $(CFLAGS) $(OBJECTS) $(LIB)
 
+ifeq ($(KERNEL),KERNEL_2_2)
 libipfwc/libipfwc.a:
        cd libipfwc/ && $(MAKE) libipfwc.a
-
-libnetlink/libnetlink.a:
-       cd libnetlink/ && $(MAKE) libnetlink.a
+endif
 
 subclean:
+ifeq ($(KERNEL),KERNEL_2_2)
        cd libipfwc/ && $(MAKE) clean
-       cd libnetlink/ && $(MAKE) clean
+endif
 
 clean: subclean
        rm -f core *.o $(EXEC)
diff --git a/TODO b/TODO
index 0e5768d..3a6ff31 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,10 +1,9 @@
-* VRRP : handle specific interface multicast binding.
 * Documentation.
+* Synchronize IPVS topology with VRRP synchronization events.
 * Insert LDAP, SSL, FTP, SSH, IMAP, POP, RADIUS checkers.
 * Security auditing.
 * Add minimum configuration verification (realserver must have
   a checker defined, ...)
 * Add system verification (must have LVS support in kernel, 
                            must have netlink support in kernel,
-                           must have ip alias support in kernel,
                            must have routing messages in kernel).
index 9594d7f..c48b002 100644 (file)
@@ -7,7 +7,7 @@
  *              data structure representation the conf file representing
  *              the loadbalanced server pool.
  *  
- * Version:     $Id: cfreader.c,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: cfreader.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
@@ -62,7 +62,11 @@ struct keyword keywords[] = {
   {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"},
@@ -323,6 +327,11 @@ void dump_svr(realserver *pointersvr)
         break;
       case LDAP_GET_ID:
         break;
+      case MISC_CHECK_ID:
+       syslog(LOG_DEBUG,"       -> Keepalive method = MISC_CHECK");
+       syslog(LOG_DEBUG,"       -> Check path = %s",
+                        pointersvr->method->misc_check_path);
+       break;
     }
 
     pointersvr = (realserver *)pointersvr->next;
@@ -337,16 +346,38 @@ void dump_vs(virtualserver *pointervs)
                       ntohs(pointervs->addr_port));
 
     syslog(LOG_DEBUG, " -> delay_loop = %d, lb_algo = %s, "
-                      "lb_kind = %s, persistence = %s, protocol = %s",
+                      "persistence = %s, protocol = %s",
                       pointervs->delay_loop, pointervs->sched,
-                      (pointervs->loadbalancing_kind == 0)?"NAT":"UNKNOWN",
                       pointervs->timeout_persistence,
                       (pointervs->service_type == IPPROTO_TCP)?"TCP":"UDP");
 
-    syslog(LOG_DEBUG, " -> nat mask = %s", inet_ntoa(pointervs->nat_mask));
+    switch (pointervs->loadbalancing_kind) {
+#ifdef KERNEL_2_2
+      case 0:
+        syslog(LOG_DEBUG, " -> lb_kind = NAT");
+        syslog(LOG_DEBUG, " -> nat mask = %s", inet_ntoa(pointervs->nat_mask));
+        break;
+      case IP_MASQ_F_VS_DROUTE:
+        syslog(LOG_DEBUG, " -> lb_kind = DR");
+        break;
+      case IP_MASQ_F_VS_TUNNEL:
+        syslog(LOG_DEBUG, " -> lb_kind = TUN");
+        break;
+#else
+      case IP_VS_CONN_F_MASQ:
+        syslog(LOG_DEBUG, " -> lb_kind = NAT");
+        break;
+      case IP_VS_CONN_F_DROUTE:
+        syslog(LOG_DEBUG, " -> lb_kind = DR");
+        break;
+      case IP_VS_CONN_F_TUNNEL:
+        syslog(LOG_DEBUG, " -> lb_kind = TUN");
+        break;
+#endif
+    }
 
     if (pointervs->s_svr != NULL) {
-      syslog(LOG_DEBUG, " -> sorry server = [%s:%d]", 
+      syslog(LOG_DEBUG, " -> sorry server = [%s:%d]",
                         inet_ntoa(pointervs->s_svr->addr_ip),
                         ntohs(pointervs->s_svr->addr_port));
     }
@@ -372,6 +403,10 @@ void dump_vrrp(vrrp_instance *pointervrrp)
 
   while (pointervrrp != NULL) {
     syslog(LOG_DEBUG, " VRRP Instance = %s", pointervrrp->iname);
+    if (pointervrrp->vsrv->init_state == VRRP_STATE_BACK)
+      syslog(LOG_DEBUG, "   Want State = BACKUP");
+    else
+      syslog(LOG_DEBUG, "   Want State = MASTER");
     syslog(LOG_DEBUG, "   Device = %s", pointervrrp->vsrv->vif->ifname);
     if (strlen(pointervrrp->isync) > 0)
       syslog(LOG_DEBUG, "   Sync with instance = %s", pointervrrp->isync);
@@ -458,6 +493,37 @@ void process_stream_tcpcheck(FILE *stream, realserver *svrfill)
   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));
+  memset(methodfill, 0, sizeof(keepalive_check));
+
+  methodfill->type = MISC_CHECK_ID;
+  methodfill->http_get = NULL;
+  methodfill->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->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;
@@ -563,6 +629,9 @@ void process_stream_svr(FILE *stream, virtualserver *vsfill)
         break;
       case KW_LDAPGET: /* not yet implemented */
         break;
+      case KW_MISCCHECK:
+       process_stream_misccheck(stream, svrfill);
+       break;
       case KW_UNKNOWN:
         break;
     }
@@ -615,6 +684,9 @@ void process_stream_vs(FILE *stream, configuration_data *conf_data)
   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:
@@ -625,11 +697,33 @@ void process_stream_vs(FILE *stream, configuration_data *conf_data)
         break;
       case KW_LBKIND:
         fscanf(stream, "%s", string);
-        /* For the moment only NAT is supported.
-         * masq_flags : IP_MASQ_F_VS_DROUTE & IP_MASQ_F_VS_TUNNEL not supported.
-         * So we just set masq_flags to 0.
-         */
-        vsfill->loadbalancing_kind = 0;
+
+#ifdef KERNEL_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);
@@ -773,6 +867,10 @@ int process_stream_vrrp(FILE *stream, configuration_data *conf_data)
   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);
@@ -783,6 +881,16 @@ int process_stream_vrrp(FILE *stream, configuration_data *conf_data)
       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;
index 7e550d7..f4b7e38 100644 (file)
@@ -5,7 +5,7 @@
  * 
  * Part:        cfreader.c include file.
  *  
- * Version:     $Id: cfreader.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: cfreader.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -33,6 +33,7 @@
 
 #ifdef KERNEL_2_2
   #include <linux/ip_masq.h>
+  #include <net/ip_masq.h>
 #else
   #include <net/ip_vs.h>
 #endif
@@ -94,22 +95,27 @@ struct keyword {
 #define KW_HTTPGET     26
 #define KW_SSLGET      27
 #define KW_LDAPGET     28
-
-#define KW_VRRP                29
-#define KW_VRRPINT     30
-#define KW_VRRPVRID    31
-#define KW_VRRPAUTH    32
-#define KW_VRRPAUTHTYPE        33
-#define KW_VRRPAUTHAH  34
-#define KW_VRRPAUTHPWD 35
-#define KW_VRRPAUTHPASS        36
-#define KW_VRRPPRIO    37
-#define KW_VRRPADVERT  38
-#define KW_VRRPIPADD   39
-#define KW_VRRPSYNC    40
-#define KW_VRRPPREEMPT 41
-
-#define KW_UNKNOWN     42
+#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_UNKNOWN     45
+
+#define KEEPALIVED_DEFAULT_DELAY 60
 
 /* Structure definition  */
 typedef struct _urls {
@@ -132,8 +138,10 @@ typedef struct _keepalive_check {
 #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;
   http_get_check *http_get;    /* FIXME : for new checker use union here */
+  char *misc_check_path;
 } keepalive_check;
 
 typedef struct _real_server {
diff --git a/check.h b/check.h
index 1865ba6..d067869 100644 (file)
--- a/check.h
+++ b/check.h
@@ -5,7 +5,7 @@
  *
  * Part:        Checkers arguments structures definitions.
  *
- * Version:     $Id: check.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: check.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 3350c0d..f0e3fb6 100644 (file)
@@ -7,7 +7,7 @@
  *              url, compute a MD5 over this result and match it to the
  *              expected value.
  *
- * Version:     $Id: check_http.c,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: check_http.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 6fd6339..8de5e4b 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_http.c include file.
  *
- * Version:     $Id: check_http.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: check_http.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
diff --git a/check_misc.c b/check_misc.c
new file mode 100644 (file)
index 0000000..5a71b68
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        MISC CHECK. Perform a system call to run an extra
+ *              system prog or script.
+ *
+ * Version:     $Id: check_misc.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ *
+ * Author:      Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+#include "check_misc.h"
+
+/* does this need to be threaded? */
+int
+misc_check_call(char* cmdline)
+{
+  int retval;
+
+  retval = system(cmdline);
+
+  if (retval == 127) {
+    /* couldn't exec command */
+    syslog(LOG_DEBUG,"Couldn't exec command: %s", cmdline);
+  } else if (retval == -1) {
+    /* other error */
+    syslog(LOG_DEBUG,"Error exec-ing command: %s", cmdline);
+  } else {
+    /* everything is good */
+    syslog(LOG_DEBUG, "Successfully exec command: %s retval is %d"
+                    , cmdline, retval);
+  }
+
+  return retval;
+}
+
+int
+misc_check_thread(struct thread *thread)
+{
+  struct thread_arg *thread_arg;
+  int status;
+
+  thread_arg = THREAD_ARG(thread);
+
+  status = misc_check_call(thread_arg->svr->method->misc_check_path);
+
+  if (status == 0) {
+    /* everything is good */
+    if (!thread_arg->svr->alive) {
+      perform_svr_state(UP, thread_arg->vs, thread_arg->svr);
+    }
+  } 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;
+}
diff --git a/check_misc.h b/check_misc.h
new file mode 100644 (file)
index 0000000..d717344
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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:        check_misc.c include file.
+ *
+ * Version:     $Id: check_misc.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ *
+ * Author:      Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _MISC_H
+#define _MISC_H
+
+/* system includes */
+#include <stdlib.h>
+
+/* local includes */
+#include "cfreader.h"
+#include "ipwrapper.h"
+#include "scheduler.h"
+#include "smtp.h"
+
+/* Prototypes defs */
+extern int misc_check_thread(struct thread *thread);
+
+#endif
index 440ac17..26443b3 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        TCP checker.
  *
- * Version:     $Id: check_tcp.c,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: check_tcp.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 3d8c722..1f852d7 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_tcp.c include file.
  *
- * Version:     $Id: check_tcp.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: check_tcp.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index bcc4c4e..282d238 100755 (executable)
@@ -6,20 +6,17 @@
 # pidfile: /var/run/keepalived.pid
 # config: /etc/keepalived/keepalived.conf
 
-
-# Source function library.
-. /etc/rc.d/init.d/functions
-
 # See how we were called.
 case "$1" in
   start)
        echo -n "Starting Keepalived for LVS: "
-       daemon keepalived
+       keepalived
        echo
        ;;
   stop)
        echo -n "Shutting down Keepalived for LVS: "
-       killproc keepalived
+       PID=`ps ax | grep keepalived | awk '{print $1}'`
+       kill $PID
        echo
        ;;
   *)
index e1fad69..63589ad 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.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: ipfwwrapper.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 429b008..9269a88 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipfwwrapper.c include file.
  *
- * Version:     $Id: ipfwwrapper.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: ipfwwrapper.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index ac2d069..6435423 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.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: ipvswrapper.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
@@ -94,12 +94,8 @@ 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);
-  urule.weight = -1;
-  /*
-   *  Set MASQ as default forwarding method.
-   *  FIXME: In the current implementation we only support NAT.
-   */
-  urule.conn_flags = IP_VS_CONN_F_MASQ;
+  urule.weight = 1;
+  urule.conn_flags = vserver->loadbalancing_kind;
   urule.netmask    = ((u_int32_t) 0xffffffff);
   urule.protocol   = vserver->service_type;
   
index 2fec27b..df8b3e1 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipvswrapper.c include file.
  *
- * Version:     $Id: ipvswrapper.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: ipvswrapper.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index f9a6fb4..8b0190e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Manipulation functions for IPVS & IPFW wrappers.
  *
- * Version:     $id: ipwrapper.c,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $id: ipwrapper.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -34,10 +34,12 @@ int clear_service_vs(virtualserver *vserver)
       return 0;
     }
 
+#ifdef KERNEL_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))
         return 0;
+#endif
 
     vserver->svr = (realserver *)vserver->svr->next;
   }
@@ -56,11 +58,12 @@ int clear_services(virtualserver *vserver)
     if (!clear_service_vs(vserver))
       return 0;
 
+#ifdef KERNEL_2_2
     /* IPFW cleaner processing */
-    if (vserver->nat_mask.s_addr != HOST_NETMASK) {
+    if (vserver->nat_mask.s_addr != HOST_NETMASK)
       if (!ipfw_cmd(IP_FW_CMD_DEL, vserver, vserver->svr))
         return 0;
-    }
+#endif
 
     vserver = (virtualserver *)vserver->next;
   }
@@ -96,7 +99,9 @@ void perform_svr_state(int alive, virtualserver *vserver, realserver *rserver)
 
         vserver->s_svr->alive = 0;
         ipvs_cmd(LVS_CMD_DEL_DEST, vserver, vserver->s_svr);
+#ifdef KERNEL_2_2
         ipfw_cmd(IP_FW_CMD_DEL, vserver, vserver->s_svr);
+#endif
       }
     }
 
@@ -105,8 +110,11 @@ void perform_svr_state(int alive, virtualserver *vserver, realserver *rserver)
            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);
+
+#ifdef KERNEL_2_2
     if (vserver->nat_mask.s_addr == HOST_NETMASK)
       ipfw_cmd(IP_FW_CMD_ADD, vserver, rserver);
+#endif
 
   } else {
 
@@ -117,8 +125,11 @@ void perform_svr_state(int alive, virtualserver *vserver, realserver *rserver)
 
     /* server is down, it is removed from the LVS realserver pool */
     ipvs_cmd(LVS_CMD_DEL_DEST, vserver, rserver);
+
+#ifdef KERNEL_2_2
     if (vserver->nat_mask.s_addr == HOST_NETMASK)
       ipfw_cmd(IP_FW_CMD_DEL, vserver, rserver);
+#endif
 
     /* if all the realserver pool is down, we add sorry server */
     if (vserver->s_svr && all_realservers_down(vserver)) {
@@ -129,7 +140,10 @@ void perform_svr_state(int alive, virtualserver *vserver, realserver *rserver)
       /* 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);
+
+#ifdef KERNEL_2_2
       ipfw_cmd(IP_FW_CMD_ADD, vserver, vserver->s_svr);
+#endif
     }
 
   }
@@ -146,6 +160,7 @@ int init_service_vs(virtualserver *vserver)
       return 0;
     }
 
+#ifdef KERNEL_2_2
     /* if we have a /32 mask, we create one nat rules per
      * realserver.
      */
@@ -154,6 +169,8 @@ int init_service_vs(virtualserver *vserver)
         vserver->svr = pointersvr;
         return 0;
       }
+#endif
+
     vserver->svr = (realserver *)vserver->svr->next;
   }
   vserver->svr = pointersvr;
@@ -170,12 +187,14 @@ int init_services(virtualserver *vserver)
     if (!ipvs_cmd(LVS_CMD_ADD, vserver, vserver->svr))
       return 0;
 
+#ifdef KERNEL_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))
         return 0;
+#endif
 
     if (!init_service_vs(vserver))
       return 0;
index f3f1add..a768653 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipwrapper.c include file.
  *
- * Version:     $Id: ipwrapper.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: ipwrapper.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 2b24e4d..40762ec 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.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: layer4.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index a59d7cf..22b166f 100644 (file)
--- a/layer4.h
+++ b/layer4.h
@@ -5,7 +5,7 @@
  *
  * Part:        layer4.c include file.
  *
- * Version:     $Id: layer4.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: layer4.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
diff --git a/libnetlink/Makefile b/libnetlink/Makefile
deleted file mode 100644 (file)
index 7d2a75d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-CC     = gcc
-COPTS   = -g -O
-CFLAGS = -Wall -Wunused $(COPTS)
-
-libnetlink.a: libnetlink.a(libnetlink.o ll_map.o)
-
-libnetlink.o: libnetlink.h
-ll_map.o: ll_map.h
-
-clean:
-       rm -f *.a *.o *~
diff --git a/libnetlink/libnetlink.c b/libnetlink/libnetlink.c
deleted file mode 100644 (file)
index ce6a0b6..0000000
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
- * libnetlink.c        RTnetlink service routines.
- *
- *             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.
- *
- * Authors:    Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <fcntl.h>
-#include <net/if_arp.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <sys/uio.h>
-
-#include "libnetlink.h"
-
-#ifndef MSG_TRUNC
-#      define MSG_TRUNC 0x20
-#endif
-
-#if 1
-#      define nl_perror(str)   perror(str)
-#else
-#      define nl_perror(str)
-#endif
-
-int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions)
-{
-       int addr_len;
-
-       memset(rth, 0, sizeof(rth));
-
-       rth->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-       if (rth->fd < 0) {
-               nl_perror("Cannot open netlink socket");
-               return -1;
-       }
-
-       memset(&rth->local, 0, sizeof(rth->local));
-       rth->local.nl_family = AF_NETLINK;
-       rth->local.nl_groups = subscriptions;
-
-       if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) {
-               nl_perror("Cannot bind netlink socket");
-               return -1;
-       }
-       addr_len = sizeof(rth->local);
-       if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) {
-               nl_perror("Cannot getsockname");
-               return -1;
-       }
-       if (addr_len != sizeof(rth->local)) {
-               fprintf(stderr, "Wrong address length %d\n", addr_len);
-               return -1;
-       }
-       if (rth->local.nl_family != AF_NETLINK) {
-               fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family);
-               return -1;
-       }
-       rth->seq = time(NULL);
-       return 0;
-}
-
-int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
-{
-       struct {
-               struct nlmsghdr nlh;
-               struct rtgenmsg g;
-       } req;
-       struct sockaddr_nl nladdr;
-
-       memset(&nladdr, 0, sizeof(nladdr));
-       nladdr.nl_family = AF_NETLINK;
-
-       req.nlh.nlmsg_len = sizeof(req);
-       req.nlh.nlmsg_type = type;
-       req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
-       req.nlh.nlmsg_pid = 0;
-       req.nlh.nlmsg_seq = rth->dump = ++rth->seq;
-       req.g.rtgen_family = family;
-
-       return sendto(rth->fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr));
-}
-
-int rtnl_send(struct rtnl_handle *rth, char *buf, int len)
-{
-       struct sockaddr_nl nladdr;
-
-       memset(&nladdr, 0, sizeof(nladdr));
-       nladdr.nl_family = AF_NETLINK;
-
-       return sendto(rth->fd, buf, len, 0, (struct sockaddr*)&nladdr, sizeof(nladdr));
-}
-
-int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len)
-{
-       struct nlmsghdr nlh;
-       struct sockaddr_nl nladdr;
-       struct iovec iov[2] = { { &nlh, sizeof(nlh) }, { req, len } };
-       struct msghdr msg = {
-               (void*)&nladdr, sizeof(nladdr),
-               iov,    2,
-               NULL,   0,
-               0
-       };
-
-       memset(&nladdr, 0, sizeof(nladdr));
-       nladdr.nl_family = AF_NETLINK;
-
-       nlh.nlmsg_len = NLMSG_LENGTH(len);
-       nlh.nlmsg_type = type;
-       nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
-       nlh.nlmsg_pid = 0;
-       nlh.nlmsg_seq = rth->dump = ++rth->seq;
-
-       return sendmsg(rth->fd, &msg, 0);
-}
-
-int rtnl_dump_filter(struct rtnl_handle *rth,
-                    int (*filter)(struct sockaddr_nl *, struct nlmsghdr *n, void *),
-                    void *arg1,
-                    int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
-                    void *arg2)
-{
-       char    buf[8192];
-       struct sockaddr_nl nladdr;
-       struct iovec iov = { buf, sizeof(buf) };
-
-       while (1) {
-               int status;
-               struct nlmsghdr *h;
-
-               struct msghdr msg = {
-                       (void*)&nladdr, sizeof(nladdr),
-                       &iov,   1,
-                       NULL,   0,
-                       0
-               };
-
-               status = recvmsg(rth->fd, &msg, 0);
-
-               if (status < 0) {
-                       if (errno == EINTR)
-                               continue;
-                       nl_perror("OVERRUN");
-                       continue;
-               }
-               if (status == 0) {
-                       fprintf(stderr, "EOF on netlink\n");
-                       return -1;
-               }
-               if (msg.msg_namelen != sizeof(nladdr)) {
-                       fprintf(stderr, "sender address length == %d\n", msg.msg_namelen);
-                       exit(1);
-               }
-
-               h = (struct nlmsghdr*)buf;
-               while (NLMSG_OK(h, status)) {
-                       int err;
-
-                       if (h->nlmsg_pid != rth->local.nl_pid ||
-                           h->nlmsg_seq != rth->dump) {
-                               if (junk) {
-                                       err = junk(&nladdr, h, arg2);
-                                       if (err < 0)
-                                               return err;
-                               }
-                               goto skip_it;
-                       }
-
-                       if (h->nlmsg_type == NLMSG_DONE)
-                               return 0;
-                       if (h->nlmsg_type == NLMSG_ERROR) {
-                               struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
-                               if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
-                                       fprintf(stderr, "ERROR truncated\n");
-                               } else {
-                                       errno = -err->error;
-                                       nl_perror("RTNETLINK answers");
-                               }
-                               return -1;
-                       }
-                       err = filter(&nladdr, h, arg1);
-                       if (err < 0)
-                               return err;
-
-skip_it:
-                       h = NLMSG_NEXT(h, status);
-               }
-               if (msg.msg_flags & MSG_TRUNC) {
-                       fprintf(stderr, "Message truncated\n");
-                       continue;
-               }
-               if (status) {
-                       fprintf(stderr, "!!!Remnant of size %d\n", status);
-                       exit(1);
-               }
-       }
-}
-
-int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
-             unsigned groups, struct nlmsghdr *answer,
-             int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
-             void *jarg)
-{
-       int status;
-       struct nlmsghdr *h;
-       struct sockaddr_nl nladdr;
-       struct iovec iov = { (void*)n, n->nlmsg_len };
-       char   buf[8192];
-       struct msghdr msg = {
-               (void*)&nladdr, sizeof(nladdr),
-               &iov,   1,
-               NULL,   0,
-               0
-       };
-
-       memset(&nladdr, 0, sizeof(nladdr));
-       nladdr.nl_family = AF_NETLINK;
-       nladdr.nl_pid = peer;
-       nladdr.nl_groups = groups;
-
-       n->nlmsg_seq = ++rtnl->seq;
-       if (answer == NULL)
-               n->nlmsg_flags |= NLM_F_ACK;
-
-       status = sendmsg(rtnl->fd, &msg, 0);
-
-       if (status < 0) {
-               nl_perror("Cannot talk to rtnetlink");
-               return -1;
-       }
-
-       iov.iov_base = buf;
-       iov.iov_len = sizeof(buf);
-
-       while (1) {
-               status = recvmsg(rtnl->fd, &msg, 0);
-
-               if (status < 0) {
-                       if (errno == EINTR)
-                               continue;
-                       nl_perror("OVERRUN");
-                       continue;
-               }
-               if (status == 0) {
-                       fprintf(stderr, "EOF on netlink\n");
-                       return -1;
-               }
-               if (msg.msg_namelen != sizeof(nladdr)) {
-                       fprintf(stderr, "sender address length == %d\n", msg.msg_namelen);
-                       exit(1);
-               }
-               for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
-                       int err;
-                       int len = h->nlmsg_len;
-                       pid_t pid=h->nlmsg_pid;
-                       int l = len - sizeof(*h);
-                       unsigned seq=h->nlmsg_seq;
-
-                       if (l<0 || len>status) {
-                               if (msg.msg_flags & MSG_TRUNC) {
-                                       fprintf(stderr, "Truncated message\n");
-                                       return -1;
-                               }
-                               fprintf(stderr, "!!!malformed message: len=%d\n", len);
-                               exit(1);
-                       }
-
-                       if (h->nlmsg_pid != pid || h->nlmsg_seq != seq) {
-                               if (junk) {
-                                       err = junk(&nladdr, h, jarg);
-                                       if (err < 0)
-                                               return err;
-                               }
-                               continue;
-                       }
-
-                       if (h->nlmsg_type == NLMSG_ERROR) {
-                               struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
-                               if (l < sizeof(struct nlmsgerr)) {
-                                       fprintf(stderr, "ERROR truncated\n");
-                               } else {
-                                       errno = -err->error;
-                                       if (errno == 0) {
-                                               if (answer)
-                                                       memcpy(answer, h, h->nlmsg_len);
-                                               return 0;
-                                       }
-                                       nl_perror("RTNETLINK answers");
-                               }
-                               return -1;
-                       }
-                       if (answer) {
-                               memcpy(answer, h, h->nlmsg_len);
-                               return 0;
-                       }
-
-                       fprintf(stderr, "Unexpected reply!!!\n");
-
-                       status -= NLMSG_ALIGN(len);
-                       h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
-               }
-               if (msg.msg_flags & MSG_TRUNC) {
-                       fprintf(stderr, "Message truncated\n");
-                       continue;
-               }
-               if (status) {
-                       fprintf(stderr, "!!!Remnant of size %d\n", status);
-                       exit(1);
-               }
-       }
-}
-
-int rtnl_listen(struct rtnl_handle *rtnl, 
-             int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
-             void *jarg)
-{
-       int status;
-       struct nlmsghdr *h;
-       struct sockaddr_nl nladdr;
-       struct iovec iov;
-       char   buf[8192];
-       struct msghdr msg = {
-               (void*)&nladdr, sizeof(nladdr),
-               &iov,   1,
-               NULL,   0,
-               0
-       };
-
-       memset(&nladdr, 0, sizeof(nladdr));
-       nladdr.nl_family = AF_NETLINK;
-       nladdr.nl_pid = 0;
-       nladdr.nl_groups = 0;
-
-
-       iov.iov_base = buf;
-       iov.iov_len = sizeof(buf);
-
-       while (1) {
-               status = recvmsg(rtnl->fd, &msg, 0);
-
-               if (status < 0) {
-                       if (errno == EINTR)
-                               continue;
-                       nl_perror("OVERRUN");
-                       continue;
-               }
-               if (status == 0) {
-                       fprintf(stderr, "EOF on netlink\n");
-                       return -1;
-               }
-               if (msg.msg_namelen != sizeof(nladdr)) {
-                       fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen);
-                       exit(1);
-               }
-               for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
-                       int err;
-                       int len = h->nlmsg_len;
-                       int l = len - sizeof(*h);
-
-                       if (l<0 || len>status) {
-                               if (msg.msg_flags & MSG_TRUNC) {
-                                       fprintf(stderr, "Truncated message\n");
-                                       return -1;
-                               }
-                               fprintf(stderr, "!!!malformed message: len=%d\n", len);
-                               exit(1);
-                       }
-
-                       err = handler(&nladdr, h, jarg);
-                       if (err < 0)
-                               return err;
-
-                       status -= NLMSG_ALIGN(len);
-                       h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
-               }
-               if (msg.msg_flags & MSG_TRUNC) {
-                       fprintf(stderr, "Message truncated\n");
-                       continue;
-               }
-               if (status) {
-                       fprintf(stderr, "!!!Remnant of size %d\n", status);
-                       exit(1);
-               }
-       }
-}
-
-int rtnl_from_file(FILE *rtnl, 
-             int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
-             void *jarg)
-{
-       int status;
-       struct sockaddr_nl nladdr;
-       char   buf[8192];
-       struct nlmsghdr *h = (void*)buf;
-
-       memset(&nladdr, 0, sizeof(nladdr));
-       nladdr.nl_family = AF_NETLINK;
-       nladdr.nl_pid = 0;
-       nladdr.nl_groups = 0;
-
-       while (1) {
-               int err, len, type;
-               pid_t pid;
-               int l;
-               unsigned seq;
-
-               status = fread(&buf, 1, sizeof(*h), rtnl);
-
-               if (status < 0) {
-                       if (errno == EINTR)
-                               continue;
-                       nl_perror("rtnl_from_file: fread");
-                       return -1;
-               }
-               if (status == 0)
-                       return 0;
-
-               len = h->nlmsg_len;
-               type= h->nlmsg_type;
-               pid=h->nlmsg_pid;
-               l = len - sizeof(*h);
-               seq=h->nlmsg_seq;
-
-               if (l<0 || len>sizeof(buf)) {
-                       fprintf(stderr, "!!!malformed message: len=%d @%lu\n",
-                               len, ftell(rtnl));
-                       return -1;
-               }
-
-               status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl);
-
-               if (status < 0) {
-                       nl_perror("rtnl_from_file: fread");
-                       return -1;
-               }
-               if (status < l) {
-                       fprintf(stderr, "rtnl-from_file: truncated message\n");
-                       return -1;
-               }
-
-               err = handler(&nladdr, h, jarg);
-               if (err < 0)
-                       return err;
-       }
-}
-
-int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data)
-{
-       int len = RTA_LENGTH(4);
-       struct rtattr *rta;
-       if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
-               return -1;
-       rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));
-       rta->rta_type = type;
-       rta->rta_len = len;
-       memcpy(RTA_DATA(rta), &data, 4);
-       n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
-       return 0;
-}
-
-int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
-{
-       int len = RTA_LENGTH(alen);
-       struct rtattr *rta;
-
-       if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
-               return -1;
-       rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));
-       rta->rta_type = type;
-       rta->rta_len = len;
-       memcpy(RTA_DATA(rta), data, alen);
-       n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
-       return 0;
-}
-
-int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data)
-{
-       int len = RTA_LENGTH(4);
-       struct rtattr *subrta;
-
-       if (RTA_ALIGN(rta->rta_len) + len > maxlen)
-               return -1;
-       subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
-       subrta->rta_type = type;
-       subrta->rta_len = len;
-       memcpy(RTA_DATA(subrta), &data, 4);
-       rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len;
-       return 0;
-}
-
-int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen)
-{
-       struct rtattr *subrta;
-       int len = RTA_LENGTH(alen);
-
-       if (RTA_ALIGN(rta->rta_len) + len > maxlen)
-               return -1;
-       subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len));
-       subrta->rta_type = type;
-       subrta->rta_len = len;
-       memcpy(RTA_DATA(subrta), data, alen);
-       rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len;
-       return 0;
-}
-
-
-int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
-{
-       while (RTA_OK(rta, len)) {
-               if (rta->rta_type <= max)
-                       tb[rta->rta_type] = rta;
-               rta = RTA_NEXT(rta,len);
-       }
-       if (len)
-               fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len);
-       return 0;
-}
-
-/****************************************************************
- NAME  : rtnl_close                            00/06/02 23:43:45
- AIM   : 
- REMARK        :
-****************************************************************/
-int rtnl_close(struct rtnl_handle *rth)
-{
-       /* close the fd */
-       close( rth->fd );
-       return(0);
-}
-
diff --git a/libnetlink/libnetlink.h b/libnetlink/libnetlink.h
deleted file mode 100644 (file)
index 1444c7d..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef __LIBNETLINK_H__
-#define __LIBNETLINK_H__ 1
-
-#include <asm/types.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-
-struct rtnl_handle
-{
-       int                     fd;
-       struct sockaddr_nl      local;
-       struct sockaddr_nl      peer;
-       __u32                   seq;
-       __u32                   dump;
-};
-
-extern int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions);
-extern int rtnl_close(struct rtnl_handle *rth);
-extern int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type);
-extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len);
-extern int rtnl_dump_filter(struct rtnl_handle *rth,
-                           int (*filter)(struct sockaddr_nl *, struct nlmsghdr *n, void *),
-                           void *arg1,
-                           int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
-                           void *arg2);
-extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
-                    unsigned groups, struct nlmsghdr *answer,
-                    int (*junk)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
-                    void *jarg);
-extern int rtnl_send(struct rtnl_handle *rth, char *buf, int);
-
-
-extern int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data);
-extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen);
-extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data);
-extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen);
-
-extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len);
-
-extern int rtnl_listen(struct rtnl_handle *, int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
-                      void *jarg);
-extern int rtnl_from_file(FILE *, int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
-                      void *jarg);
-
-#endif /* __LIBNETLINK_H__ */
-
diff --git a/libnetlink/ll_map.c b/libnetlink/ll_map.c
deleted file mode 100644 (file)
index e5a95e6..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * ll_map.c
- *
- *             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.
- *
- * Authors:    Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <string.h>
-
-#include "libnetlink.h"
-#include "ll_map.h"
-
-struct idxmap
-{
-       struct idxmap * next;
-       int             index;
-       int             type;
-       int             alen;
-       unsigned        flags;
-       unsigned char   addr[8];
-       char            name[16];
-};
-
-static struct idxmap *idxmap[16];
-
-int ll_remember_index(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
-{
-       int h;
-       struct ifinfomsg *ifi = NLMSG_DATA(n);
-       struct idxmap *im, **imp;
-       struct rtattr *tb[IFLA_MAX+1];
-
-       if (n->nlmsg_type != RTM_NEWLINK)
-               return 0;
-
-       if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi)))
-               return -1;
-
-
-       memset(tb, 0, sizeof(tb));
-       parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));
-       if (tb[IFLA_IFNAME] == NULL)
-               return 0;
-
-       h = ifi->ifi_index&0xF;
-
-       for (imp=&idxmap[h]; (im=*imp)!=NULL; imp = &im->next)
-               if (im->index == ifi->ifi_index)
-                       break;
-
-       if (im == NULL) {
-               im = malloc(sizeof(*im));
-               if (im == NULL)
-                       return 0;
-               im->next = *imp;
-               im->index = ifi->ifi_index;
-               *imp = im;
-       }
-
-       im->type = ifi->ifi_type;
-       im->flags = ifi->ifi_flags;
-       if (tb[IFLA_ADDRESS]) {
-               int alen;
-               im->alen = alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
-               if (alen > sizeof(im->addr))
-                       alen = sizeof(im->addr);
-               memcpy(im->addr, RTA_DATA(tb[IFLA_ADDRESS]), alen);
-       } else {
-               im->alen = 0;
-               memset(im->addr, 0, sizeof(im->addr));
-       }
-       strcpy(im->name, RTA_DATA(tb[IFLA_IFNAME]));
-       return 0;
-}
-
-const char *ll_idx_n2a(int idx, char *buf)
-{
-       struct idxmap *im;
-
-       if (idx == 0)
-               return "*";
-       for (im = idxmap[idx&0xF]; im; im = im->next)
-               if (im->index == idx)
-                       return im->name;
-       snprintf(buf, 16, "if%d", idx);
-       return buf;
-}
-
-
-const char *ll_index_to_name(int idx)
-{
-       static char nbuf[16];
-
-       return ll_idx_n2a(idx, nbuf);
-}
-
-int ll_index_to_type(int idx)
-{
-       struct idxmap *im;
-
-       if (idx == 0)
-               return -1;
-       for (im = idxmap[idx&0xF]; im; im = im->next)
-               if (im->index == idx)
-                       return im->type;
-       return -1;
-}
-
-unsigned ll_index_to_flags(int idx)
-{
-       struct idxmap *im;
-
-       if (idx == 0)
-               return 0;
-
-       for (im = idxmap[idx&0xF]; im; im = im->next)
-               if (im->index == idx)
-                       return im->flags;
-       return 0;
-}
-
-int ll_name_to_index(char *name)
-{
-       static char ncache[16];
-       static int icache;
-       struct idxmap *im;
-       int i;
-
-       if (name == NULL)
-               return 0;
-       if (icache && strcmp(name, ncache) == 0)
-               return icache;
-       for (i=0; i<16; i++) {
-               for (im = idxmap[i]; im; im = im->next) {
-                       if (strcmp(im->name, name) == 0) {
-                               icache = im->index;
-                               strcpy(ncache, name);
-                               return im->index;
-                       }
-               }
-       }
-       return 0;
-}
-
-int ll_init_map(struct rtnl_handle *rth)
-{
-       if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) {
-               perror("Cannot send dump request");
-               exit(1);
-       }
-
-       if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) {
-               fprintf(stderr, "Dump terminated\n");
-               exit(1);
-       }
-       return 0;
-}
diff --git a/libnetlink/ll_map.h b/libnetlink/ll_map.h
deleted file mode 100644 (file)
index 739f157..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __LL_MAP_H__
-#define __LL_MAP_H__ 1
-
-extern int ll_remember_index(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
-extern int ll_init_map(struct rtnl_handle *rth);
-extern int ll_name_to_index(char *name);
-extern const char *ll_index_to_name(int idx);
-extern const char *ll_idx_n2a(int idx, char *buf);
-extern int ll_index_to_type(int idx);
-extern unsigned ll_index_to_flags(int idx);
-
-#endif /* __LL_MAP_H__ */
diff --git a/main.c b/main.c
index 1b68f9a..94effca 100644 (file)
--- a/main.c
+++ b/main.c
@@ -5,7 +5,7 @@
  *
  * Part:        Main program structure.
  *
- * Version:     $Id: main.c,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: main.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -125,6 +125,10 @@ int main(int argc, char **argv)
     closelog();
     exit(0);
   }
+
+  /* daemonize process */
+  daemon(0, 0);
+
   /* write the pidfile */
   if (!pidfile_write(getpid())) {
     syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
@@ -152,9 +156,6 @@ int main(int argc, char **argv)
   /* Signal handling initialization  */
   signal_init();
 
-  /* daemonize process */
-  daemon(0, 0);
-
   /* Create the master thread */
   master = thread_make_master();
 
@@ -171,6 +172,7 @@ int main(int argc, char **argv)
   /* We then cleanup the room & closelog */
   thread_destroy_master(master);
   clear_services(conf_data->lvstopology);
+
   /* Stop VRRP instances */
   clear_vrrp_instance(conf_data->vrrp);
   clear_conf(conf_data);
diff --git a/main.h b/main.h
index 55d0bd3..ef815ce 100644 (file)
--- a/main.h
+++ b/main.h
@@ -5,7 +5,7 @@
  *
  * Part:        Main program include file.
  *
- * Version:     $Id: main.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: main.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -39,6 +39,6 @@ struct thread_master *master;
 
 /* Build version */
 #define PROG    "keepalived"
-#define VERSION "0.4.1 (14/09, 2001)"
+#define VERSION "0.4.8 (20/11, 2001)"
 
 #endif
index 146fa76..bcd7736 100644 (file)
--- a/pidfile.c
+++ b/pidfile.c
@@ -5,7 +5,7 @@
  *
  * Part:        pidfile utility.
  *
- * Version:     $Id: pidfile.c,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: pidfile.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 15cb41b..1360a2e 100644 (file)
--- a/pidfile.h
+++ b/pidfile.h
@@ -5,7 +5,7 @@
  *
  * Part:        pidfile.c include file.
  *
- * Version:     $Id: pidfile.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: pidfile.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
diff --git a/samples/keepalived.conf.misc_check b/samples/keepalived.conf.misc_check
new file mode 100644 (file)
index 0000000..31d9111
--- /dev/null
@@ -0,0 +1,119 @@
+# Configuration File for keepalived
+
+global_defs {
+   notification_email {
+     acassen
+   }
+   notification_email_from Alexandre.Cassen@firewall.loc
+   smtp_server 192.168.200.1
+   smtp_connect_timeout 30
+   lvs_id LVS_DEVEL
+}
+
+virtual_server 10.10.10.2 1358 {
+    delay_loop 6
+    lb_algo rr 
+    lb_kind NAT
+    nat_mask 255.255.255.0
+    persistence_timeout 50
+    protocol TCP
+
+    sorry_server 192.168.200.200 1358
+
+    real_server 192.168.200.2 1358 {
+        weight 1
+        HTTP_GET {
+            url { 
+              path /testurl/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334d
+            }
+            url { 
+              path /testurl2/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334d
+            }
+            url { 
+              path /testurl3/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334d
+            }
+            connect_timeout 3
+            nb_get_retry 3
+            delay_before_retry 3
+        }
+    }
+
+    real_server 192.168.200.3 1358 {
+        weight 1
+        HTTP_GET {
+            url { 
+              path /testurl/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334c
+            }
+            url { 
+              path /testurl2/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334c
+            }
+            connect_timeout 3
+            nb_get_retry 3
+            delay_before_retry 3
+        }
+    }
+
+    real_server 192.168.200.6 1358 {
+        weight 1
+        MISC_CHECK {
+          misc_path /usr/local/bin/script.sh
+        }
+    }
+
+}
+
+virtual_server 10.10.10.3 1358 {
+    delay_loop 3
+    lb_algo rr 
+    lb_kind NAT
+    nat_mask 255.255.255.0
+    persistence_timeout 50
+    protocol TCP
+
+    real_server 192.168.200.4 1358 {
+        weight 1
+        HTTP_GET {
+            url { 
+              path /testurl/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334d
+            }
+            url { 
+              path /testurl2/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334d
+            }
+            url { 
+              path /testurl3/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334d
+            }
+            connect_timeout 3
+            nb_get_retry 3
+            delay_before_retry 3
+        }
+    }
+
+    real_server 192.168.200.5 1358 {
+        weight 1
+        HTTP_GET {
+            url { 
+              path /testurl/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334d
+            }
+            url { 
+              path /testurl2/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334d
+            }
+            url { 
+              path /testurl3/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334d
+            }
+            connect_timeout 3
+            nb_get_retry 3
+            delay_before_retry 3
+        }
+    }
+}
similarity index 52%
rename from keepalived.conf.vrrp
rename to samples/keepalived.conf.vrrp
index d3d4c3f..10327b2 100644 (file)
@@ -10,38 +10,61 @@ global_defs {
    lvs_id LVS_DEVEL
 }
 
+
 vrrp_instance VI_1 {
+    state MASTER
     interface eth0
-    virtual_router_id 50
+    virtual_router_id 51
+    priority 100
+    advert_int 1
     authentication {
         auth_type AH
-        auth_pass k!4@lve1
+        auth_pass 1111
     }
-    priority 100
+    virtual_ipaddress {
+        192.168.200.16
+        192.168.200.17
+        192.168.200.18
+    }
+}
+
+vrrp_instance VI_2 {
+    interface eth0
+    virtual_router_id 50
+    priority 50
     advert_int 1
     virtual_ipaddress {
-        192.168.200.11
-        192.168.200.12
         192.168.200.13
+        192.168.200.14
+        192.168.200.15
     }
-    sync_instance VI_2
-    preempt
 }
 
-vrrp_instance VI_2 {
+vrrp_instance VI_3 {
+    state MASTER
     interface eth1
-    virtual_router_id 51
+    virtual_router_id 52
+    priority 100
+    advert_int 1
     authentication {
         auth_type AH
-        auth_pass k!4@lve2
+        auth_pass 1111
     }
-    priority 100
-    advert_int 1
     virtual_ipaddress {
-        192.168.201.11
-        192.168.201.12
         192.168.201.13
+        192.168.201.14
+        192.168.201.15
     }
-    sync_instance VI_1
 }
 
+vrrp_instance VI_4 {
+    interface eth1
+    virtual_router_id 53
+    priority 50
+    advert_int 1
+    virtual_ipaddress {
+        192.168.201.16
+        192.168.201.17
+        192.168.201.18
+    }
+}
diff --git a/samples/keepalived.conf.vrrp.sync b/samples/keepalived.conf.vrrp.sync
new file mode 100644 (file)
index 0000000..f252960
--- /dev/null
@@ -0,0 +1,70 @@
+# Configuration File for keepalived
+
+global_defs {
+   notification_email {
+     acassen@canal-plus.com
+   }
+   notification_email_from keepalived@canal-plus.com
+   smtp_server 172.31.47.6
+   smtp_connect_timeout 30
+   lvs_id LVS_DEVEL
+}
+
+vrrp_instance VI_1 {
+    state MASTER
+    interface eth0
+    virtual_router_id 51
+    priority 150
+    advert_int 1
+    authentication {
+        auth_type AH
+        auth_pass 1111
+    }
+    virtual_ipaddress {
+        192.168.200.16
+        192.168.200.17
+        192.168.200.18
+    }
+}
+
+vrrp_instance VI_2 {
+    interface eth0
+    virtual_router_id 52
+    priority 100
+    advert_int 1
+    virtual_ipaddress {
+        192.168.200.19
+        192.168.200.20
+        192.168.200.21
+    }
+    sync_instance VI_3
+}
+
+vrrp_instance VI_3 {
+    interface eth1
+    virtual_router_id 53
+    priority 100
+    advert_int 1
+    virtual_ipaddress {
+        192.168.201.19
+        192.168.201.20
+        192.168.201.21
+    }
+    sync_instance VI_2
+}
+
+virtual_server 192.168.200.19 80 {
+    delay_loop 20
+    lb_algo rr
+    lb_kind NAT
+    nat_mask 255.255.255.0
+    persistence_timeout 50
+    protocol TCP
+
+    real_server 192.168.201.100 80 {
+        weight 1
+        TCP_CHECK {
+            connect_timeout 3
+        }
+    }
+}
diff --git a/samples/sample.misccheck.smbcheck.sh b/samples/sample.misccheck.smbcheck.sh
new file mode 100644 (file)
index 0000000..f555296
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+# remove it as smbcheck.sh and put it the location you want
+
+SAMBA_BIN=`which smbclient 2> /dev/null`
+
+if [ -z "$SAMBA_BIN" ] ; then
+       exit 2
+fi
+
+if [ -z "$1" ] ; then
+       echo "Usage: $0 <ip address>"
+       exit 2
+fi 
+
+($SAMBA_BIN -N -L $1 -W CENTRALB -U nobody) \
+ | egrep '^Domain=\[[A-Za-z0-9_-]+\]' > /dev/null 2>&1
+
index d3acacf..338cd82 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.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: scheduler.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -101,7 +101,7 @@ thread_list_add_before (struct thread_list *list,
 }
 
 /* timer compare */
-static int
+int
 thread_timer_cmp (struct timeval a, struct timeval b)
 {
   if (a.tv_sec > b.tv_sec) 
@@ -551,26 +551,26 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
 retry:  /* When thread can't fetch try to find next thread again. */
 
   /* If there is event process it first. */
-  while ((thread = thread_trim_head (&m->event))) {
+  while ((thread = thread_trim_head(&m->event))) {
     *fetch = *thread;
     free(timer_wait);
 
     /* If daemon hanging event is received return NULL pointer */ 
     if (thread->type == THREAD_TERMINATE) {
       thread->type = THREAD_UNUSED;
-      thread_add_unuse (m, thread);
+      thread_add_unuse(m, thread);
       return NULL;
     }
     thread->type = THREAD_UNUSED;
-    thread_add_unuse (m, thread);
+    thread_add_unuse(m, thread);
     return fetch;
   }
 
   /* If there is ready threads process them */
-  while ((thread = thread_trim_head (&m->ready))) {
+  while ((thread = thread_trim_head(&m->ready))) {
     *fetch = *thread;
     thread->type = THREAD_UNUSED;
-    thread_add_unuse (m, thread);
+    thread_add_unuse(m, thread);
     free(timer_wait);
     return fetch;
   }
@@ -727,6 +727,10 @@ register_vs_worker_thread(struct thread_master *master,
         break;
       case LDAP_GET_ID:
         break;
+      case MISC_CHECK_ID:
+        thread_arg = thread_arg_new(root, lstptr, lstptr->svr);
+        thread_add_timer(master, misc_check_thread, thread_arg,
+                         thread_arg->vs->delay_loop);
       default:
         break;
     }
@@ -742,16 +746,11 @@ void
 register_worker_thread(struct thread_master *master, configuration_data *lstptr)
 {
   virtualserver *pointervs;
-  vrrp_instance *pointervrrp;
 
-  /* register VRRP specifics threads */
-  pointervrrp = lstptr->vrrp;
-  while (lstptr->vrrp) {
-    thread_add_event(master, vrrp_state_init_thread, lstptr->vrrp, VRRP_STATE_INIT);
-
-    lstptr->vrrp = (vrrp_instance *)lstptr->vrrp->next;
-  }
-  lstptr->vrrp = pointervrrp;
+  /* 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;
index 1b22995..318de41 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        scheduler.c include file.
  *
- * Version:     $Id: scheduler.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: scheduler.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -86,7 +86,7 @@ struct thread
 
 /* MICRO SEC def */
 #define TIMER_SEC_MICRO 1000000
-#define TIMER_MAX_SEC   10
+#define TIMER_MAX_SEC   1000
 
 /* Macros. */
 #define THREAD_ARG(X) ((X)->arg)
@@ -148,6 +148,9 @@ thread_fetch (struct thread_master *m,
 void
 thread_call (struct thread *thread);
 
+int
+thread_timer_cmp (struct timeval a, struct timeval b);
+
 struct timeval
 thread_timer_sub (struct timeval a, struct timeval b);
 
@@ -163,6 +166,9 @@ extern int
 http_connect_thread(struct thread *thread);
 
 extern int
-vrrp_state_init_thread(struct thread *thread);
+misc_check_thread(struct thread *thread);
+
+extern int
+vrrp_dispatcher_init_thread(struct thread *thread);
 
 #endif
diff --git a/smtp.c b/smtp.c
index 381aeba..7ea3d9a 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.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: smtp.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -465,30 +465,33 @@ void smtp_alert(struct thread_master *master,
   struct thread_arg *thread_arg;
   struct smtp_thread_arg *smtp_arg;
 
-  /* allocate a new thread_arg */
-  thread_arg = thread_arg_new(root, NULL, NULL);
+  /* Only send mail if email specified */
+  if (root->email) {
+    /* allocate a new thread_arg */
+    thread_arg = thread_arg_new(root, NULL, NULL);
 
-  /* allocate & initialize smtp argument data structure */
-  smtp_arg = (struct smtp_thread_arg *)malloc(sizeof(struct smtp_thread_arg));
-  memset(smtp_arg, 0, sizeof(struct smtp_thread_arg));
+    /* allocate & initialize smtp argument data structure */
+    smtp_arg = (struct smtp_thread_arg *)malloc(sizeof(struct smtp_thread_arg));
+    memset(smtp_arg, 0, sizeof(struct smtp_thread_arg));
 
-  smtp_arg->subject = (char *)malloc(MAX_SUBJECT_LENGTH);
-  smtp_arg->body = (char *)malloc(MAX_BODY_LENGTH);
-  memset(smtp_arg->subject, 0, MAX_SUBJECT_LENGTH);
-  memset(smtp_arg->body, 0, MAX_BODY_LENGTH);
+    smtp_arg->subject = (char *)malloc(MAX_SUBJECT_LENGTH);
+    smtp_arg->body = (char *)malloc(MAX_BODY_LENGTH);
+    memset(smtp_arg->subject, 0, MAX_SUBJECT_LENGTH);
+    memset(smtp_arg->body, 0, 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);
-  else
-    snprintf(smtp_arg->subject, MAX_SUBJECT_LENGTH, "[%s] %s", root->lvs_id, subject);
+    /* 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);
+    else
+      snprintf(smtp_arg->subject, MAX_SUBJECT_LENGTH, "[%s] %s", root->lvs_id, subject);
 
-  strncpy(smtp_arg->body, body, MAX_BODY_LENGTH);
+    strncpy(smtp_arg->body, body, MAX_BODY_LENGTH);
 
-  thread_arg->checker_arg = smtp_arg;
+    thread_arg->checker_arg = smtp_arg;
 
-  thread_add_event(master, smtp_connect_thread, thread_arg, 0);
+    thread_add_event(master, smtp_connect_thread, thread_arg, 0);
+  }
 }
diff --git a/smtp.h b/smtp.h
index df8e212..1a6a78b 100644 (file)
--- a/smtp.h
+++ b/smtp.h
@@ -5,7 +5,7 @@
  *
  * Part:        smtp.c include file.
  *
- * Version:     $Id: smtp.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: smtp.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
diff --git a/utils.c b/utils.c
index 26f04bd..e50581d 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -5,7 +5,7 @@
  *
  * Part:        General program utils.
  *
- * Version:     $Id: utils.c,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: utils.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
diff --git a/vrrp.c b/vrrp.c
index 9f9273c..0ba8d5e 100644 (file)
--- a/vrrp.c
+++ b/vrrp.c
@@ -4,10 +4,9 @@
  *              master fails, a backup server takes over.
  *              The original implementation has been made by jerome etienne.
  *
- * Version:     $Id: vrrp.c,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: vrrp.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
- *              Based on the Jerome Etienne, <jetienne@arobas.net> code.
  *
  *              This program is distributed in the hope that it will be useful, 
  *              but WITHOUT ANY WARRANTY; without even the implied warranty of 
  */
 
 /* local include */
-#include "scheduler.h"
-#include "cfreader.h"
-#include "utils.h"
+#include "vrrp_scheduler.h"
 #include "vrrp.h"
 
-/* local prototypes */
-static int vrrp_state_goto_master_thread(struct thread *thread);
-static int vrrp_state_master_thread(struct thread *thread);
-int vrrp_state_backup_thread(struct thread *thread);
-
 /* compute checksum */
 static u_short in_csum( u_short *addr, int len, u_short csum)
 {
@@ -63,8 +55,23 @@ static u_short in_csum( u_short *addr, int len, u_short csum)
   return (answer);
 }
 
+/* retrieve MAC address from interface name */
+static int hwaddr_get(char *ifname, char *addr, int addrlen)
+{
+  struct ifreq ifr;
+  int fd = socket(AF_INET, SOCK_DGRAM, 0);
+  int ret;
+
+  if (fd < 0) return (-1);
+  strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+  ret = ioctl(fd, SIOCGIFHWADDR, (char *)&ifr);
+  memcpy(addr, ifr.ifr_hwaddr.sa_data, addrlen);
+  close(fd);
+  return ret;
+}
+
 /* resolve ipaddress from interface name */
-static uint32_t ifname_to_ip(char *ifname)
+static uint32_t ifname_to_ip(const char *ifname)
 {
   struct ifreq ifr;
   int fd = socket(AF_INET, SOCK_DGRAM, 0);
@@ -82,7 +89,7 @@ static uint32_t ifname_to_ip(char *ifname)
 }
 
 /* resolve interface index from interface name */
-static int ifname_to_idx(char *ifname)
+int ifname_to_idx(const char *ifname)
 {
   struct ifreq ifr;
   int fd = socket(AF_INET, SOCK_DGRAM, 0);
@@ -97,102 +104,60 @@ static int ifname_to_idx(char *ifname)
   return ifindex;
 }
 
-/* retrieve MAC options */
-static int rcvhwaddr_op(char *ifname, char *addr, int addrlen, int addF)
+/* resolve ifname from index */
+static void index_to_ifname(const int ifindex, char *ifname)
 {
   struct ifreq ifr;
   int fd = socket(AF_INET, SOCK_DGRAM, 0);
-  int ret;
 
-  if (fd < 0) return (-1);
+  if (fd < 0) return;
 
-  strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-  memcpy( ifr.ifr_hwaddr.sa_data, addr, addrlen );
-  ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
-
-  ret = ioctl(fd, addF ? SIOCADDMULTI : SIOCDELMULTI, (char *)&ifr);
-  if (ret) {
-    syslog(LOG_INFO, "Can't %s on %s. errno=%d"
-                   , addF ? "SIOCADDMULTI" : "SIOCDELMULTI"
-                   , ifname, errno );
-  }
+  /* get interface name */
+  ifr.ifr_ifindex = ifindex;
+  if (ioctl(fd, SIOCGIFNAME, (char *)&ifr) == 0)
+    strncpy(ifname, ifr.ifr_name, sizeof(ifr.ifr_name));
   close(fd);
-  return ret;
 }
 
-/* Set MAC address - need to shutdown the interface before */
-static int hwaddr_set(char *ifname, char *addr, int addrlen)
+/* resolve ipaddress from interface index */
+static uint32_t index_to_ip(const int ifindex)
 {
-  struct ifreq ifr;
-  int fd = socket(AF_INET, SOCK_DGRAM, 0);
-  int ret;
-  unsigned long flags;
-
-  if (fd < 0) return (-1);
-  strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-
-  /* get the flags */
-  ret = ioctl(fd, SIOCGIFFLAGS, (char *)&ifr);
-  if (ret) goto end;
-  flags = ifr.ifr_flags;
+  char ifname[IFNAMSIZ];
 
-  /* set the interface down */
-  ifr.ifr_flags &= ~IFF_UP;
-  ret = ioctl(fd, SIOCSIFFLAGS, (char *)&ifr);
-  if(ret) goto end;
+  memset(&ifname, 0, IFNAMSIZ);
+  index_to_ifname(ifindex, ifname);
 
-  /* change the hwaddr */
-  memcpy(ifr.ifr_hwaddr.sa_data, addr, addrlen);
-  ifr.ifr_hwaddr.sa_family = AF_UNIX;
-  ret = ioctl(fd, SIOCSIFHWADDR, (char *)&ifr);
-  if(ret) goto end;
-
-  /* set the interface up */
-  ifr.ifr_flags = flags;
-  ret = ioctl(fd, SIOCSIFFLAGS, (char *)&ifr);
-  if(ret) goto end;
-
-end:;
-  if (ret) syslog(LOG_INFO, "MAC set : error errno=%d", errno);
-
-  close(fd);
-  return ret;
-}
-
-/* retrieve MAC address from interface name */
-static int hwaddr_get(char *ifname, char *addr, int addrlen)
-{
-  struct ifreq ifr;
-  int fd = socket(AF_INET, SOCK_DGRAM, 0);
-  int ret;
-
-  if (fd < 0) return (-1);
-  strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-  ret = ioctl(fd, SIOCGIFHWADDR, (char *)&ifr);
-  memcpy(addr, ifr.ifr_hwaddr.sa_data, addrlen);
-  close(fd);
-  return ret;
+  return(ifname_to_ip(ifname));
 }
 
 /* add/remove VIP */
-static int ipaddr_ops(vrrp_rt *vsrv, int addF)
+static int vrrp_handle_ipaddress(vrrp_rt *vsrv, int cmd)
 {
   int i, err = 0;
+  int retry = 0;
   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];
-    if(!addF && !vadd->deletable) continue;
-
-    if (ipaddr_op(ifidx , vadd->addr, addF)) {
+    if(!cmd && !vadd->deletable) continue;
+retry:
+    if (netlink_address_ipv4(ifidx , 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"
-                     , addF ? "set" : "remove"
+                     , cmd ? "set" : "remove"
                      , inet_ntoa(in)
                      , 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);
+        if (!retry) {
+          retry++;
+          goto retry;
+        }
+      }
     } else {
       vadd->deletable = 1;
     }
@@ -213,7 +178,7 @@ static int vrrp_iphdr_len(vrrp_rt *vsrv)
 }
 
 /* IPSEC AH header length */
-static int vrrp_ipsecah_len(vrrp_rt *vsrv)
+int vrrp_ipsecah_len()
 {
   return sizeof(ipsec_ah);
 }
@@ -230,7 +195,7 @@ static int vrrp_hd_len(vrrp_rt *vsrv)
  * IPSEC AH incoming packet check.
  * return 0 for a valid pkt, != 0 otherwise.
  */
-static int vrrp_in_chk_ipsecah( vrrp_rt *vsrv, char *buffer)
+static int vrrp_in_chk_ipsecah(vrrp_rt *vsrv, char *buffer)
 {
   struct iphdr *ip = (struct iphdr*)(buffer);
   ipsec_ah *ah = (ipsec_ah *)((char *)ip + (ip->ihl<<2));
@@ -252,7 +217,7 @@ static int vrrp_in_chk_ipsecah( vrrp_rt *vsrv, char *buffer)
   vsrv->ipsecah_counter->seq_number++;
   if (ah->seq_number >= vsrv->ipsecah_counter->seq_number) {
 #ifdef DEBUG
-  syslog(LOG_DEBUG, "IPSEC AH : SEQUENCE NUMBER : %d\n", ah->seq_number);
+//  syslog(LOG_DEBUG, "IPSEC AH : SEQUENCE NUMBER : %d\n", ah->seq_number);
 #endif
     vsrv->ipsecah_counter->seq_number = ah->seq_number;
   } else {
@@ -277,10 +242,10 @@ static int vrrp_in_chk_ipsecah( vrrp_rt *vsrv, char *buffer)
   memset(ah->auth_data, 0, sizeof(ah->auth_data));
 
   /* Compute the ICV */
-  hmac_md5(buffer, vrrp_iphdr_len(vsrv)+vrrp_ipsecah_len(vsrv)+vrrp_hd_len(vsrv),
+  hmac_md5(buffer, vrrp_iphdr_len(vsrv)+vrrp_ipsecah_len()+vrrp_hd_len(vsrv),
            vsrv->vif->auth_data, sizeof(vsrv->vif->auth_data), digest);
 
-  if (memcmp(backup_auth_data,digest,HMAC_MD5_TRUNC) != 0) {
+  if (memcmp(backup_auth_data, digest, HMAC_MD5_TRUNC) != 0) {
     syslog(LOG_INFO, "IPSEC AH : invalid IPSEC HMAC-MD5 value."
                      " Due to fields mutation or bad password !");
     return 1;
@@ -297,7 +262,7 @@ static int vrrp_in_chk_vips(vrrp_rt *vsrv, uint32_t ipaddr, unsigned char *buffe
   uint32_t ipbuf;
 
   for (i=0; i < vsrv->naddr; i++) {
-    bcopy(buffer+i*sizeof(uint32_t),&ipbuf,sizeof(uint32_t));
+    bcopy(buffer+i*sizeof(uint32_t), &ipbuf, sizeof(uint32_t));
     if (ipaddr == ntohl(ipbuf)) return 1;
   }
 
@@ -320,7 +285,7 @@ static int vrrp_in_chk(vrrp_rt *vsrv, char *buffer)
 
   if (vif->auth_type == VRRP_AUTH_AH) {
     ah = (ipsec_ah *)(buffer + sizeof(struct iphdr));
-    hd = (vrrp_pkt *)(buffer + ihl + vrrp_ipsecah_len(vsrv));
+    hd = (vrrp_pkt *)(buffer + ihl + vrrp_ipsecah_len());
   } else {
     hd = (vrrp_pkt *)(buffer + ihl);
   }
@@ -379,8 +344,11 @@ static int vrrp_in_chk(vrrp_rt *vsrv, char *buffer)
   }
 
   /* MUST verify that the VRID is valid on the receiving interface */
-  if (vsrv->vrid != hd->vrid)
-    return VRRP_PACKET_KO;
+  if (vsrv->vrid != hd->vrid) {
+    syslog(LOG_INFO, "received VRID mismatch. Received %d, Expected %d", 
+                     hd->vrid, vsrv->vrid);
+    return VRRP_PACKET_DROP;
+  }
 
   /*
    * MAY verify that the IP address(es) associated with the
@@ -398,7 +366,7 @@ static int vrrp_in_chk(vrrp_rt *vsrv, char *buffer)
                      , vsrv->vaddr[i].addr);
       syslog(LOG_INFO, "one or more VIP associated with"
                        " VRID mismatch actual MASTER advert");
-      return VRRP_PACKET_DROP;
+      return VRRP_PACKET_KO;
     }
 
   /*
@@ -414,7 +382,7 @@ static int vrrp_in_chk(vrrp_rt *vsrv, char *buffer)
 
   /* check the authenicaion if it is ipsec ah */
   if(hd->auth_type == VRRP_AUTH_AH)
-    return(vrrp_in_chk_ipsecah(vsrv,buffer));
+    return(vrrp_in_chk_ipsecah(vsrv, buffer));
 
   return VRRP_PACKET_OK;
 }
@@ -448,7 +416,7 @@ static void vrrp_build_ip(vrrp_rt *vsrv, char *buffer, int buflen)
   ip->ihl      = 5;
   ip->version  = 4;
   ip->tos      = 0;
-  ip->tot_len  = ip->ihl*4 + vrrp_hd_len( vsrv );
+  ip->tot_len  = ip->ihl*4 + vrrp_hd_len(vsrv);
   ip->tot_len  = htons(ip->tot_len);
   ip->id       = ++vsrv->vif->ip_id;
   ip->frag_off = 0;
@@ -460,7 +428,7 @@ static void vrrp_build_ip(vrrp_rt *vsrv, char *buffer, int buflen)
   ip->daddr    = htonl(INADDR_VRRP_GROUP);
 
   /* checksum must be done last */
-  ip->check = in_csum( (u_short*)ip, ip->ihl*4, 0 );
+  ip->check = in_csum((u_short*)ip, ip->ihl*4, 0);
 }
 
 /* build IPSEC AH header */
@@ -469,17 +437,17 @@ static void vrrp_build_ipsecah(vrrp_rt *vsrv, char *buffer, int buflen)
   ICV_mutable_fields *ip_mutable_fields;
   unsigned char *digest;
   struct iphdr *ip = (struct iphdr *)(buffer);
-  ipsec_ah *ah = (ipsec_ah *)(buffer+sizeof(struct iphdr));
+  ipsec_ah *ah = (ipsec_ah *)(buffer + sizeof(struct iphdr));
 
   /* alloc a temp memory space to stock the ip mutable fields */
-  ip_mutable_fields=calloc(sizeof(ICV_mutable_fields),1);
-  memset(ip_mutable_fields,0,sizeof(ICV_mutable_fields));
+  ip_mutable_fields=calloc(sizeof(ICV_mutable_fields), 1);
+  memset(ip_mutable_fields, 0, sizeof(ICV_mutable_fields));
 
   /* fill in next header filed --rfc2402.2.1 */
   ah->next_header = IPPROTO_VRRP;
 
   /* update IP header total length value */
-  ip->tot_len = ip->ihl*4 + vrrp_ipsecah_len( vsrv ) + vrrp_hd_len( vsrv );
+  ip->tot_len = ip->ihl*4 + vrrp_ipsecah_len() + vrrp_hd_len(vsrv);
   ip->tot_len = htons(ip->tot_len);
 
   /* update ip checksum */
@@ -568,21 +536,21 @@ static int vrrp_build_vrrp(vrrp_rt *vsrv, int prio, char *buffer, int buflen)
 
   /* copy the ip addresses */
   for( i = 0; i < vsrv->naddr; i++ ){
-    iparr[i] = htonl( vsrv->vaddr[i].addr );
+    iparr[i] = htonl(vsrv->vaddr[i].addr);
   }
   hd->chksum  = in_csum( (u_short*)hd, vrrp_hd_len(vsrv), 0);
 
   /* copy the passwd if the authentication is VRRP_AH_PASS */
   if( vif->auth_type == VRRP_AUTH_PASS ){
-    char  *pw  = (char *)hd+sizeof(*hd)+vsrv->naddr*4;
-    memcpy( pw, vif->auth_data, sizeof(vif->auth_data));
+    char *pw = (char *)hd + sizeof(*hd) + vsrv->naddr*4;
+    memcpy(pw, vif->auth_data, sizeof(vif->auth_data));
   }
 
   return(0);
 }
 
 /* build VRRP packet */
-static void vrrp_build_pkt( vrrp_rt *vsrv, int prio, char *buffer, int buflen )
+static void vrrp_build_pkt(vrrp_rt *vsrv, int prio, char *buffer, int buflen)
 {
   char *bufptr;
 
@@ -594,23 +562,23 @@ static void vrrp_build_pkt( vrrp_rt *vsrv, int prio, char *buffer, int buflen )
   /* build the ip header */
   buffer += vrrp_dlt_len(vsrv);
   buflen -= vrrp_dlt_len(vsrv);
-  vrrp_build_ip( vsrv, buffer, buflen );
+  vrrp_build_ip(vsrv, buffer, buflen);
 
   /* build the vrrp header */
   buffer += vrrp_iphdr_len(vsrv);
 
   if (vsrv->vif->auth_type == VRRP_AUTH_AH)
-    buffer += vrrp_ipsecah_len(vsrv);
+    buffer += vrrp_ipsecah_len();
   buflen -= vrrp_iphdr_len(vsrv);
 
   if (vsrv->vif->auth_type == VRRP_AUTH_AH)
-    buflen -= vrrp_ipsecah_len(vsrv);
+    buflen -= vrrp_ipsecah_len();
   vrrp_build_vrrp(vsrv, prio, buffer, buflen);
 
   /* build the IPSEC AH header */
   if (vsrv->vif->auth_type == VRRP_AUTH_AH) {
     bufptr += vrrp_dlt_len(vsrv);
-    buflen += vrrp_ipsecah_len(vsrv) + vrrp_iphdr_len(vsrv);;
+    buflen += vrrp_ipsecah_len() + vrrp_iphdr_len(vsrv);;
     vrrp_build_ipsecah(vsrv, bufptr, buflen);
   }
 }
@@ -623,18 +591,18 @@ static int vrrp_send_pkt(vrrp_rt *vsrv, char *buffer, int buflen)
   int fd = socket(PF_PACKET, SOCK_PACKET, 0x300); /* 0x300 is magic */
 
   if( fd < 0 ){
-    syslog(LOG_DEBUG, "VRRP Error : socket creation");
+    syslog(LOG_INFO, "VRRP Error : socket creation");
     return -1;
   }
 
   /* build the address */
   memset(&from, 0 , sizeof(from));
-  strcpy( from.sa_data, vsrv->vif->ifname );
+  strcpy(from.sa_data, vsrv->vif->ifname);
 
   /* send the data */
   len = sendto(fd, buffer, buflen, 0, &from, sizeof(from));
 
-  close( fd );
+  close(fd);
   return len;
 }
 
@@ -647,7 +615,7 @@ static int vrrp_send_adv(vrrp_rt *vsrv, int prio)
   /* alloc the memory */
   buflen = vrrp_dlt_len(vsrv) + vrrp_iphdr_len(vsrv) + vrrp_hd_len(vsrv);
   if (vsrv->vif->auth_type == VRRP_AUTH_AH)
-    buflen += vrrp_ipsecah_len(vsrv);
+    buflen += vrrp_ipsecah_len();
   buffer = calloc(buflen, 1);
   memset(buffer,0,buflen);
 
@@ -656,37 +624,31 @@ static int vrrp_send_adv(vrrp_rt *vsrv, int prio)
 
   /* send it */
   ret = vrrp_send_pkt(vsrv, buffer, buflen);
-#ifdef DEBUG
-  syslog(LOG_DEBUG, "Sending VRRP Advert on %s", vsrv->vif->ifname);
-//  printf("Sending on : %s : fd :%d\n", vsrv->vif->ifname,vsrv->sockfd);
-//  print_buffer(buflen,buffer);
-#endif
 
   /* free the memory */
   free(buffer);
   return ret;
 }
 
-
 /* Received packet processing */
-static int vrrp_read(vrrp_rt *vsrv, char *buf, int buflen)
+int vrrp_check_packet(vrrp_rt *vsrv, char *buf, int buflen)
 {
-  int len = 0;
   int ret;
 
-  len = read(vsrv->sockfd, buf, buflen);
-
-#ifdef DEBUG
-  syslog(LOG_DEBUG, "VRRP packet received (%d bytes)", len);
-//  print_buffer(buflen,buf);
-#endif
-
-  if (len > 0) {
+  if (buflen > 0) {
     ret = vrrp_in_chk(vsrv, buf);
 
-    if (ret == VRRP_PACKET_KO || ret == VRRP_PACKET_DROP)
-      syslog(LOG_INFO, "bogus VRRP packet received !!!");
+    if (ret == VRRP_PACKET_DROP) {
+      syslog(LOG_INFO, "Sync instance needed on %s !!!",
+                       vsrv->vif->ifname);
+    }
 
+    if (ret == VRRP_PACKET_KO)
+      syslog(LOG_INFO, "bogus VRRP packet received on %s !!!",
+                       vsrv->vif->ifname);
+//    else
+//      syslog(LOG_INFO, "Success receiving VRRP packet on %s.",
+//                       vsrv->vif->ifname);
     return ret;
   }
 
@@ -694,7 +656,7 @@ static int vrrp_read(vrrp_rt *vsrv, char *buf, int buflen)
 }
 
 /* send a gratuitous ARP packet */
-static int send_gratuitous_arp(vrrp_rt *vsrv, int addr, int vAddrF)
+static int send_gratuitous_arp(vrrp_rt *vsrv, int addr)
 {
   struct m_arphdr {
     unsigned short int ar_hrd;          /* Format of hardware address.  */
@@ -709,11 +671,11 @@ static int send_gratuitous_arp(vrrp_rt *vsrv, int addr, int vAddrF)
     unsigned char __ar_tip[4];          /* Target IP address.  */
   };
 
-  char buf[sizeof(struct m_arphdr)+ETHER_HDR_LEN];
-  char buflen = sizeof(struct m_arphdr)+ETHER_HDR_LEN;
+  char buf[sizeof(struct m_arphdr) + ETHER_HDR_LEN];
+  char buflen = sizeof(struct m_arphdr) + ETHER_HDR_LEN;
   struct ether_header *eth = (struct ether_header *)buf;
-  struct m_arphdr *arph = (struct m_arphdr *)(buf+vrrp_dlt_len(vsrv));
-  char  *hwaddr = vAddrF ? vsrv->hwaddr : vsrv->vif->hwaddr;
+  struct m_arphdr *arph = (struct m_arphdr *)(buf + vrrp_dlt_len(vsrv));
+  char  *hwaddr = vsrv->vif->hwaddr;
   int  hwlen = ETH_ALEN;
 
   /* hardcoded for ethernet */
@@ -722,7 +684,7 @@ static int send_gratuitous_arp(vrrp_rt *vsrv, int addr, int vAddrF)
   eth->ether_type = htons(ETHERTYPE_ARP);
 
   /* build the arp payload */
-  memset(arph, 0, sizeof( *arph ));
+  memset(arph, 0, sizeof(*arph));
   arph->ar_hrd = htons(ARPHRD_ETHER);
   arph->ar_pro = htons(ETHERTYPE_IP);
   arph->ar_hln = 6;
@@ -735,263 +697,143 @@ static int send_gratuitous_arp(vrrp_rt *vsrv, int addr, int vAddrF)
   return vrrp_send_pkt(vsrv, buf, buflen);
 }
 
-/* becoming master */
-static int vrrp_state_goto_master_thread(struct thread *thread)
+/* Gratuitous ARP on each VIP */
+void vrrp_send_gratuitous_arp(vrrp_instance *vrrp_instance)
 {
-  int  i;
-  vrrp_instance *vrrp_instance = THREAD_ARG(thread);
+  int  i, j;
   vrrp_rt *vsrv = vrrp_instance->vsrv;
-  vrrp_if *vif = vsrv->vif;
-  struct rt_entry *rt_table;
-
-  /* set the VRRP MAC address -- rfc2338.7.3 */
-  if(!vsrv->no_vmac) {
-    /* backup the routing table */
-    rt_table = iproute_list(vif->ifname);
 
-    hwaddr_set(vif->ifname, vsrv->hwaddr, sizeof(vsrv->hwaddr));
-    rcvhwaddr_op(vif->ifname, vif->hwaddr, sizeof(vif->hwaddr), 1);
+  /* send gratuitous arp for each virtual ip */
+  for (j = 0; j < 5; j++)
+    for (i = 0; i < vsrv->naddr; i++)
+      send_gratuitous_arp(vsrv, vsrv->vaddr[i].addr);
+}
 
-    /* restore routing table */
-    iproute_restore(rt_table, vif->ifname);
-    iproute_clear(rt_table);
-  }
+/* becoming master */
+void vrrp_state_goto_master(vrrp_instance *vrrp_instance)
+{
+  vrrp_rt *vsrv = vrrp_instance->vsrv;
 
   /* add the ip addresses */
-  ipaddr_ops(vsrv, 1);
+  vrrp_handle_ipaddress(vsrv, VRRP_IPADDRESS_ADD);
 
   /* send an advertisement */
   vrrp_send_adv(vsrv, vsrv->priority);
 
-  /* send gratuitous arp for each virtual ip */
-  for (i = 0; i < vsrv->naddr; i++)
-    send_gratuitous_arp(vsrv, vsrv->vaddr[i].addr, 1);
+  /* remotes arp tables update */
+  vrrp_send_gratuitous_arp(vrrp_instance);
 
-  syslog(LOG_INFO, "VRRP_Instance(%s) entering MASTER STATE"
+  syslog(LOG_INFO, "VRRP_Instance(%s) Entering MASTER STATE"
                  , vrrp_instance->iname);
 
-  /* register master state thread */
   vsrv->state = VRRP_STATE_MAST;
-  thread_add_read(thread->master, vrrp_state_master_thread, vrrp_instance, 
-                  vsrv->sockfd, vsrv->adver_int);
-
-  return 0;
 }
 
 /* leaving master state */
 static void vrrp_restore_interface(vrrp_rt *vsrv, int advF)
 {
-  uint32_t addr[1024];
-  vrrp_if *vif = vsrv->vif;
-  struct rt_entry *rt_table;
-
-  /* restore the original MAC addresses */
-  if (!vsrv->no_vmac) {
-    /* backup the routing table */
-    rt_table = iproute_list(vif->ifname);
-
-    hwaddr_set(vif->ifname, vif->hwaddr, sizeof(vif->hwaddr));
-    rcvhwaddr_op(vif->ifname, vif->hwaddr, sizeof(vif->hwaddr), 0);
-
-    /* restore routing table */
-    iproute_restore(rt_table, vif->ifname);
-    iproute_clear(rt_table);
-  }
-
   /* remove the ip addresses */
-  ipaddr_ops(vsrv, 0);
+  vrrp_handle_ipaddress(vsrv, VRRP_IPADDRESS_DEL);
 
-  /* if we stop vrrpd, warn the other routers to speed up the recovery */
-  if (advF) {
+  /* if we stop vrrp, warn the other routers to speed up the recovery */
+  if (advF)
     vrrp_send_adv(vsrv, VRRP_PRIO_STOP);
-  }
-
-  /*
-   * Send gratuitous ARP for all the non-vrrp ip addresses to update
-   * the cache of remote hosts using these addresses
-   */
-  if (!vsrv->no_vmac) {
-    int i, naddr;
-    naddr = ipaddr_list(ifname_to_idx(vif->ifname), addr
-                        , sizeof(addr)/sizeof(addr[0]));
-    for (i = 0; i < naddr; i++)
-      send_gratuitous_arp(vsrv, addr[i], 0);
-  }
 }
 
-static int vrrp_state_leave_master_thread(struct thread *thread)
+void vrrp_state_leave_master(vrrp_instance *instance)
 {
-  vrrp_instance *vrrp_instance = THREAD_ARG(thread);
-  vrrp_rt *vsrv = vrrp_instance->vsrv;
+  vrrp_rt *vsrv = instance->vsrv;
 
-  /* restore the routing table & remove VIPs */
+  /* Remove VIPs */
   vrrp_restore_interface(vsrv, 0);
 
   syslog(LOG_INFO, "VRRP_Instance(%s) Entering BACKUP STATE"
-                 , vrrp_instance->iname);
+                 , instance->iname);
 
   /* register the vrrp backup handler */
   vsrv->state = VRRP_STATE_BACK;
-  thread_add_read(thread->master, vrrp_state_backup_thread, vrrp_instance,
-                  vsrv->sockfd, vsrv->ms_down_timer);
-  return 0;
 }
 
 /* BACKUP state processing */
-int vrrp_state_backup_thread(struct thread *thread)
+void vrrp_state_backup(vrrp_instance *instance, char *buf, int buflen)
 {
-  char *buf;
   int ret = 0;
-  int buflen = 0;
-  struct iphdr *iph;
+  vrrp_rt *vsrv = instance->vsrv;
+  struct iphdr *iph = (struct iphdr *)buf;
   vrrp_pkt *hd;
-  vrrp_instance *vrrp_instance = THREAD_ARG(thread);
-  vrrp_rt *vsrv = vrrp_instance->vsrv;
 
-//printf("-----[ %s ]------\nBACKUP STATE fd : %d\n", vrrp_instance->iname, thread->u.fd);
-
-  if (thread->type == THREAD_READ_TIMEOUT) {
-
-    /* If becoming MASTER in IPSEC AH AUTH, we reset the anti-replay */
-    if (vsrv->ipsecah_counter->cycle) {
-      vsrv->ipsecah_counter->cycle = 0;
-      vsrv->ipsecah_counter->seq_number = 0;
-    }
-
-    /* register the vrrp transit backup state */
-    vsrv->state = VRRP_STATE_BACK;
-    thread_add_event(thread->master, vrrp_state_goto_master_thread, 
-                     vrrp_instance, VRRP_STATE_MAST);
-
-    syslog(LOG_INFO, "VRRP_Instance(%s) becoming MASTER"
-                   , vrrp_instance->iname);
-  } else {
-    /* buffer allocation */
-    if(vsrv->vif->auth_type == VRRP_AUTH_AH) {
-      buflen = vrrp_iphdr_len(vsrv) + vrrp_ipsecah_len(vsrv) + vrrp_hd_len(vsrv);
-      buf = calloc(buflen,1); 
-      memset(buf,0,buflen);
-
-      /* fill the header structure */
-      ret = vrrp_read(vsrv, buf, buflen);
-      iph = (struct iphdr *)buf;
-      hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2) + vrrp_ipsecah_len(vsrv));
-    } else {
-      buflen = vrrp_iphdr_len(vsrv) + vrrp_hd_len(vsrv);
-      buf = calloc(buflen, 1);
-      memset(buf,0,buflen);
-
-      /* fill the header structure */
-      ret = vrrp_read( vsrv, buf, buflen );
-      iph = (struct iphdr *)buf;
-      hd = (vrrp_pkt *)((char *)iph + (iph->ihl<<2));
-    }
-
-    if (ret == VRRP_PACKET_KO   || 
-        ret == VRRP_PACKET_NULL ||
-        ret == VRRP_PACKET_DROP) {
-      syslog(LOG_INFO, "Dropping received advertisment...\n");
-      vsrv->ms_down_timer = 3 * vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);
-    } else if (hd->priority == 0) {
-      vsrv->ms_down_timer = VRRP_TIMER_SKEW(vsrv);
-    } else if( !vsrv->preempt || hd->priority >= vsrv->priority ) {
-      vsrv->ms_down_timer = 3 * vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);
-    }
+  /* Fill the VRRP header */
+  switch (iph->protocol) {
+    case IPPROTO_IPSEC_AH:
+      hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2) + vrrp_ipsecah_len());
+      break;
+    case IPPROTO_VRRP:
+      hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2));
+      break;
+  }
 
-    /* register next vrrp master thread */
-    thread_add_read(thread->master, vrrp_state_backup_thread, vrrp_instance,
-                    thread->u.fd, vsrv->ms_down_timer);
+  /* Process the incoming packet */
+  ret = vrrp_check_packet(vsrv, buf, buflen);
 
-    free(buf);
+  if (ret == VRRP_PACKET_KO   || 
+      ret == VRRP_PACKET_NULL) {
+    syslog(LOG_INFO, "VRRP_Instance(%s) ignoring received advertisment..."
+                   , instance->iname);
+    vsrv->ms_down_timer = 3 * vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);
+  } else if (hd->priority == 0) {
+    vsrv->ms_down_timer = VRRP_TIMER_SKEW(vsrv);
+  } else if( !vsrv->preempt || hd->priority >= vsrv->priority ) {
+    vsrv->ms_down_timer = 3 * vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);
   }
-
-  return 0;
 }
 
 /* MASTER state processing */
-static int vrrp_state_master_thread(struct thread *thread)
+void vrrp_state_master_tx(vrrp_instance *instance, const int prio)
 {
-  char *buf;
-  int ret = 0;
-  int buflen = 0;
-  struct iphdr *iph;
-  vrrp_pkt *hd;
-  vrrp_instance *vrrp_instance = THREAD_ARG(thread);
-  vrrp_rt *vsrv = vrrp_instance->vsrv;
-
-//printf("-----[ %s ]------\nMASTER STATE fd : %d\n", vrrp_instance->iname, thread->u.fd);
-
-  if (thread->type == THREAD_READ_TIMEOUT) {
-
-    if (vsrv->wantstate == VRRP_STATE_BACK ||
-        vsrv->ipsecah_counter->cycle) {
-      vsrv->ms_down_timer = 3 * vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);
-
-      /* register the vrrp transit backup state */
-      vsrv->state  = VRRP_STATE_BACK;
-      thread_add_event(thread->master, vrrp_state_leave_master_thread, 
-                       vrrp_instance, VRRP_STATE_BACK);
-
-      syslog(LOG_INFO, "VRRP_Instance(%s) becoming BACKUP"
-                     , vrrp_instance->iname);
-    }
+  vrrp_rt *vsrv = instance->vsrv;
 
+  if (prio == VRRP_PRIO_OWNER)
+    vrrp_send_adv(vsrv, VRRP_PRIO_OWNER);
+  else
     vrrp_send_adv(vsrv, vsrv->priority);
+}
 
-    /* register next vrrp master thread */
-    thread_add_read(thread->master, vrrp_state_master_thread, vrrp_instance,
-                    thread->u.fd, vsrv->adver_int);
-  } else {
-    /* buffer allocation */
-    if (vsrv->vif->auth_type == VRRP_AUTH_AH) {
-      buflen = vrrp_iphdr_len(vsrv) + vrrp_ipsecah_len(vsrv) + vrrp_hd_len(vsrv);
-      buf = calloc(buflen,1); 
-      memset(buf,0,buflen);
-
-      /* fill the header structure */
-      ret = vrrp_read(vsrv, buf, buflen);
-      iph = (struct iphdr *)buf;
-      hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2) + vrrp_ipsecah_len(vsrv));
-    } else {
-      buflen = vrrp_iphdr_len(vsrv) + vrrp_hd_len(vsrv);
-      buf = calloc(buflen, 1);
-      memset(buf,0,buflen);
-
-      /* fill the header structure */
-      ret = vrrp_read(vsrv, buf, buflen);
-      iph = (struct iphdr *)buf;
-      hd = (vrrp_pkt *)((char *)iph + (iph->ihl<<2));
-    }
-
-    if (ret == VRRP_PACKET_KO   || 
-        ret == VRRP_PACKET_NULL ||
-        ret == VRRP_PACKET_DROP) {
-      syslog(LOG_INFO, "Dropping received VRRP packet...\n");
-      vrrp_send_adv(vsrv, vsrv->priority);
-
-      /* register next vrrp master thread */
-      thread_add_read(thread->master, vrrp_state_master_thread, vrrp_instance,
-                      thread->u.fd, vsrv->adver_int);
-
-    } else if (hd->priority == 0) {
-      vrrp_send_adv(vsrv, vsrv->priority);
-
-      /* register next vrrp master thread */
-      thread_add_read(thread->master, vrrp_state_master_thread, vrrp_instance,
-                      thread->u.fd, vsrv->adver_int);
+int vrrp_state_master_rx(vrrp_instance *instance, char *buf, int buflen)
+{
+  int ret = 0;
+  vrrp_rt *vsrv = instance->vsrv;
+  struct iphdr *iph = (struct iphdr *)buf;
+  vrrp_pkt *hd;
 
-    } else if( hd->priority > vsrv->priority ||
-              (hd->priority == vsrv->priority &&
-              ntohl(iph->saddr) > vsrv->vif->ipaddr)) {
+  /* Fill the VRRP header */
+  switch (iph->protocol) {
+    case IPPROTO_IPSEC_AH:
+      hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2) + vrrp_ipsecah_len());
+      break;
+    case IPPROTO_VRRP:
+      hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2));
+      break;
+  }
 
-      vsrv->ms_down_timer = 3 * vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);
+  /* Process the incoming packet */
+  ret = vrrp_check_packet(vsrv, buf, buflen);
 
-      /* register the vrrp transit backup state */
-      vsrv->state  = VRRP_STATE_BACK;
-      thread_add_event(thread->master, vrrp_state_leave_master_thread, 
-                       vrrp_instance, VRRP_STATE_BACK);
-    }
-    free(buf);
+  if (ret == VRRP_PACKET_KO   ||
+      ret == VRRP_PACKET_NULL ||
+      ret == VRRP_PACKET_DROP) {
+    syslog(LOG_INFO, "VRRP_Instance(%s) Dropping received VRRP packet..."
+                   , instance->iname);
+    vrrp_send_adv(vsrv, vsrv->priority);
+    return 0;
+  } else if (hd->priority == 0) {
+    vrrp_send_adv(vsrv, vsrv->priority);
+    return 0;
+  } else if( hd->priority > vsrv->priority ||
+            (hd->priority == vsrv->priority &&
+            ntohl(iph->saddr) > vsrv->vif->ipaddr)) {
+    vsrv->ms_down_timer = 3 * vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);
+    vsrv->state = VRRP_STATE_BACK;
+    return 1;
   }
 
   return 0;
@@ -1013,9 +855,6 @@ static int chk_min_cfg(vrrp_rt *vsrv)
     return 0;
   }
 
-  /* vrrp structure is completed */
-  vsrv->initF = 1;
-
   return 1;
 }
 
@@ -1054,104 +893,68 @@ int complete_vrrp_init(vrrp_rt *vsrv)
 }
 
 /* open the socket and join the multicast group. */
-static int open_vrrp_socket(vrrp_rt *vsrv)
+int open_vrrp_socket(const int proto, const int index)
 {
-  struct ip_mreq req;
-  struct ip_mreqn interface;
-  u_char loop;
+  struct ip_mreqn req_add;
+  char ifname[IFNAMSIZ];
   int fd;
   int ret;
 
   /* open the socket */
-  if (vsrv->vif->auth_type == VRRP_AUTH_AH)
-    fd = socket(AF_INET, SOCK_RAW, IPPROTO_IPSEC_AH);
-  else
-    fd = socket(AF_INET, SOCK_RAW, IPPROTO_VRRP);
+  fd = socket(AF_INET, SOCK_RAW, proto);
 
-  if(fd < 0){
+  if (fd < 0) {
     int err = errno;
     syslog(LOG_INFO, "cant open raw socket. errno=%d. (try to run it as root)"
                    , err);
     return -1;
   }
 
-  /* join the multicast group */
-  memset(&req, 0, sizeof (req));
-  req.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);
-  req.imr_interface.s_addr = htonl(vsrv->vif->ipaddr);
-  ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
-                   (char *)&req, sizeof(struct ip_mreq));
-
-  /* disable loop back to local socket */
-  loop = 0;
-//  setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
-
+  /* -> inbound processing option
+   * Specify the bound_dev_if.
+   * why IP_ADD_MEMBERSHIP & IP_MULTICAST_IF doesnt set
+   * sk->bound_dev_if themself ??? !!!
+   * Needed for filter multicasted advert per interface.
+   * 
+   * -- If you read this !!! and know the answer to the question
+   *    please feal free to answer me ! :)
+   */
+  memset(ifname, 0, IFNAMSIZ);
+  index_to_ifname(index, ifname);
+  ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
+                   ifname, strlen(ifname)+1);
   if (ret < 0) {
     int  err = errno;
-    syslog(LOG_INFO, "cant do IP_ADD_MEMBERSHIP errno=%d", err);
+    syslog(LOG_INFO, "cant bind to device %s. errno=%d. (try to run it as root)",
+                     ifname, err);
+    close(fd); /* sd leak handle */
     return -1;
   }
-#ifdef DEBUG
-    else {
-    syslog(LOG_DEBUG, "VRRP socket successfully created...");
-  }
-#endif
-
-  /* binding the socket to the local interface */
-  memset(&interface, 0, sizeof(interface));
-  interface.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);
-  interface.imr_address.s_addr = htonl(vsrv->vif->ipaddr);
-  interface.imr_ifindex = ifname_to_idx(vsrv->vif->ifname);
-  ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
-                   &interface, sizeof(struct ip_mreqn));
 
+  /* -> outbound processing option
+   * join the multicast group.
+   * binding the socket to the interface for outbound multicast
+   * traffic.
+   */
+  memset(&req_add, 0, sizeof (req_add));
+  req_add.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);
+  req_add.imr_address.s_addr = htonl(index_to_ip(index));
+  req_add.imr_ifindex = index;
+  ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+                   (char *)&req_add, sizeof(struct ip_mreqn));
   if (ret < 0) {
     int  err = errno;
-    syslog(LOG_INFO, "cant bind socket to interface errno=%d", err);
+    syslog(LOG_INFO, "cant do IP_ADD_MEMBERSHIP errno=%d", err);
     return -1;
   }
 
   return fd;
 }
 
-/* 
- * Initialize state handling
- * --rfc2338.6.4.1
- */
-int vrrp_state_init_thread(struct thread *thread)
-{
-  vrrp_instance *vrrp_instance = THREAD_ARG(thread);
-  vrrp_rt *vsrv = vrrp_instance->vsrv;
-  int fd;
-
-  /* create the socket */
-  fd = open_vrrp_socket(vsrv);
-  if (fd < 0) return -1;
-
-  vsrv->sockfd = fd;
-
-  if (vsrv->priority == VRRP_PRIO_OWNER ||
-      vsrv->wantstate == VRRP_STATE_MAST){
-    thread_add_event(thread->master, vrrp_state_goto_master_thread, 
-                     vrrp_instance, VRRP_STATE_MAST);
-  } else {
-    vsrv->ms_down_timer = 3 * vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);
-
-    syslog(LOG_INFO, "VRRP_Instance(%s) Entering BACKUP STATE"
-                   , vrrp_instance->iname);
-
-    /* register the vrrp backup handler */
-    vsrv->state = VRRP_STATE_BACK;
-    thread_add_read(thread->master, vrrp_state_backup_thread,
-                    vrrp_instance, fd, vsrv->ms_down_timer);
-  }
-
-  return 0;
-}
-
 /* handle terminate state */
 void vrrp_state_stop_instance(vrrp_rt *vsrv)
 {
   /* restore MAC, routing table & remove VIPs */
-  vrrp_restore_interface(vsrv, 1);
+  if (vsrv->state == VRRP_STATE_MAST)
+    vrrp_restore_interface(vsrv, 1);
 }
diff --git a/vrrp.h b/vrrp.h
index b8b468d..f7db1bb 100644 (file)
--- a/vrrp.h
+++ b/vrrp.h
@@ -4,7 +4,7 @@
  *              master fails, a backup server takes over.
  *              The original implementation has been made by jerome etienne.
  *
- * Version:     $Id: vrrp.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: vrrp.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              Based on the Jerome Etienne, <jetienne@arobas.net> code.
 #include <net/if.h>
 #include <net/if_arp.h>
 #include <sys/ioctl.h>
+#include <sys/time.h>
+#include <unistd.h>
 
 /* local include */
-#include "vrrp_iproute.h"
+#include "cfreader.h"
 #include "vrrp_ipaddress.h"
 #include "vrrp_ipsecah.h"
+#include "utils.h"
 
 typedef struct {       /* rfc2338.5.1 */
        uint8_t         vers_type;      /* 0-3=type, 4-7=version */
@@ -62,7 +65,8 @@ typedef struct {      /* rfc2338.5.1 */
 #define VRRP_ADVER_DFL 1       /* advert. interval (in sec) -- rfc2338.5.3.7 */
 #define VRRP_PREEMPT_DFL 1     /* rfc2338.6.1.2.Preempt_Mode */
 
-typedef struct {       /* parameters per interface -- rfc2338.6.1.1 */
+/* parameters per interface -- rfc2338.6.1.1 */
+typedef struct {
        int             auth_type;      /* authentification type. VRRP_AUTH_* */
        uint8_t         auth_data[8];   /* authentification data */
 
@@ -77,7 +81,6 @@ typedef struct {      /* parameters per interface -- rfc2338.6.1.1 */
         * to warn the user only if the outoing mtu is too small
         */
        int             ip_id;
-
 } vrrp_if;
 
 typedef struct {
@@ -85,28 +88,23 @@ typedef struct {
        int             deletable;      /* TRUE if one of my primary addr */
 } vip_addr;
 
-typedef struct {       /* parameters per virtual router -- rfc2338.6.1.2 */
+/* parameters per virtual router -- rfc2338.6.1.2 */
+typedef struct {
        int     vrid;           /* virtual id. from 1(!) to 255 */
        int     priority;       /* priority value */
        int     naddr;          /* number of ip addresses */
        vip_addr *vaddr;        /* point on the ip address array */
        int     adver_int;      /* delay between advertisements(in sec) */      
        char    hwaddr[6];      /* VMAC -- rfc2338.7.3 */
-
-#if 0  /* dynamically calculated */
-       double  skew_time;      /* skew Master_Down_Interval. (256-Prio)/256 */ 
-       int     mast_down_int;  /* interval for backup to declare master down*/
-#endif
        int     preempt;        /* true if a higher prio preempt a lower one */
        int     state;          /* internal state (init/backup/master) */
+       int     init_state;     /* the initial state of the instance */
        int     wantstate;      /* user explicitly wants a state (back/mast) */
-       int     sockfd;         /* the socket descriptor */
-       int     initF;          /* true if the struct is init */
-       int     no_vmac;        /* dont handle the virtual MAC --rfc2338.7.3 */
+       int     fd;             /* the socket descriptor */
 
        /* rfc2336.6.2 */
        uint32_t        ms_down_timer;
-       uint32_t        adver_timer;
+       struct timeval  sands;
 
        /* IPSEC AH counter def --rfc2402.3.3.2 */
        seq_counter *ipsecah_counter;
@@ -116,30 +114,35 @@ typedef struct {  /* parameters per virtual router -- rfc2338.6.1.2 */
 } vrrp_rt;
 
 /* VRRP state machine -- rfc2338.6.4 */
-#define VRRP_STATE_INIT        1       /* rfc2338.6.4.1 */
-#define VRRP_STATE_BACK        2       /* rfc2338.6.4.2 */
-#define VRRP_STATE_MAST        3       /* rfc2338.6.4.3 */
-#define VRRP_STATE_NONE        99      /* internal */
+#define VRRP_DISPATCHER        0       /* internal */
+#define VRRP_STATE_INIT                1       /* rfc2338.6.4.1 */
+#define VRRP_STATE_BACK                2       /* rfc2338.6.4.2 */
+#define VRRP_STATE_MAST                3       /* rfc2338.6.4.3 */
+#define VRRP_STATE_GOTO_MASTER 4       /* internal */
+#define VRRP_STATE_LEAVE_MASTER        5       /* internal */
+#define VRRP_STATE_FAULT       99      /* internal */
 
 /* VRRP packet handling */
-#define VRRP_PACKET_OK   0
-#define VRRP_PACKET_KO   1
-#define VRRP_PACKET_DROP 2
-#define VRRP_PACKET_NULL 3
+#define VRRP_PACKET_OK       0
+#define VRRP_PACKET_KO       1
+#define VRRP_PACKET_DROP     2
+#define VRRP_PACKET_NULL     3
+#define VRRP_PACKET_TEMP_LEN 256
 
 #define VRRP_AUTH_LEN  8
 
-#define VRRP_IS_BAD_VID(id) ((id)<1 || (id)>255)       /* rfc2338.6.1.vrid */
-#define VRRP_IS_BAD_PRIORITY(p) ((p)<1 || (p)>255)     /* rfc2338.6.1.prio */
-#define VRRP_IS_BAD_ADVERT_INT(d) ((d)<1)
+#define VRRP_IS_BAD_VID(id)            ((id)<1 || (id)>255)    /* rfc2338.6.1.vrid */
+#define VRRP_IS_BAD_PRIORITY(p)                ((p)<1 || (p)>255)      /* rfc2338.6.1.prio */
+#define VRRP_IS_BAD_ADVERT_INT(d)      ((d)<1)
 
-#define VRRP_TIMER_HZ                  1000000
-#define VRRP_TIMER_SKEW( srv ) ((256-(srv)->priority)*VRRP_TIMER_HZ/256) 
+#define VRRP_TIMER_HZ          1000000
+#define VRRP_TIMER_SKEW(srv)   ((256-(srv)->priority)*VRRP_TIMER_HZ/256) 
 
-#define VRRP_MIN( a , b )      ( (a) < (b) ? (a) : (b) )
-#define VRRP_MAX( a , b )      ( (a) > (b) ? (a) : (b) )
+#define VRRP_MIN(a, b) ((a) < (b)?(a):(b))
+#define VRRP_MAX(a, b) ((a) > (b)?(a):(b))
 
 /* prototypes */
+extern int vrrp_ipsecah_len();
 extern int complete_vrrp_init(vrrp_rt *vsrv);
 extern void vrrp_state_stop_instance(vrrp_rt *vsrv);
 
index 9b792cb..975bfbe 100644 (file)
@@ -8,7 +8,7 @@
  *              master fails, a backup server takes over.
  *              The original implementation has been made by jerome etienne.
  *
- * Version:     $Id: vrrp_ipaddress.c,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: vrrp_ipaddress.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 
 /* local include */
 #include "vrrp_ipaddress.h"
-#include "libnetlink/libnetlink.h"
+#include "vrrp_netlink.h"
 
-static int get_addrinfo(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+int netlink_address_ipv4(int ifindex, uint32_t addr, int cmd)
 {
-  struct ifaddrmsg *ifa = NLMSG_DATA(n);
-  int len = n->nlmsg_len;
-  iplist_ctx *ctx = (iplist_ctx *)arg;
-  struct rtattr *rta_tb[IFA_MAX+1];
-
-  /* sanity check */
-  len -= NLMSG_LENGTH(sizeof(*ifa));
-  if (len < 0) {
-    syslog(LOG_INFO, "IPADDRESS : BUG: wrong nlmsg len %d", len);
-    return -1;
-  }
-
-  /* check the message type */
-  if (n->nlmsg_type != RTM_NEWADDR)
-    return 0;
-  /* check it is ipv4 */
-  if( ifa->ifa_family != AF_INET)
-    return 0;
-
-  /* check it is the good interface */
-  if(ifa->ifa_index != ctx->ifindex)
-    return 0;
-    
-  /* parse the attribute */
-  memset(rta_tb, 0, sizeof(rta_tb));
-  parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), len);
-
-  if (!rta_tb[IFA_LOCAL])
-    rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
-
-  if (rta_tb[IFA_LOCAL]) {
-    u_char *src = RTA_DATA(rta_tb[IFA_LOCAL]);
-    if( ctx->nb_elem >= ctx->max_elem )
-      return 0;
-    ctx->addr[ctx->nb_elem++] = (src[0]<<24) + (src[1]<<16) +
-            (src[2]<<8) + src[3];
-  }
-  return 0;
-}
-
-int ipaddr_list( int ifindex, uint32_t *array, int max_elem )
-{
-  struct rtnl_handle  rth;
-  iplist_ctx  ctx;
-
-  /* init the struct */
-  ctx.ifindex  = ifindex;
-  ctx.addr  = array;
-  ctx.max_elem  = max_elem;
-  ctx.nb_elem  = 0;
-
-  /* open the rtnetlink socket */
-  if( rtnl_open( &rth, 0) )
-    return -1;
-
-  /* send the request */
-  if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETADDR) < 0) {
-    syslog(LOG_INFO, "IPADDRESS : Cannot send dump request");
-    return -1;
-  }
-
-  /* parse the answer */
-  if (rtnl_dump_filter(&rth, get_addrinfo, &ctx, NULL, NULL) < 0) {
-    syslog(LOG_INFO, "IPADDRESS : Flush terminated");
-    exit(1);
-  }
-  
-  /* to close the clocket */
-   rtnl_close(&rth);
-  
-  return ctx.nb_elem;
-}
-
-int ipaddr_op(int ifindex, uint32_t addr, int addF)
-{
-  struct rtnl_handle  rth;
+  struct nl_handle nlh;
   struct {
-    struct nlmsghdr   n;
-    struct ifaddrmsg   ifa;
-    char         buf[256];
+    struct nlmsghdr n;
+    struct ifaddrmsg ifa;
+    char buf[256];
   } req;
 
   memset(&req, 0, sizeof(req));
 
   req.n.nlmsg_len    = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
   req.n.nlmsg_flags  = NLM_F_REQUEST;
-  req.n.nlmsg_type   = addF ? RTM_NEWADDR : RTM_DELADDR;
+  req.n.nlmsg_type   = cmd ? RTM_NEWADDR:RTM_DELADDR;
   req.ifa.ifa_family = AF_INET;
   req.ifa.ifa_index  = ifindex;
   req.ifa.ifa_prefixlen  = 32;
@@ -123,14 +48,14 @@ int ipaddr_op(int ifindex, uint32_t addr, int addF)
   addr = htonl(addr);
   addattr_l(&req.n, sizeof(req), IFA_LOCAL, &addr, sizeof(addr));
 
-  if (rtnl_open(&rth, 0) < 0)
+  if (netlink_socket(&nlh, 0) < 0)
     return -1;
-  if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
+
+  if (netlink_talk(&nlh, &req.n) < 0)
     return -1;
   
   /* to close the clocket */
-   rtnl_close( &rth );
+  netlink_close(&nlh);
 
   return(0);
 }
-
index e84c713..2abc17c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_ipaddress.c include file.
  *
- * Version:     $Id: vrrp_ipaddress.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: vrrp_ipaddress.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include <string.h>
 #include <syslog.h>
 
-/* types definitions */
-typedef struct {
-  int    ifindex;
-  uint32_t  *addr;
-  int    max_elem;
-  int    nb_elem;
-} iplist_ctx;
+/* types definition */
+#define VRRP_IPADDRESS_DEL 0
+#define VRRP_IPADDRESS_ADD 1
 
 /* prototypes */
-int ipaddr_list(int ifindex, uint32_t *array, int max_elem);
-int ipaddr_op(int ifindex, uint32_t addr, int addF);
+extern int netlink_address_ipv4(int ifindex, uint32_t addr, int cmd);
+
 #endif
 
diff --git a/vrrp_iproute.c b/vrrp_iproute.c
deleted file mode 100644 (file)
index 9c9f23e..0000000
+++ /dev/null
@@ -1,280 +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:        Routing utilities using the NETLINK kernel interface.
- *
- * Version:     $Id: vrrp_iproute.c,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
- *
- * Author:      Alexandre Cassen, <acassen@linux-vs.org>
- *
- *              This program is distributed in the hope that it will be useful,
- *              but WITHOUT ANY WARRANTY; without even the implied warranty of
- *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *              See the GNU General Public License for more details.
- *
- *              This program is free software; you can redistribute it and/or
- *              modify it under the terms of the GNU General Public License
- *              as published by the Free Software Foundation; either version
- *              2 of the License, or (at your option) any later version.
- */
-
-/* local includes */
-#include "vrrp_iproute.h"
-#include "libnetlink/libnetlink.h"
-#include "libnetlink/ll_map.h"
-#include "utils.h"
-
-/* Allocation function */
-struct rt_entry * iproute_new()
-{
-  struct rt_entry *entry;
-
-  entry = (struct rt_entry *)malloc(sizeof(struct rt_entry));
-  memset(entry, 0, sizeof(struct rt_entry));
-
-  entry->rtm = (struct rtmsg *)malloc(sizeof(struct rtmsg));
-  memset(entry->rtm, 0, sizeof(struct rtmsg));
-
-  return entry;
-}
-
-/* free memory */
-void iproute_del(struct rt_entry *entry)
-{
-  free(entry->rtm);
-  free(entry);
-}
-
-/* destroy functions */
-struct rt_entry * clear_entry(struct rt_entry *entry)
-{
-  struct rt_entry *t;
-
-  t = (struct rt_entry *)entry->next;
-  iproute_del(entry);
-  return t;
-}
-
-void iproute_clear(struct rt_entry *lstentry)
-{
-  while (lstentry)
-    lstentry = clear_entry(lstentry);
-}
-
-/* Append rt entry function */
-struct rt_entry * iproute_append(struct rt_entry *lstentry, struct rt_entry *entry)
-{
-  struct rt_entry *ptr = lstentry;
-
-  if (lstentry) {
-    while (lstentry->next) lstentry = (struct rt_entry *)lstentry->next;
-    lstentry->next = (struct rt_entry *)entry;
-    return ptr;
-  } else {
-    lstentry = entry;
-    return lstentry;
-  }
-}
-
-/* Our rt netlink filter */
-int iproute_filter(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
-{
-  struct rt_entry *rtarg;
-  struct rtmsg *r = NLMSG_DATA(n);
-  int len = n->nlmsg_len;
-  struct rtattr *tb[RTA_MAX+1];
-  struct rt_entry *entry;
-
-  rtarg = (struct rt_entry *)arg;
-
-  /* Just lookup the Main routing table */
-  if (r->rtm_table != RT_TABLE_MAIN)
-    return 0;
-
-  /* init len value  */
-  len -= NLMSG_LENGTH(sizeof(*r));
-  if (len <0) {
-    syslog(LOG_INFO, "IPROUTE : BUG: wrong nlmsg len %d", len);
-    return -1;
-  }
-
-  /* init the parse attribute space */
-  memset(tb, 0, sizeof(tb));
-  parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
-
-  /*
-   * we return from filter when route is
-   * cloned from another route, learn by an
-   * ICMP redirect or set by kernel.
-   * Return too when rt type != gateway or direct route.
-   */
-  if (r->rtm_flags & RTM_F_CLONED)
-    return 0;
-  if (r->rtm_protocol == RTPROT_REDIRECT)
-    return 0;
-  if (r->rtm_protocol == RTPROT_KERNEL)
-    return 0;
-  if (r->rtm_type != RTN_UNICAST)
-    return 0;
-
-  if (tb[RTA_OIF]) {
-    /* alloc new memory entry */
-    entry = iproute_new();
-
-    /* copy the rtmsg infos */
-    memcpy(entry->rtm, r, sizeof(struct rtmsg));
-
-    /*
-     * can use RTA_PAYLOAD(tb[RTA_SRC])
-     * but ipv4 addr are 4 bytes coded
-     */
-    entry->oif = *(int *) RTA_DATA(tb[RTA_OIF]);
-    if (tb[RTA_SRC]) memcpy(&entry->src, RTA_DATA(tb[RTA_SRC]), 4);
-    if (tb[RTA_PREFSRC]) memcpy(&entry->psrc, RTA_DATA(tb[RTA_PREFSRC]), 4);
-    if (tb[RTA_DST]) memcpy(&entry->dest, RTA_DATA(tb[RTA_DST]), 4);
-    if (tb[RTA_GATEWAY]) memcpy(&entry->gate, RTA_DATA(tb[RTA_GATEWAY]), 4);
-    if (tb[RTA_FLOW]) memcpy(&entry->flow, RTA_DATA(tb[RTA_FLOW]), 4);
-    if (tb[RTA_IIF]) entry->iif = *(int *) RTA_DATA(tb[RTA_IIF]);
-    if (tb[RTA_PRIORITY]) entry->prio = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
-    if (tb[RTA_METRICS]) entry->metrics = *(int *) RTA_DATA(tb[RTA_METRICS]);
-
-    /* save this entry */
-    rtarg = iproute_append(rtarg, entry);
-  }
-
-  return 0;
-}
-
-struct rt_entry * iproute_fetch(struct rt_entry *r)
-{
-  struct rtnl_handle rth;
-
-  if (rtnl_open(&rth, 0) < 0) {
-    syslog(LOG_INFO, "IPROUTE : Can not initialize netlink interface...");
-    return NULL;
-  }
-
-  ll_init_map(&rth);
-
-  if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETROUTE) < 0) {
-    syslog(LOG_INFO, "IPROUTE : Cannot send dump request.");
-    close(rth.fd);
-    return NULL;
-  }
-
-  if (rtnl_dump_filter(&rth, iproute_filter, r, NULL, NULL) < 0) {
-    syslog(LOG_INFO, "IPROUTE : Dump terminated.");
-    close(rth.fd);
-    return NULL;
-  }
-
-  close(rth.fd);
-  return r;
-}
-
-int iproute_restore_entry(struct rt_entry *r)
-{
-  struct rtnl_handle rth;
-
-  struct {
-    struct nlmsghdr n;
-    struct rtmsg r;
-    char buf[1024];
-  } req;
-
-  memset(&req, 0, sizeof(req));
-
-  req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
-  req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
-  req.n.nlmsg_type = RTM_NEWROUTE;
-
-  memcpy(&req.r, r->rtm, sizeof(struct rtmsg));
-
-  if (r->src)
-    addattr_l(&req.n, sizeof(req), RTA_SRC, &r->src, 4);
-  if (r->psrc)
-    addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &r->psrc, 4);
-  if (r->dest)
-    addattr_l(&req.n, sizeof(req), RTA_DST, &r->dest, 4);
-  if (r->gate)
-    addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &r->gate, 4);
-  if (r->flow)
-    addattr_l(&req.n, sizeof(req), RTA_FLOW, &r->flow, 4);
-
-  if (r->oif)
-    addattr32(&req.n, sizeof(req), RTA_OIF, r->oif);
-  if (r->iif)
-    addattr32(&req.n, sizeof(req), RTA_IIF, r->iif);
-  if (r->prio)
-    addattr32(&req.n, sizeof(req), RTA_PRIORITY, r->prio);
-  if (r->metrics)
-    addattr32(&req.n, sizeof(req), RTA_METRICS, r->metrics);
-
-  if (rtnl_open(&rth, 0) < 0) {
-    syslog(LOG_INFO, "IPROUTE : Can not initialize netlink interface...");
-    return -1;
-  }
-
-  if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) {
-    syslog(LOG_INFO, "IPROUTE : Can not talk with netlink interface...");
-    return -1;
-  }
-
-  return 0;
-}
-
-/* rt netlink dump function */
-void iproute_dump(struct rt_entry *r)
-{
-  while (r) {
-    if (r->src) syslog(LOG_DEBUG, "src %s ", ip_ntoa(r->src));
-    if (r->psrc) syslog(LOG_DEBUG, "prefsrc %s ", ip_ntoa(r->psrc));
-    if (r->iif) syslog(LOG_DEBUG, "idev %s", ll_index_to_name(r->iif));
-
-    if (r->dest) syslog(LOG_DEBUG, "dest %s ", ip_ntoa(r->dest));
-    if (r->gate) syslog(LOG_DEBUG, "gateway %s ", ip_ntoa(r->gate));
-
-    if (r->prio) syslog(LOG_DEBUG, "priority %d ", r->prio);
-    if (r->metrics) syslog(LOG_DEBUG, "metrics %d ", r->metrics);
-
-    if (r->oif) syslog(LOG_DEBUG, "odev %s ", ll_index_to_name(r->oif));
-
-    /* rtmsg specifics */
-    if (r->rtm->rtm_dst_len) syslog(LOG_DEBUG, "mask %d ", r->rtm->rtm_dst_len);
-    if (r->rtm->rtm_scope == RT_SCOPE_LINK) syslog(LOG_DEBUG, "scope link");
-
-    printf("\n");
-
-    r = (struct rt_entry *)r->next;
-  }
-}
-
-struct rt_entry *iproute_list(char *dev)
-{
-  struct rt_entry rt_table;
-
-  /* Fetch the main routing table */
-  memset(&rt_table, 0, sizeof(struct rt_entry));
-  if (!iproute_fetch(&rt_table)) return NULL;
-
-  return rt_table.next;
-}
-
-int iproute_restore(struct rt_entry *lstentry, char *dev)
-{
-  int idx = ll_name_to_index(dev);
-  int ret = 0;
-
-  while (lstentry) {
-    if (lstentry->oif == idx) {
-      ret = iproute_restore_entry(lstentry);
-      if (ret < 0) return ret;
-    }
-
-    lstentry = (struct rt_entry *)lstentry->next;
-  }
-
-  return 0;
-}
index d1efd1e..39f77a5 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.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: vrrp_ipsecah.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 6c95571..eca257b 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_ipsecah.c include file.
  * 
- * Version:     $Id: vrrp_ipsecah.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: vrrp_ipsecah.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
diff --git a/vrrp_netlink.c b/vrrp_netlink.c
new file mode 100644 (file)
index 0000000..d65e45e
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        NETLINK kernel command channel.
+ *
+ * Version:     $Id: vrrp_netlink.c,v 0.4.8 2001/11/20 15:26: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.
+ */
+
+/* local include */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <net/if_arp.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/uio.h>
+
+#include "vrrp_netlink.h"
+
+/* Create a socket to netlink interface */
+int netlink_socket(struct nl_handle *nl, unsigned long groups)
+{
+  int addr_len;
+  int ret;
+
+  memset(nl, 0, sizeof(nl));
+
+  nl->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+  if (nl->fd < 0) {
+    syslog(LOG_INFO, "Netlink: Cannot open netlink socket : (%s)"
+                   , strerror(errno));
+    return -1;
+  }
+
+  ret = fcntl(nl->fd, F_SETFL, O_NONBLOCK);
+  if (ret < 0) {
+    syslog(LOG_INFO, "Netlink: Cannot set netlink socket flags : (%s)"
+                   , strerror(errno));
+    close(nl->fd);
+    return -1;
+  }
+
+  memset(&nl->snl, 0, sizeof(nl->snl));
+  nl->snl.nl_family = AF_NETLINK;
+  nl->snl.nl_groups = groups;
+
+  ret = bind(nl->fd, (struct sockaddr*)&nl->snl, sizeof(nl->snl));
+  if (ret < 0) {
+    syslog(LOG_INFO, "Netlink: Cannot bind netlink socket : (%s)"
+                   , strerror(errno));
+    close(nl->fd);
+    return -1;
+  }
+
+  addr_len = sizeof(nl->snl);
+  ret = getsockname(nl->fd, (struct sockaddr *)&nl->snl, &addr_len);
+  if (ret < 0 || addr_len != sizeof(nl->snl)) {
+    syslog(LOG_INFO, "Netlink: Cannot getsockname : (%s)"
+                   , strerror(errno));
+    close(nl->fd);
+    return -1;
+  }
+
+  if (nl->snl.nl_family != AF_NETLINK) {
+    syslog(LOG_INFO, "Netlink: Wrong address family %d", nl->snl.nl_family);
+    close(nl->fd);
+    return -1;
+  }
+
+  nl->seq = time(NULL);
+
+  return ret;
+}
+
+/* Close a netlink socket */
+int netlink_close(struct nl_handle *nl)
+{
+  close(nl->fd);
+  return 0;
+}
+
+/* iproute2 utility function */
+int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
+{
+  int len = RTA_LENGTH(alen);
+  struct rtattr *rta;
+
+  if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
+    return -1;
+
+  rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len));
+  rta->rta_type = type;
+  rta->rta_len = len;
+  memcpy(RTA_DATA(rta), data, alen);
+  n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
+
+  return 0;
+}
+
+/* Our netlink parser */
+static int netlink_parse_info(int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
+                              struct nl_handle *nl)
+{
+  int status;
+  int ret = 0;
+  int error;
+
+  while (1) {
+    char buf[4096];
+    struct iovec iov = { buf, sizeof buf };
+    struct sockaddr_nl snl;
+    struct msghdr msg = {(void*)&snl, sizeof snl, &iov, 1, NULL, 0, 0};
+    struct nlmsghdr *h;
+
+    status = recvmsg (nl->fd, &msg, 0);
+
+    if (status < 0) {
+      if (errno == EINTR)
+        continue;
+      if (errno == EWOULDBLOCK)
+        break;
+      syslog(LOG_INFO, "Netlink: Received message overrun");
+      continue;
+    }
+
+    if (status == 0) {
+      syslog(LOG_INFO, "Netlink: EOF");
+      return -1;
+    }
+
+    if (msg.msg_namelen != sizeof snl) {
+      syslog(LOG_INFO, "Netlink: Sender address length error: length %d"
+                     , msg.msg_namelen);
+      return -1;
+    }
+
+    for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, status);
+         h = NLMSG_NEXT (h, status)) {
+      /* Finish of reading. */
+      if (h->nlmsg_type == NLMSG_DONE)
+        return ret;
+
+      /* Error handling. */
+      if (h->nlmsg_type == NLMSG_ERROR) {
+        struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
+        if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr))) {
+          syslog(LOG_INFO, "Netlink: error: message truncated");
+          return -1;
+        }
+        syslog (LOG_INFO, "Netlink: error: %s, type=(%u), seq=%u, pid=%d"
+                        , strerror (-err->error)
+                        , err->msg.nlmsg_type, err->msg.nlmsg_seq
+                        , err->msg.nlmsg_pid);
+
+        return -1;
+      }
+
+      error = (*filter) (&snl, h);
+      if (error < 0) {
+        syslog(LOG_INFO, "Netlink: filter function error");
+        ret = error;
+      }
+    }
+
+    /* After error care. */
+    if (msg.msg_flags & MSG_TRUNC) {
+      syslog(LOG_INFO, "Netlink: error: message truncated");
+      continue;
+    }
+    if (status) {
+      syslog(LOG_INFO, "Netlink: error: data remnant size %d", status);
+      return -1;
+    }
+  }
+
+  return ret;
+}
+
+/* Out talk filter */
+static int netlink_talk_filter(struct sockaddr_nl *snl, struct nlmsghdr *h)
+{
+  syslog(LOG_INFO, "Netlink: ignoring message type 0x%04x"
+                 , h->nlmsg_type);
+  return 0;
+}
+
+/* send message to netlink kernel socket, then receive response */
+int netlink_talk(struct nl_handle *nl, struct nlmsghdr *n)
+{
+  int status;
+  struct sockaddr_nl snl;
+  struct iovec iov = { (void*) n, n->nlmsg_len };
+  struct msghdr msg = {(void*) &snl, sizeof snl, &iov, 1, NULL, 0, 0};
+
+  memset(&snl, 0, sizeof snl);
+  snl.nl_family = AF_NETLINK;
+
+  n->nlmsg_seq = ++nl->seq;
+
+  /* Send message to netlink interface. */
+  status = sendmsg(nl->fd, &msg, 0);
+  if (status < 0) {
+    syslog(LOG_INFO, "Netlink: sendmsg() error: %s"
+                   , strerror (errno));
+    return -1;
+  }
+
+  status = netlink_parse_info(netlink_talk_filter, nl);
+  return status;
+}
similarity index 53%
rename from vrrp_iproute.h
rename to vrrp_netlink.h
index 1ae9e7c..e5e5a88 100644 (file)
@@ -3,9 +3,9 @@
  *              <www.linuxvirtualserver.org>. It monitor & manipulate
  *              a loadbalanced server pool using multi-layer checks.
  *
- * Part:        vrrp_iproute.c include file.
+ * Part:        vrrp_netlink.c include file.
  *
- * Version:     $Id: vrrp_iproute.h,v 0.4.1 2001/09/14 00:37:56 acassen Exp $
+ * Version:     $Id: vrrp_netlink.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
  *              but WITHOUT ANY WARRANTY; without even the implied warranty of
  *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  *              See the GNU General Public License for more details.
- *
+ *              
  *              This program is free software; you can redistribute it and/or
  *              modify it under the terms of the GNU General Public License
  *              as published by the Free Software Foundation; either version
  *              2 of the License, or (at your option) any later version.
  */
 
-#ifndef _VRRP_IPROUTE_H
-#define _VRRP_IPROUTE_H
-
-/* global includes */
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <syslog.h>
-
-/* specify a routing entry */
-struct rt_entry {
-  struct rtmsg *rtm;
+#ifndef _VRRP_NETLINK_H
+#define _VRRP_NETLINK_H 1
 
-  uint32_t psrc;
-  uint32_t src;
-  uint32_t dest;
-  uint32_t gate;
-  uint32_t flow;
-  int iif;
-  int oif;
-  int prio;
-  int metrics;
+/* Hack for GNU libc version 2. */
+#ifndef MSG_TRUNC
+#define MSG_TRUNC      0x20
+#endif /* MSG_TRUNC */
 
-  struct rt_entry *next;
+/* global includes */
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+/* types definitions */
+struct nl_handle {
+  int fd;
+  struct sockaddr_nl snl;
+  __u32 seq;
 };
 
 /* prototypes */
-
-extern struct rt_entry *iproute_fetch(struct rt_entry *r);
-extern void iproute_dump(struct rt_entry *r);
-extern void iproute_clear(struct rt_entry *lstentry);
-extern int iproute_restore(struct rt_entry *lstentry, char *dev);
-extern struct rt_entry *iproute_list(char *dev);
+extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen);
+extern int netlink_socket(struct nl_handle *nl, unsigned long groups);
+extern int netlink_close(struct nl_handle *nl);
+extern int netlink_talk (struct nl_handle *nl, struct nlmsghdr *n);
 
 #endif
diff --git a/vrrp_scheduler.c b/vrrp_scheduler.c
new file mode 100644 (file)
index 0000000..867cabd
--- /dev/null
@@ -0,0 +1,634 @@
+/*
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        Sheduling framework for vrrp code.
+ *
+ * Version:     $Id: vrrp_scheduler.c,v 0.4.8 2001/11/20 15:26: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 "vrrp_scheduler.h"
+#include "vrrp_ipsecah.h"
+#include "vrrp.h"
+
+/*
+ * Initialize state handling
+ * --rfc2338.6.4.1
+ */
+static void vrrp_init_state(vrrp_instance *instance)
+{
+  vrrp_instance *vrrpptr = instance;
+
+  while (instance) {
+    if (instance->vsrv->priority == VRRP_PRIO_OWNER ||
+        instance->vsrv->wantstate == VRRP_STATE_MAST) {
+      instance->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;
+    }
+
+    instance = (vrrp_instance *)instance->next;
+  }
+  instance = vrrpptr;
+}
+
+static void vrrp_init_instance_sands(vrrp_instance *instance)
+{
+  struct timeval timer_now;
+
+  gettimeofday(&timer_now, NULL);
+
+  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 (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;
+  }
+}
+
+static void vrrp_init_sands(vrrp_instance *instance)
+{
+  vrrp_instance *vrrpptr = instance;
+
+  while (instance) {
+    vrrp_init_instance_sands(instance);
+
+    instance = (vrrp_instance *)instance->next;
+  }
+  instance = vrrpptr;
+}
+
+/* Timer functions */
+static struct timeval vrrp_compute_timer(const int fd, vrrp_instance *vrrp)
+{
+  vrrp_instance *ptr = vrrp;
+  struct timeval timer;
+
+  /* clean the memory */
+  memset(&timer, 0, sizeof(struct timeval));
+
+  while (vrrp) {
+    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;
+      }
+    }
+
+    vrrp = (vrrp_instance *)vrrp->next;
+  }
+  vrrp = ptr;
+
+  return timer;
+}
+
+static struct timeval vrrp_timer_delta(struct timeval timer)
+{
+  struct 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)
+{
+  struct timeval timer;
+  long vrrp_timer = 0;
+
+  timer = vrrp_compute_timer(fd, instance);
+  timer = vrrp_timer_delta(timer);
+  vrrp_timer = timer.tv_sec * VRRP_TIMER_HZ + timer.tv_usec;
+
+  return vrrp_timer;
+}
+
+static int vrrp_timer_vrid_timeout(const int fd, vrrp_instance *vrrp)
+{
+  vrrp_instance *ptr = vrrp;
+  struct timeval vrrp_timer;
+  int vrid = 0;
+
+  /* clean the memory */
+  memset(&vrrp_timer, 0, sizeof(struct timeval));
+  vrrp_timer = vrrp_compute_timer(fd, vrrp);
+
+  while (vrrp) {
+    if (thread_timer_cmp(vrrp->vsrv->sands, vrrp_timer) == 0)
+      vrid = vrrp->vsrv->vrid;
+
+    vrrp = (vrrp_instance *)vrrp->next;
+  }
+  vrrp = ptr;
+
+  return vrid;
+}
+
+/* Simple dump function
+static void vrrp_timer_dump(vrrp_instance *vrrp)
+{
+  vrrp_instance *ptr = vrrp;
+  struct timeval timer_now;
+  struct timeval timer;
+  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;
+    syslog(LOG_DEBUG, "Timer(vrid,value) : (%d,%d)", vrrp->vsrv->vrid, vrrp_timer);
+
+    vrrp = (vrrp_instance *)vrrp->next;
+  }
+  vrrp = ptr;
+}
+*/
+
+/* Thread functions */
+static void vrrp_register_workers(struct thread_master *master,
+                                  vrrp_instance *instance,
+                                  sockpool *pool)
+{
+  sockpool *poolptr = pool;
+  struct timeval timer;
+  long vrrp_timer = 0;
+
+  /* init compute timer */
+  memset(&timer, 0, sizeof(struct timeval));
+
+  /* Init the VRRP instances state */
+  vrrp_init_state(instance);
+
+  /* Init VRRP instances sands */
+  vrrp_init_sands(instance);
+
+  while (pool) {
+    /* 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;
+  }
+  pool = poolptr;
+}
+
+/* VRRP dispatcher functions */
+static int already_exist_sock(sockpool *lstptr, int ifindex, int proto)
+{
+  sockpool *ptrpool = lstptr;
+
+  while (lstptr) {
+    if ((lstptr->ifindex == ifindex) && (lstptr->proto == proto)) {
+      lstptr = ptrpool;
+      return 1;
+    }
+    lstptr = (sockpool *)lstptr->next;
+  }
+  lstptr = ptrpool;
+  return 0;
+}
+
+static sockpool *add_sock(sockpool *lstsock, sockpool *sock)
+{
+  sockpool *ptrpool = lstsock;
+
+  if (lstsock) {
+    while (lstsock->next) lstsock = (sockpool *)lstsock->next;
+    lstsock->next = (struct sockpool *)sock;
+    return ptrpool;
+  } else {
+    lstsock = sock;
+    return lstsock;
+  }
+}
+
+static sockpool *remove_sock(sockpool *pool)
+{
+  sockpool *t;
+
+  t = (sockpool *)pool->next;
+  free(pool);
+  return t;
+}
+
+static void clear_sockpool(sockpool *pool)
+{
+  while (pool)
+    pool = remove_sock(pool);
+}
+
+static sockpool *vrrp_create_sockpool(vrrp_instance *instance, sockpool *pool)
+{
+  vrrp_instance *ptr = instance;
+  sockpool *sock;
+  int ifindex;
+  int proto;
+
+  while (instance) {
+    ifindex = ifname_to_idx(instance->vsrv->vif->ifname);
+    if (instance->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));
+      memset(sock, 0, sizeof(sockpool));
+
+      /* fill in the new sock structure */
+      sock->ifindex = ifindex;
+      sock->proto = proto;
+      pool = add_sock(pool, sock);
+    }
+
+    instance = (vrrp_instance *)instance->next;
+  }
+
+  instance = ptr;
+  return pool;
+}
+
+static void vrrp_open_sockpool(sockpool *pool)
+{
+  sockpool *ptr = pool;
+
+  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;
+  }
+  pool = ptr;
+}
+
+static void vrrp_set_fds(vrrp_instance *instance, sockpool *pool)
+{
+  sockpool *ptr = pool;
+  vrrp_instance *ptrvrrp = instance;
+  int proto;
+
+  while (pool) {
+    while (instance) {
+      if (instance->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;
+    }
+    instance = ptrvrrp;
+
+    pool = (sockpool *)pool->next;
+  }
+  pool = ptr;
+}
+
+/*
+ * We create & allocate a socket pool here. The soft design
+ * can be sum up by the following sketch :
+ *
+ *    fd1  fd2    fd3  fd4          fdi  fdi+1
+ * -----\__/--------\__/---........---\__/---
+ *    | ETH0 |    | ETH1 |          | ETHn |
+ *    +------+    +------+          +------+
+ *
+ * Here we have n physical NIC. Each NIC own a maximum of 2 fds.
+ * (one for VRRP the other for IPSEC_AH). All our VRRP instances
+ * are multiplexed through this fds. So our design can handle 2*n
+ * multiplexing points.
+ */
+int vrrp_dispatcher_init_thread(struct thread *thread)
+{
+  vrrp_instance *instance = THREAD_ARG(thread);
+  sockpool *pool;
+
+  /* init */
+  pool = NULL;
+
+  /* create the VRRP socket pool list */
+  pool = vrrp_create_sockpool(instance, pool);
+
+  /* open the VRRP socket pool */
+  vrrp_open_sockpool(pool);
+
+  /* set VRRP instance fds to sockpool */
+  vrrp_set_fds(instance, pool);
+
+  /* register read dispatcher worker thread */
+  vrrp_register_workers(thread->master, instance, pool);
+
+  /* cleanup the temp socket pool */
+  clear_sockpool(pool);
+
+  return 0;
+}
+
+static vrrp_instance *vrrp_search_instance_isync(char *isync, vrrp_instance *instance)
+{
+  while (instance) {
+    if (strcmp(instance->iname, isync) == 0) /* FIXME: handle buffer overflow */
+      return instance;
+    instance = (vrrp_instance *)instance->next;
+  }
+
+  return NULL;
+}
+
+static vrrp_instance *vrrp_search_instance(const int vrid, vrrp_instance *instance)
+{
+  while (instance) {
+    if (instance->vsrv->vrid == vrid)
+      return instance;
+    instance = (vrrp_instance *)instance->next;
+  }
+
+  return NULL;
+}
+
+static void vrrp_handle_backup(vrrp_instance *instance,
+                               char *vrrp_buffer,
+                               int len)
+{
+  vrrp_state_backup(instance, vrrp_buffer, len);
+}
+
+static void vrrp_handle_become_master(vrrp_instance *instance,
+                                     char *vrrp_buffer,
+                                     int len)
+{
+  vrrp_rt *vsrv = instance->vsrv;
+  struct iphdr *iph = (struct iphdr *)vrrp_buffer;
+  ipsec_ah *ah;
+
+  /*
+   * If we are in IPSEC AH mode, we must be sync
+   * with the remote IPSEC AH VRRP instance counter.
+   */
+  if (iph->protocol == IPPROTO_IPSEC_AH) {
+    ah = (ipsec_ah *)(vrrp_buffer + sizeof(struct iphdr));
+    vsrv->ipsecah_counter->seq_number = ah->seq_number + 1;
+    vsrv->ipsecah_counter->cycle = 0;
+  }
+}
+
+static void vrrp_handle_leave_master(vrrp_instance *instance,
+                                     char *vrrp_buffer,
+                                     int len)
+{
+  if (vrrp_state_master_rx(instance, vrrp_buffer, len)) {
+    syslog(LOG_INFO, "VRRP_Instance(%s) Received higher prio advert"
+                    , instance->iname);
+    vrrp_state_leave_master(instance);
+  }
+}
+
+static int vrrp_handle_state(vrrp_instance *instance,
+                             char *vrrp_buffer,
+                             int len)
+{
+  int previous_state;
+
+  previous_state = instance->vsrv->state;
+
+  switch (instance->vsrv->state) {
+    case VRRP_STATE_BACK:
+      vrrp_handle_backup(instance, vrrp_buffer, len);
+      break;
+    case VRRP_STATE_GOTO_MASTER:
+      vrrp_handle_become_master(instance, vrrp_buffer, len);
+      break;
+    case VRRP_STATE_MAST:
+      vrrp_handle_leave_master(instance, vrrp_buffer, len);
+      break;
+  }
+
+  return previous_state;
+}
+
+static void vrrp_handle_goto_master(vrrp_instance *instance)
+{
+  vrrp_rt *vsrv = instance->vsrv;
+
+  /* If becoming MASTER in IPSEC AH AUTH, we reset the anti-replay */
+  if (vsrv->ipsecah_counter->cycle) {
+    vsrv->ipsecah_counter->cycle = 0;
+    vsrv->ipsecah_counter->seq_number = 0;
+  }
+
+  vsrv->state = VRRP_STATE_BACK;
+  vsrv->wantstate = VRRP_STATE_MAST;
+
+  /* handle master state transition */
+  vrrp_state_goto_master(instance);
+}
+
+static void vrrp_handle_master(vrrp_instance *instance)
+{
+  vrrp_rt *vsrv = instance->vsrv;
+
+  if (vsrv->wantstate == VRRP_STATE_BACK ||
+      vsrv->ipsecah_counter->cycle) {
+    vsrv->ms_down_timer = 3 * vsrv->adver_int + VRRP_TIMER_SKEW(vsrv);
+
+    /* handle backup state transition */
+    vsrv->state = VRRP_STATE_BACK;
+    vrrp_state_leave_master(instance);
+
+    syslog(LOG_INFO, "VRRP_Instance(%s) Becoming BACKUP"
+                   , instance->iname);
+  } else {
+    /* send the VRRP advert */
+    vrrp_state_master_tx(instance, 0);
+  }
+}
+
+static int vrrp_handle_state_timeout(vrrp_instance *instance)
+{
+  int previous_state;
+
+  previous_state = instance->vsrv->state;
+
+  switch (instance->vsrv->state) {
+    case VRRP_STATE_BACK:
+      vrrp_handle_goto_master(instance);
+      break;
+    case VRRP_STATE_GOTO_MASTER:
+      vrrp_handle_goto_master(instance);
+      break;
+    case VRRP_STATE_MAST:
+      vrrp_handle_master(instance);
+      break;
+    case VRRP_STATE_FAULT:
+      vrrp_handle_master(instance);
+      break;
+  }
+
+  return previous_state;
+}
+
+/* Our read packet dispatcher */
+int vrrp_read_dispatcher_thread(struct thread *thread)
+{
+  vrrp_instance *instance = THREAD_ARG(thread);
+  vrrp_instance *ptr = instance;
+  vrrp_instance *vrrp_isync;
+  vrrp_instance *vrrp_instance;
+  long vrrp_timer = 0;
+  char *vrrp_buffer;
+  struct iphdr *iph;
+  vrrp_pkt *hd;
+  int len = 0;
+  int vrid = 0;
+  int previous_state = 0;
+
+  if (thread->type == THREAD_READ_TIMEOUT) {
+
+    /* Searching for matching instance */
+    vrid = vrrp_timer_vrid_timeout(thread->u.fd, instance);
+    vrrp_instance = vrrp_search_instance(vrid, instance);
+    instance = ptr;
+
+// syslog(LOG_DEBUG, "Dispatcher timeout on (fd,vrid) : (%d,%d)", thread->u.fd, 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 (vrrp_isync->vsrv->state == VRRP_STATE_BACK) {
+        syslog(LOG_INFO, "VRRP_Instance(%s) must be sync with %s"
+                        , vrrp_instance->iname
+                        , vrrp_isync->iname);
+
+        /* Send the higher priority advert */
+        syslog(LOG_INFO, "VRRP_Instance(%s) sending OWNER advert"
+                        , vrrp_isync->iname);
+        vrrp_state_master_tx(vrrp_isync, VRRP_PRIO_OWNER);
+      } else {
+        /* Otherwise, we simply update remotes arp tables */
+        syslog(LOG_INFO, "VRRP_Instance(%s) gratuitous arp on %s"
+                       , vrrp_isync->iname
+                       , vrrp_isync->vsrv->vif->ifname);
+        vrrp_isync->vsrv->state = VRRP_STATE_MAST;
+        vrrp_send_gratuitous_arp(vrrp_isync);
+      }
+    }
+
+    /*
+     * We are sure the instance exist. So we can
+     * compute new sands timer safely.
+     */
+    vrrp_init_instance_sands(vrrp_instance);
+
+  } else {
+
+    /* allocate & clean the read buffer */
+    vrrp_buffer = (char *)malloc(VRRP_PACKET_TEMP_LEN);
+    memset(vrrp_buffer, 0, VRRP_PACKET_TEMP_LEN);
+
+    /* read & affect received buffer */
+    len = read(thread->u.fd, vrrp_buffer, VRRP_PACKET_TEMP_LEN);
+    iph = (struct iphdr *)vrrp_buffer;
+
+    switch (iph->protocol) {
+      case IPPROTO_IPSEC_AH:
+        hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2) + vrrp_ipsecah_len());
+        break;
+      case IPPROTO_VRRP:
+        hd  = (vrrp_pkt *)((char *)iph + (iph->ihl<<2));
+        break;
+    }
+
+    /* Searching for matching instance */
+    vrrp_instance = vrrp_search_instance(hd->vrid, instance);
+    instance = ptr;
+
+    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;
+
+        /* synchronized instance probably failed */
+        if (vrrp_isync->vsrv->state == VRRP_STATE_MAST &&
+            vrrp_isync->vsrv->init_state == VRRP_STATE_MAST) {
+          syslog(LOG_INFO, "VRRP_Instance(%s) transition to FAULT state"
+                         , vrrp_instance->iname);
+          vrrp_isync->vsrv->state = VRRP_STATE_FAULT;
+        } else if (vrrp_isync->vsrv->state == VRRP_STATE_MAST) {
+          syslog(LOG_INFO, "VRRP_Instance(%s) must be sync with %s"
+                         , vrrp_instance->iname
+                         , vrrp_isync->iname);
+
+          /* Transition to BACKUP state */
+          vrrp_isync->vsrv->wantstate = VRRP_STATE_BACK;
+        }
+      }
+
+      /*
+       * Refresh sands only if found matching instance.
+       * Otherwize the packet is simply ignored...
+       *
+       * FIXME: Add a dropping packet framework to not
+       *        degrade the instance timer during dropping.
+       */
+      vrrp_init_instance_sands(vrrp_instance);
+    }
+
+    /* cleanup the room */
+    free(vrrp_buffer);
+
+  }
+
+  /* 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);
+
+  return 0;
+}
diff --git a/vrrp_scheduler.h b/vrrp_scheduler.h
new file mode 100644 (file)
index 0000000..d25a8ec
--- /dev/null
@@ -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:        vrrp_scheduler.c include file.
+ * 
+ * Version:     $Id: vrrp_scheduler.h,v 0.4.8 2001/11/20 15:26: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 _VRRP_SCHEDULER_H
+#define _VRRP_SCHEDULER_H
+
+/* system include */
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdint.h>
+
+/* local include */
+#include "scheduler.h"
+
+/*
+ * Our instance dispatcher use a socket pool.
+ * That way we handle VRRP protocole type per
+ * physical interface.
+ */
+typedef struct {
+  int ifindex;
+  int proto;
+  int fd;
+
+  struct sockpool *next;
+} sockpool;
+
+/* extern prototypes */
+extern int open_vrrp_socket(const int proto, const int index);
+extern int ifname_to_idx(const char *ifname);
+extern void vrrp_send_gratuitous_arp(vrrp_instance *vrrp_instance);
+extern int vrrp_read_dispatcher_thread(struct thread *thread);
+extern int vrrp_state_master_rx(vrrp_instance *instance, char *buf, int buflen);
+extern void vrrp_state_master_tx(vrrp_instance *instance, const int prio);
+extern void vrrp_state_backup(vrrp_instance *instance, char *buf, int buflen);
+extern void vrrp_state_goto_master(vrrp_instance *vrrp_instance);
+extern void vrrp_state_leave_master(vrrp_instance *instance);
+
+#endif